FreeBSD ϵͳ½á¹¹ÊÖ²á

The FreeBSD Documentation Project

FreeBSD ÖÐÎļƻ®

¡¡¡¡»¶Ó­ÄúÔĶÁ¡¶FreeBSDϵͳ½á¹¹Êֲᡷ¡£ Õâ±¾ÊֲỹÔÚ²»¶ÏÓÉÐí¶àÈ˼ÌÐøÊéд¡£ Ðí¶àÕ½ڻ¹Êǿհף¬ÓеÄÕÂ½ÚØ½´ý¸üС£ Èç¹ûÄú¶ÔÕâ¸öÏîÄ¿¸ÐÐËȤ²¢Ô¸ÒâÓÐËù¹±Ï×£¬Ç뷢Пø FreeBSD Îĵµ¼Æ»®ÓʼþÁÐ±í¡£

¡¡¡¡ ±¾ÎĵµµÄ×îÐÂÓ¢ÎÄԭʼ°æ±¾¿É´Ó FreeBSD Web Õ¾µã »ñµÃ£¬ ÓÉ FreeBSD ÖÐÎļƻ® ά»¤µÄ×îÐÂÒë±¾¿ÉÒÔÔÚ FreeBSD ÖÐÎļƻ® ¿ìÕÕ Web Õ¾µã ºÍ FreeBSD ÖÐÎļƻ® Îĵµ¿ìÕÕ ´¦»ñµÃ£¬ ÕâÒ»Òë±¾»á²»¶ÏÏòÖ÷վͬ²½¡£ ´ËÍ⣬ ÄúÒ²¿ÉÒÔ´Ó FreeBSD FTP ·þÎñÆ÷ »òÖÚ¶àµÄ ¾µÏñÕ¾µã µÃµ½Õâ·ÝÎĵµµÄ¸÷ÖÖÆäËû¸ñʽÒÔ¼°Ñ¹ËõÐÎʽµÄ°æ±¾¡£

FreeBSDÊÇFreeBSD»ù½ð»áµÄ×¢²áÉ̱ꡣ

UNIXÊÇOpen GroupÔÚÃÀ¹úºÍÆäËü¹ú¼ÒµÄ×¢²áÉ̱ꡣ

Sun, Sun Microsystems, SunOS, Solaris, Java, JDK, ÒÔ¼° OpenJDK ÊÇ Sun Microsystems, Inc. ÔÚÃÀ¹úºÍÆäËü¹ú¼ÒµÄÉ̱ê»ò×¢²áÉ̱ꡣ

Apple and QuickTimeÊÇApple Computer, Inc.µÄÉ̱꣬ ÔÚÃÀ¹úºÍÆäËü¹ú¼Ò×¢²á¡£

Macromedia and FlashÊÇMacromedia, Inc. ÔÚÃÀ¹úºÍ/»òÆäËü¹ú¼ÒµÄÉ̱ê»ò×¢²áÉ̱ꡣ

Microsoft, Windows, and Windows MediaÊÇMicrosoft Corporation ÔÚÃÀ¹úºÍ/»òÆäËü¹ú¼ÒµÄÉ̱ê»ò×¢²áÉ̱ꡣ

PartitionMagicÊÇPowerQuest CorporationÔÚÃÀ¹úºÍ/»òÆäËü¹ú¼ÒµÄ×¢²áÉ̱ꡣ

Ðí¶àÖÆÔìÉ̺;­ÏúÉÌʹÓÃһЩ³ÆÎªÉ̱êµÄͼ°¸»òÎÄ×ÖÉè¼ÆÀ´ÕÃÏÔ×Ô¼ºµÄ²úÆ·¡£ ±¾ÎĵµÖгöÏֵģ¬ Ϊ FreeBSD Project ËùÖªÏþµÄÉ̱꣬ºóÃæ½«ÒÔ '"' »ò '®' ·ûºÅÀ´±ê×¢¡£

ÖØÒª: ±¾ÎÄÖÐÐí¿ÉÖ¤µÄ·Ç¹Ù·½ÖÐÎÄ·­Òë½ö¹©²Î¿¼£¬ ²»×÷ΪÅж¨ÈκÎÔðÈεÄÒÀ¾Ý¡£ÈçÓëÓ¢ÎÄÔ­ÎÄÓгöÈ룬ÔòÒÔÓ¢ÎÄÔ­ÎÄΪ׼¡£

ÔÚÂú×ãÏÂÁÐÐí¿ÉÌõ¼þµÄǰÌáÏ£¬ ÔÊÐíÔÙ·Ö·¢»òÒÔÔ´´úÂë (SGML DocBook) »ò ¡°±àÒ롱 (SGML, HTML, PDF, PostScript, RTF µÈ) µÄ¾­¹ýÐ޸ĻòδÐ޸ĵÄÐÎʽ£º

  1. ÔÙ·Ö·¢Ô´´úÂë (SGML DocBook) ±ØÐë²»¼ÓÐ޸ĵı£ÁôÉÏÊö°æÈ¨¸æÊ¾¡¢ ±¾Ìõ¼þÇåµ¥ºÍÏÂÊöÆúȨÊé×÷Ϊ¸ÃÎļþµÄ×îÏÈÈô¸ÉÐС£

  2. ÔÙ·Ö·¢±àÒëµÄÐÎʽ (ת»»ÎªÆäËüDTD¡¢ PDF¡¢ PostScript¡¢ RTF »òÆäËüÐÎʽ)£¬ ±ØÐ뽫ÉÏÊö°æÈ¨¸æÊ¾¡¢±¾Ìõ¼þÇåµ¥ºÍÏÂÊöÆúȨÊ鏴֯µ½Óë·Ö·¢Æ·Ò»Í¬ÌṩµÄÎļþ£¬ ÒÔ¼°ÆäËü²ÄÁÏÖС£

ÖØÒª: ±¾ÎĵµÓÉ FREEBSD DOCUMENTATION PROJECT ¡°°´ÏÖ×´Ìõ¼þ¡± Ìṩ£¬ ²¢ÔÚ´ËÃ÷ʾ²»ÌṩÈκÎÃ÷ʾ»ò°µÊ¾µÄ±£ÕÏ£¬ °üÀ¨µ«²»ÏÞÓÚ¶ÔÉÌÒµÊÊÏúÐÔ¡¢ ¶ÔÌØ¶¨Ä¿µÄµÄÊÊÓÃÐԵݵʾ±£ÕÏ¡£ ÈκÎÇé¿öÏ£¬ FREEBSD DOCUMENTATION PROJECT ¾ù²»¶ÔÈκÎÖ±½Ó¡¢ ¼ä½Ó¡¢ żȻ¡¢ ÌØÊâ¡¢ ³Í·£ÐԵģ¬ »ò±ØÈ»µÄËðʧ (°üÀ¨µ«²»ÏÞÓÚÌæ´úÉÌÆ·»ò·þÎñµÄ²É¹º¡¢ ʹÓᢠÊý¾Ý»òÀûÒæµÄËðʧ»òÓªÒµÖжÏ) ¸ºÔ𣬠ÎÞÂÛÊÇÈçºÎµ¼ÖµIJ¢ÒÔÈκÎÓÐÔðÈÎÂß¼­µÄ£¬ ÎÞÂÛÊÇ·ñÊÇÔÚ±¾ÎĵµÊ¹ÓÃÒÔÍâÒÔÈκη½Ê½²úÉúµÄÆõÔ¼¡¢ ÑϸñÔðÈλòÊÇÃñÊÂÇÖȨÐÐΪ(°üÀ¨Êèºö»òÆäËü)Öеģ¬ ¼´Ê¹Òѱ»¸æÖª·¢Éú¸ÃËðʧµÄ¿ÉÄÜÐÔ¡£

Redistribution and use in source (SGML DocBook) and 'compiled' forms (SGML, HTML, PDF, PostScript, RTF and so forth) with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code (SGML DocBook) must retain the above copyright notice, this list of conditions and the following disclaimer as the first lines of this file unmodified.

  2. Redistributions in compiled form (transformed to other DTDs, converted to PDF, PostScript, RTF and other formats) must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

ÖØÒª: THIS DOCUMENTATION IS PROVIDED BY THE FREEBSD DOCUMENTATION PROJECT "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD DOCUMENTATION PROJECT BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


Ŀ¼
µÚI²¿·Ö. ÄÚºË
µÚ1Õ¡¡Òýµ¼¹ý³ÌÓëÄں˳õʼ»¯
1.1 ¸ÅÊö
1.2 ×ÜÀÀ
1.3 BIOS POST
1.4 boot0½×¶Î
1.5 boot2½×¶Î
1.6 loader½×¶Î
1.7 Äں˳õʼ»¯
µÚ2Õ¡¡ÄÚºËÖеÄËø
2.1 Mutex
2.2 ¹²Ïí»¥³âËø
2.3 Ô­×Ó±£»¤±äÁ¿
µÚ3Õ¡¡Äں˶ÔÏó
3.1 ÊõÓï
3.2 KobjµÄ¹¤×÷Á÷³Ì
3.3 ʹÓÃKobj
µÚ4Õ¡¡Jail×Óϵͳ
4.1 JailµÄϵͳ½á¹¹
4.2 ϵͳ¶Ô±»Çô½û³ÌÐòµÄÏÞÖÆ
µÚ5Õ¡¡SYSINIT¿ò¼Ü
5.1 ÊõÓï
5.2 SYSINIT²Ù×÷
5.3 ʹÓÃSYSINIT
µÚ6Õ¡¡TrustedBSD MAC ¿ò¼Ü
6.1 MAC Îĵµ°æÈ¨ÉùÃ÷
6.2 ÊõÓï½âÎö
6.3 ¸ÅÊö
6.4 °²È«²ßÂÔ±³¾°ÖªÊ¶
6.5 MAC ¿ò¼ÜµÄÄÚºËÌåϵ½á¹¹
6.6 MAC²ßÂÔÄ£¿éÌåϵ½á¹¹
6.7 MAC²ßÂÔÈë¿Úº¯Êý²Î¿¼
6.8 Ó¦ÓòãÌåϵ½á¹¹
6.9 С½á
µÚ7Õ¡¡ÐéÄâÄÚ´æÏµÍ³
7.1 ÎïÀíÄÚ´æµÄ¹ÜÀí©¤©¤vm_page_t
7.2 ͳһµÄ»º´æÐÅÏ¢½á¹¹Ì婤©¤vm_object_t
7.3 ÎļþϵͳÊäÈë/Êä³ö©¤©¤buf½á¹¹Ìå
7.4 Ó³ÉäÒ³±í©¤©¤vm_map_t, vm_entry_t
7.5 KVM´æ´¢Ó³Éä
7.6 µ÷ÕûFreeBSDµÄÐéÄâÄÚ´æÏµÍ³
µÚ8Õ¡¡SMPng Éè¼ÆÎĵµ
8.1 Ð÷ÂÛ
8.2 »ù±¾¹¤¾ßÓëÉÏËøµÄ»ù´¡ÖªÊ¶
8.3 ¼Ü¹¹ÓëÉè¼Æ¸ÅÀÀ
8.4 ÌØ¶¨Êý¾ÝµÄËø²ßÂÔ
8.5 ʵÏÖ˵Ã÷
8.6 ÆäËü»°Ìâ
ÊõÓï±í
µÚII²¿·Ö. É豸Çý¶¯³ÌÐò
µÚ9Õ¡¡±àд FreeBSD É豸Çý¶¯³ÌÐò
9.1 ¼ò½é
9.2 ¶¯Ì¬ÄÚºËÁ´½Ó¹¤¾ß©¤©¤KLD
9.3 ·ÃÎÊÉ豸Çý¶¯³ÌÐò
9.4 ×Ö·ûÉ豸
9.5 ¿éÉ豸(ÏûÍöÖÐ)
9.6 ÍøÂçÉ豸Çý¶¯³ÌÐò
µÚ10Õ¡¡ISAÉ豸Çý¶¯³ÌÐò
10.1 ¸ÅÊö
10.2 »ù±¾ÐÅÏ¢
10.3 Device_tÖ¸Õë
10.4 ÅäÖÃÎļþÓë×Ô¶¯ÅäÖÃÆÚ¼äʶ±ðºÍ̽²âµÄ˳Ðò
10.5 ×ÊÔ´
10.6 ×ÜÏßÄÚ´æÓ³Éä
10.7 DMA
10.8 xxx_isa_probe
10.9 xxx_isa_attach
10.10 xxx_isa_detach
10.11 xxx_isa_shutdown
10.12 xxx_intr
µÚ11Õ¡¡PCIÉ豸
11.1 ̽²âÓëÁ¬½Ó
11.2 ×ÜÏß×ÊÔ´
µÚ12Õ¡¡Í¨Ó÷ÃÎÊ·½·¨SCSI¿ØÖÆÆ÷
12.1 Ìá¸Ù
12.2 ͨÓûù´¡½á¹¹
12.3 ÂÖѯ
12.4 Ò첽ʼþ
12.5 ÖжÏ
12.6 ´íÎó×ÜÀÀ
12.7 ³¬Ê±´¦Àí
µÚ13Õ¡¡USBÉ豸
13.1 ¼ò½é
13.2 Ö÷¿ØÆ÷
13.3 USBÉ豸ÐÅÏ¢
13.4 É豸µÄ̽²âºÍÁ¬½Ó
13.5 USBÇý¶¯³ÌÐòµÄЭÒéÐÅÏ¢
µÚ14Õ¡¡Newbus
14.1 É豸Çý¶¯³ÌÐò
14.2 Newbus¸ÅÀÀ
14.3 Newbus API
µÚ15Õ¡¡ÉùÒô×Óϵͳ
15.1 ¼ò½é
15.2 Îļþ
15.3 ̽²â£¬Á¬½ÓµÈ
15.4 ½Ó¿Ú
µÚ16Õ¡¡PC Card
16.1 Ìí¼ÓÉ豸
µÚIII²¿·Ö. ¸½Â¼
²Î¿¼ÊéÄ¿
±í¸ñÇåµ¥
±í2-1. MutexÁбí
±í2-2. ¹²Ïí»¥³âËøÁбí
²åͼÇåµ¥
ͼ14-1. driver_tʵÏÖ
ͼ14-2. É豸״̬device_state_t
·¶ÀýÇåµ¥
Àý5-1. SYSINIT()µÄÀý×Ó
Àý5-2. µ÷ÕûSYSINIT()˳ÐòµÄÀý×Ó
Àý5-3. SYSUNINIT()µÄÀý×Ó
Àý9-1. ÊÊÓÃÓÚFreeBSD 4.XµÄ»ØÏÔαÉ豸Çý¶¯³ÌÐòʵÀý
Àý9-2. ÊÊÓÃÓÚFreeBSD 5.X»ØÏÔαÉ豸Çý¶¯³ÌÐòʵÀý
Àý14-1. NewbusµÄ·½·¨

µÚI²¿·Ö. ÄÚºË

Ŀ¼
µÚ1Õ¡¡Òýµ¼¹ý³ÌÓëÄں˳õʼ»¯
µÚ2Õ¡¡ÄÚºËÖеÄËø
µÚ3Õ¡¡Äں˶ÔÏó
µÚ4Õ¡¡Jail×Óϵͳ
µÚ5Õ¡¡SYSINIT¿ò¼Ü
µÚ6Õ¡¡TrustedBSD MAC ¿ò¼Ü
µÚ7Õ¡¡ÐéÄâÄÚ´æÏµÍ³
µÚ8Õ¡¡SMPng Éè¼ÆÎĵµ

µÚ1Õ ¡¡Òýµ¼¹ý³ÌÓëÄں˳õʼ»¯

¹©¸å£ºSergey Lyubka. ·­Ò룺intron@intron.ac.

1.1 ¸ÅÊö

¡¡¡¡ÕâÒ»ÕÂÊǶÔÒýµ¼¹ý³ÌºÍϵͳ³õʼ»¯¹ý³ÌµÄ×ÜÀÀ¡£ÕâЩ¹ý³ÌʼÓÚBIOS(¹Ì¼þ)POST, Ö±µ½µÚÒ»¸öÓû§½ø³Ì½¨Á¢¡£ÓÉÓÚϵͳÆô¶¯µÄ×î³õ²½ÖèÊÇÓëÓ²¼þ½á¹¹Ïà¹ØµÄ¡¢ÊǽôÅäºÏµÄ£¬ ÕâÀïÓÃIA-32(Intel Architecture 32bit)½á¹¹×÷ΪÀý×Ó¡£


1.2 ×ÜÀÀ

¡¡¡¡Ò»Ì¨ÔËÐÐFreeBSDµÄ¼ÆËã»úÓжàÖÖÒýµ¼·½·¨¡£ÕâÀïÌÖÂÛÆäÖÐ×îͨ³£µÄ·½·¨£¬ Ò²¾ÍÊÇ´Ó°²×°Á˲Ù×÷ϵͳµÄÓ²ÅÌÉÏÒýµ¼¡£Òýµ¼¹ý³Ì·Ö¼¸²½Íê³É:

  • BIOS POST

  • boot0½×¶Î

  • boot2½×¶Î

  • loader½×¶Î

  • Äں˳õʼ»¯

¡¡¡¡boot0ºÍboot2½×¶ÎÔÚÊÖ²á boot(8)Öб»³ÆÎªbootstrap stages 1 and 2£¬ ÊÇFreeBSDµÄ3½×¶ÎÒýµ¼¹ý³ÌµÄ¿ªÊ¼¡£ÔÚÿһ½×¶Î¶¼Óи÷ÖÖ¸÷ÑùµÄÐÅÏ¢ÏÔʾÔÚÆÁÄ»ÉÏ£¬ Äã¿ÉÒԲο¼Ï±íʶ±ð³öÕâЩ²½Öè¡£Çë×¢Òâʵ¼ÊµÄÏÔʾÄÚÈÝ¿ÉÄÜËæ»úÆ÷µÄ²»Í¬¶øÓÐÒ»Ð©Çø±ð:

ÊÓ²»Í¬»úÆ÷¶ø¶¨

BIOS(¹Ì¼þ)ÏûÏ¢

F1    FreeBSD
F2    BSD
F5    Disk 2

boot0

>>FreeBSD/i386 BOOT
Default: 1:ad(1,a)/boot/loader
boot:

boot2a

BTX loader 1.0 BTX version is 1.01
BIOS drive A: is disk0
BIOS drive C: is disk1
BIOS 639kB/64512kB available memory
FreeBSD/i386 bootstrap loader, Revision 0.8
Console internal video/keyboard
(jkh@bento.freebsd.org, Mon Nov 20 11:41:23 GMT 2000)
/kernel text=0x1234 data=0x2345 syms=[0x4+0x3456]
Hit [Enter] to boot immediately, or any other key for command prompt
Booting [kernel] in 9 seconds..._

loader

Copyright (c) 1992-2002 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
        The Regents of the University of California. All rights reserved.
FreeBSD 4.6-RC #0: Sat May  4 22:49:02 GMT 2002
    devnull@kukas:/usr/obj/usr/src/sys/DEVNULL
Timecounter "i8254"  frequency 1193182 Hz

ÄÚºË

±í×¢:
a. ÕâÖÖÌáʾ½öÔÚboot0½×¶ÎÓû§Ñ¡Ôñ²Ù×÷ϵͳºó ÈÔ°´×¡¼üÅÌÉÏijһ¼üʱ²Å³öÏÖ¡£

1.3 BIOS POST

¡¡¡¡µ±PC¼Óµçºó£¬´¦ÀíÆ÷µÄ¼Ä´æÆ÷±»ÉèÎªÄ³Ð©ÌØ¶¨Öµ¡£ÔÚÕâЩ¼Ä´æÆ÷ÖУ¬ Ö¸ÁîÖ¸Õë¼Ä´æÆ÷±»ÉèΪ32λֵ0xfffffff0¡£ Ö¸ÁîÖ¸Õë¼Ä´æÆ÷Ö¸Ïò´¦ÀíÆ÷½«ÒªÖ´ÐеÄÖ¸Áî´úÂë¡£cr1£¬ Ò»¸ö32λ¿ØÖƼĴæÆ÷£¬ÔÚ¸ÕÆô¶¯Ê±Öµ±»ÉèΪ0¡£cr1µÄPE(Protected Enabled£¬ ±£»¤Ä£Ê½Ê¹ÄÜ)λÓÃÀ´Ö¸Ê¾´¦ÀíÆ÷ÊÇ´¦ÓÚ±£»¤Ä£Ê½»¹ÊÇʵµØÖ·Ä£Ê½¡£ ÓÉÓÚÆô¶¯Ê±¸Ãλ±»Çå룬´¦ÀíÆ÷ÔÚʵµØÖ·Ä£Ê½ÖÐÒýµ¼¡£ÔÚʵµØÖ·Ä£Ê½ÖУ¬ ÏßÐÔµØÖ·ÓëÎïÀíµØÖ·ÊǵÈͬµÄ¡£

¡¡¡¡Öµ0xfffffff0ÂÔСÓÚ4G,Òò´Ë¼ÆËã»úûÓÐ4G×Ö½ÚÎïÀíÄڴ棬 Õâ¾Í²»»áÊÇÒ»¸öÓÐЧµÄÄÚ´æµØÖ·¡£¼ÆËã»úÓ²¼þ½«Õâ¸öµØÖ·×ªÖ¸ÏòBIOS´æ´¢¿é¡£

¡¡¡¡BIOS±íʾBasic Input Output System (»ù±¾ÊäÈëÊä³öϵͳ)¡£ÔÚÖ÷°åÉÏ£¬Ëü±»¹Ì»¯ÔÚÒ»¸öÏà¶ÔÈÝÁ¿½ÏСµÄ Ö»¶Á´æ´¢Æ÷(Read-Only Memory, ROM)¡£BIOS°üº¬¸÷ÖÖ¸÷ÑùΪÖ÷°åÓ²¼þ ¶¨ÖƵĵײãÀý³Ì¡£¾ÍÕâÑù£¬´¦ÀíÆ÷Ê×ÏÈÖ¸Ïò³£×¤BIOS´æ´¢Æ÷µÄµØÖ· 0xfffffff0¡£Í¨³£Õâ¸öλÖðüº¬Ò»ÌõÌø×ªÖ¸ÁָÏòBIOSµÄPOSTÀý³Ì¡£

¡¡¡¡POST±íʾPower On Self Test(¼Óµç×Ô¼ì)¡£ ÕâÌ׳ÌÐò°üÀ¨ÄÚ´æ¼ì²é£¬ÏµÍ³×ÜÏß¼ì²éºÍÆäËüµ×²ã¹¤¾ß£¬ ´Ó¶øÊ¹µÃCPUÄܹ»³õʼ»¯Õų̂¼ÆËã»ú¡£ÕâÒ»½×¶ÎÖÐÓÐÒ»¸öÖØÒª²½Ö裬 ¾ÍÊÇÈ·¶¨Òýµ¼É豸¡£ÏÖÔÚËùÓеÄBIOS¶¼ÔÊÐíÊÖ¹¤Ñ¡ÔñÒýµ¼É豸¡£ Äã¿ÉÒÔ´ÓÈíÅÌ¡¢¹âÅÌÇý¶¯Æ÷¡¢Ó²Å̵ÈÉ豸Òýµ¼¡£

¡¡¡¡POSTµÄ×îºóÒ»²½ÊÇÖ´ÐÐINT 0x19Ö¸Áî¡£ Õâ¸öÖ¸Áî´ÓÒýµ¼É豸µÚÒ»¸öÉÈÇø¶ÁÈ¡512×Ö½Ú£¬×°ÈëµØÖ·0x7c00¡£ µÚÒ»¸öÉÈÇøµÄ˵·¨×îÔçÆðÔ´ÓÚÓ²Å̵Ľṹ£¬ Ó²ÅÌÃæ±»·ÖΪÈô¸ÉÔ²ÖùÐιìµÀ¡£¸ø¹ìµÀ±àºÅ£¬Í¬Ê±ÓÖ½«¹ìµÀ·ÖΪ Ò»¶¨ÊýÄ¿(ͨ³£ÊÇ64)µÄÉÈÐΡ£0ºÅ¹ìµÀÊÇÓ²Å̵Ä×îÍâȦ£¬1ºÅÉÈÇø£¬ µÚÒ»¸öÉÈÇø(¹ìµÀ¡¢ÖùÃæ¶¼´Ó0¿ªÊ¼±àºÅ£¬¶øÉÈÇø´Ó1¿ªÊ¼±àºÅ) ÓÐ×ÅÌØÊâµÄ×÷Óã¬ËüÓÖ±»³ÆÎªÖ÷Òýµ¼¼Ç¼(Master Boot Record, MBR)¡£ µÚÒ»¹ìÊ£ÓàµÄÉÈÇø³£³£²»Ê¹ÓÃ[1]¡£


1.4 boot0½×¶Î

¡¡¡¡ÈÃÎÒÃÇ¿´Ò»ÏÂÎļþ/boot/boot0¡£ ÕâÊÇÒ»¸ö½ö512×Ö½ÚµÄСÎļþ¡£Èç¹ûÔÚFreeBSD°²×°¹ý³ÌÖÐÑ¡Ôñ ¡°bootmanager¡±£¬Õâ¸öÎļþÖеÄÄÚÈݽ«±»Ð´ÈëÓ²ÅÌMBR

¡¡¡¡ÈçǰËùÊö£¬ INT 0x19 Ö¸Áî×°ÔØ MBR£¬ Ò²¾ÍÊÇ boot0 µÄÄÚÈÝÖÁÄÚ´æµØÖ· 0x7c00¡£ ÔÙ¿´Îļþ sys/boot/i386/boot0/boot0.S£¬ ¿ÉÒÔ²ÂÏëÕâÀïÃæ·¢ÉúÁËʲô - ÕâÊÇÒýµ¼¹ÜÀíÆ÷£¬ Ò»¶ÎÓÉ Robert NordierÊéдµÄÁîÈËÆð¾´µÄ³ÌÐòƬ¶Î¡£

¡¡¡¡MBRÀҲ¾ÍÊÇboot0À ´ÓÆ«ÒÆÁ¿0x1be¿ªÊ¼ÓÐÒ»¸öÌØÊâµÄ½á¹¹£¬³ÆÎª ·ÖÇø±í¡£ÆäÖÐÓÐ4Ìõ¼Ç¼ (³ÆÎª·ÖÇø¼Ç¼)£¬Ã¿Ìõ¼Ç¼16×Ö½Ú¡£ ·ÖÇø¼Ç¼±íʾӲÅÌÈçºÎ±»»®·Ö£¬ÔÚFreeBSDµÄÊõÓïÖУ¬ Õâ±»³ÆÎªslice(d)¡£16×Ö½ÚÖÐÓÐÒ»¸ö±êÖ¾×Ö½Ú¾ö¶¨Õâ¸ö·ÖÇøÊÇ·ñ¿ÉÒýµ¼¡£ ÓнöÖ»ÄÜÓÐÒ»¸ö·ÖÇø¿ÉÉ趨ÕâÒ»±êÖ¾¡£·ñÔò£¬ boot0µÄ´úÂ뽫¾Ü¾ø¼ÌÐøÖ´ÐС£

¡¡¡¡Ò»¸ö·ÖÇø¼Ç¼ÓÐÈçÏÂÓò£º

  • 1×Ö½Ú ÎļþϵͳÀàÐÍ

  • 1×Ö½Ú ¿ÉÒýµ¼±êÖ¾

  • 6×Ö½Ú CHS¸ñʽÃèÊö·û

  • 8×Ö½Ú LBA¸ñʽÃèÊö·û

¡¡¡¡Ò»¸ö·ÖÇø¼Ç¼ÃèÊö·û°üº¬Ä³Ò»·ÖÇøÔÚÓ²ÅÌÉϵÄÈ·ÇÐλÖÃÐÅÏ¢¡£ LBAºÍCHSÁ½ÖÖÃèÊö·ûָʾÏàͬµÄÐÅÏ¢£¬µ«ÊÇָʾ·½Ê½ÓÐËù²»Í¬£ºLBA (Âß¼­¿éѰַ£¬Logical Block Addressing)ָʾ·ÖÇøµÄÆðʼÉÈÇøºÍ·ÖÇø³¤¶È£¬ ¶øCHS(ÖùÃæ ´ÅÍ· ÉÈÇø)ָʾÊ×ÉÈÇøºÍÄ©ÉÈÇø

¡¡¡¡Òýµ¼¹ÜÀíÆ÷ɨÃè·ÖÇø±í£¬²¢ÔÚÆÁÄ»ÉÏÏÔʾ²Ëµ¥£¬ÒÔ±ãÓû§¿ÉÒÔ Ñ¡ÔñÓÃÓÚÒýµ¼µÄ´ÅÅ̺ͷÖÇø¡£ÔÚ¼üÅÌÉϰ´ÏÂÏàÓ¦µÄ¼üºó£¬ boot0½øÐÐÈç϶¯×÷£º

  • ±ê¼ÇÑ¡ÖеķÖÇøÎª¿ÉÒýµ¼£¬Çå³ýÒÔǰµÄ¿ÉÒýµ¼±êÖ¾

  • ¼Çס±¾´ÎÑ¡ÔñµÄ·ÖÇøÒÔ±¸Ï´ÎÒýµ¼Ê±×÷ΪȱʡÏî

  • ×°ÔØÑ¡ÖзÖÇøµÄµÚÒ»¸öÉÈÇø£¬²¢Ìø×ªÖ´ÐÐÖ®

¡¡¡¡Ê²Ã´Êý¾Ý»á´æÔÚÓÚÒ»¸ö¿ÉÒýµ¼ÉÈÇø(ÕâÀïÖ¸FreeBSDÉÈÇø)µÄµÚÒ»ÉÈÇøÀïÄØ£¿ ÕýÈçÄãÒѾ­²Âµ½µÄ£¬ÄǾÍÊÇboot2¡£


1.5 boot2½×¶Î

¡¡¡¡Ò²ÐíÄãÏëÖªµÀ£¬ÎªÊ²Ã´boot2ÊÇÔÚ boot0Ö®ºó£¬¶ø²»ÊÇÔÚboot1Ö®ºó¡£ÊÂʵÉÏ£¬ Ò²ÓÐÒ»¸ö512×Ö½ÚµÄÎļþboot1´æ·ÅÔÚĿ¼ /bootÀÄÇÊÇÓÃÀ´´ÓÒ»ÕÅÈíÅÌÒýµ¼ÏµÍ³µÄ¡£ ´ÓÈíÅÌÒýµ¼Ê±£¬boot1Æð×Å boot0¶ÔÓ²ÅÌÒýµ¼ÏàͬµÄ×÷ÓÃ:ËüÕÒµ½ boot2²¢ÔËÐÐÖ®¡£

¡¡¡¡Äã¿ÉÄÜÒѾ­¿´µ½ÓÐÒ»Îļþ/boot/mbr¡£ ÕâÊÇboot0µÄ¼ò»¯°æ±¾¡£ mbrÖеĴúÂë²»»áÏÔʾ²Ëµ¥ÈÃÓû§Ñ¡Ôñ£¬ ¶øÖ»ÊǼòµ¥µÄÒýµ¼±»±êÖ¾µÄ·ÖÇø¡£

¡¡¡¡ÊµÏÖboot2µÄ´úÂë´æ·ÅÔÚĿ¼ sys/boot/i386/boot2/À¶ÔÓ¦µÄ¿ÉÖ´ÐÐÎļþÔÚ /bootÀï¡£ÔÚ/bootÀïµÄÎļþ boot0ºÍboot2²»»áÔÚÒýµ¼¹ý³ÌÖÐʹÓ㬠ֻÓÐboot0cfgÕâÑùµÄ¹¤¾ß²Å»áʹÓÃËüÃÇ¡£ boot0µÄÄÚÈÝÓ¦ÔÚMBRÖвÅÄÜÉúЧ¡£ boot2λÓÚ¿ÉÒýµ¼µÄFreeBSD·ÖÇøµÄ¿ªÊ¼¡£ ÕâЩλÖò»ÊÜÎļþϵͳ¿ØÖÆ£¬ËùÒÔËüÃDz»¿ÉÓÃls Ö®ÀàµÄÃüÁî²é¿´¡£

¡¡¡¡boot2µÄÖ÷ÒªÈÎÎñÊÇ×°ÔØÎļþ /boot/loader£¬ÄÇÊÇÒýµ¼¹ý³ÌµÄµÚÈý½×¶Î¡£ ÔÚboot2ÖеĴúÂë²»ÄÜʹÓÃÖîÈç open()ºÍread() Ö®ÀàµÄÀý³Ìº¯Êý,ÒòΪÄں˻¹Ã»Óб»¼ÓÔØ¡£¶øÓ¦µ±É¨ÃèÓ²ÅÌ£¬ ¶ÁÈ¡Îļþϵͳ½á¹¹£¬ÕÒµ½Îļþ/boot/loader£¬ ÓÃBIOSµÄ¹¦Äܽ«Ëü¶ÁÈëÄڴ棬Ȼºó´ÓÆäÈë¿Úµã¿ªÊ¼Ö´ÐÐÖ®¡£

¡¡¡¡³ý´ËÖ®Í⣬boot2»¹¿ÉÌáʾÓû§½øÐÐÑ¡Ôñ£¬ loader¿ÉÒÔ´ÓÆäËü´ÅÅÌ¡¢ÏµÍ³µ¥Ôª¡¢·ÖÇø×°ÔØ¡£

¡¡¡¡boot2 µÄ¶þ½øÖÆ´úÂëÓÃÌØÊâµÄ·½Ê½²úÉú£º

sys/boot/i386/boot2/Makefile
boot2: boot2.ldr boot2.bin ${BTX}/btx/btx
	btxld -v -E ${ORG2} -f bin -b ${BTX}/btx/btx -l boot2.ldr \
		-o boot2.ld -P 1 boot2.bin

¡¡¡¡Õâ¸öMakefileƬ¶Ï±íÃ÷btxld(8)±»ÓÃÀ´Á´½Ó¶þ½øÖÆ´úÂë¡£ BTX±íʾÒýµ¼À©Õ¹Æ÷(BooT eXtender)ÊǸø³ÌÐò(³ÆÎª¿Í»§(client) Ìṩ±£»¤Ä£Ê½»·¾³¡¢²¢Óë¿Í»§³ÌÐòÏàÁ´½ÓµÄÒ»¶Î´úÂë¡£ËùÒÔ boot2ÊÇÒ»¸öBTX¿Í»§£¬Ê¹ÓÃBTXÌṩµÄ·þÎñ¡£

¡¡¡¡¹¤¾ßbtxldÊÇÁ´½ÓÆ÷£¬ Ëü½«Á½¸ö¶þ½øÖÆ´úÂëÁ´½ÓÔÚÒ»Æð¡£btxld(8)ºÍld(1) µÄÇø±ðÊÇldͨ³£½«Á½¸öÄ¿±êÎļþ Á´½Ó³ÉÒ»¸ö¶¯Ì¬Á´½Ó¿â»ò¿ÉÖ´ÐÐÎļþ£¬¶øbtxld Ôò½«Ò»¸öÄ¿±êÎļþÓëBTXÁ´½ÓÆðÀ´£¬²úÉúÊʺÏÓÚ·ÅÔÚ·ÖÇøÊײ¿µÄ¶þ½øÖÆ´úÂ룬 ÒÔʵÏÖϵͳÒýµ¼¡£

¡¡¡¡boot0Ö´ÐÐÌø×ªÖÁBTXµÄÈë¿Úµã¡£ È»ºó£¬BTX½«´¦ÀíÆ÷Çл»ÖÁ±£»¤Ä£Ê½£¬²¢×¼±¸Ò»¸ö¼òµ¥µÄ»·¾³£¬ È»ºóµ÷Óÿͻ§¡£Õâ¸ö»·¾³°üÀ¨£º

  • ÐéÄâ8086ģʽ¡£ÕâÒâζ×ÅBTXÊÇÐéÄâ8086µÄ¼àÊÓ³ÌÐò¡£ ʵģʽָÁÈçpushf, popf, cli, sti, if£¬¾ù¿É±»¿Í»§µ÷Óá£

  • ½¨Á¢ÖжÏÃèÊö·û±í(Interrupt Descriptor Table, IDT)£¬ ʹµÃËùÓеÄÓ²¼þÖжϿɱ»È±Ê¡µÄBIOS³ÌÐò´¦Àí¡£ ½¨Á¢ÖжÏ0x30£¬ÕâÊÇϵͳµ÷Óùؿڡ£

  • Á½¸öϵͳµ÷ÓÃexecºÍ exitµÄ¶¨ÒåÈçÏÂ:

    sys/boot/i386/btx/lib/btxsys.s:
    		.set INT_SYS,0x30		# ÖжϺÅ
    #
    # System call: exit
    #
    __exit: 	xorl %eax,%eax			# BTXϵͳµ÷ÓÃ0x0
    		int $INT_SYS			#
    #
    # System call: exec
    #
    __exec: 	movl $0x1,%eax			# BTXϵͳµ÷ÓÃ0x1
    		int $INT_SYS			# 
    

¡¡¡¡BTX½¨Á¢È«¾ÖÃèÊö·û±í(Global Descriptor Table, GDT):

sys/boot/i386/btx/btx/btx.s:
gdt:		.word 0x0,0x0,0x0,0x0		# ÒÔ¿ÕΪÈë¿Ú
		.word 0xffff,0x0,0x9a00,0xcf	# SEL_SCODE
		.word 0xffff,0x0,0x9200,0xcf	# SEL_SDATA
		.word 0xffff,0x0,0x9a00,0x0	# SEL_RCODE
		.word 0xffff,0x0,0x9200,0x0	# SEL_RDATA
		.word 0xffff,MEM_USR,0xfa00,0xcf# SEL_UCODE
		.word 0xffff,MEM_USR,0xf200,0xcf# SEL_UDATA
		.word _TSSLM,MEM_TSS,0x8900,0x0 # SEL_TSS

¡¡¡¡¿Í»§µÄ´úÂëºÍÊý¾ÝʼÓÚµØÖ·MEM_USR(0xa000)£¬Ñ¡Ôñ·û(selector) SEL_UCODEÖ¸Ïò¿Í»§µÄÊý¾Ý¶Î¡£Ñ¡Ôñ·û SEL_UCODE ÓµÓеÚ3¼¶ÃèÊö·ûȨÏÞ (Descriptor Privilege Level, DPL)£¬ÕâÊÇ×îµÍ¼¶È¨ÏÞ¡£µ«ÊÇ INT 0x30 Ö¸ÁîµÄ´¦Àí³ÌÐò´æ´¢ÓÚÁíÒ»¸ö¶ÎÀ Õâ¸ö¶ÎµÄÑ¡Ôñ·ûSEL_SCODE (supervisor code)ÓÉÓÐ׏ÜÀí¼¶È¨ÏÞ¡£ ÕýÈç´úÂ뽨Á¢IDT(ÖжÏÃèÊö·û±í)ʱ½øÐеIJÙ×÷ÄÇÑù:

		mov $SEL_SCODE,%dh		# ¶ÎÑ¡Ôñ·û
init.2: 	shr %bx				# ÊÇ·ñ´¦ÀíÕâ¸öÖжϣ¿
		jnc init.3			# ·ñ
		mov %ax,(%di)			# ÉèÖô¦Àí³ÌÐòÆ«ÒÆÁ¿
		mov %dh,0x2(%di)		# ÉèÖô¦Àí³ÌÐòÑ¡Ôñ·û
		mov %dl,0x5(%di)		# ÉèÖÃ P:DPL:type
		add $0x4,%ax			# ÏÂÒ»¸öÖжϴ¦Àí³ÌÐò

¡¡¡¡ËùÒÔ£¬µ±¿Í»§µ÷Óà __exec()ʱ£¬´úÂ뽫±»ÒÔ×î¸ßȨÏÞÖ´ÐС£ ÕâʹµÃÄں˿ÉÒÔÐ޸ı£»¤Ä£Ê½Êý¾Ý½á¹¹£¬Èç·ÖÒ³±í(page tables)¡¢È«¾ÖÃèÊö·û±í(GDT)¡¢ ÖжÏÃèÊö·û±í(IDT)µÈ¡£

¡¡¡¡boot2 ¶¨ÒåÁËÒ»¸öÖØÒªµÄÊý¾Ý½á¹¹£º struct bootinfo¡£Õâ¸ö½á¹¹ÓÉ boot2 ³õʼ»¯£¬È»ºó±»×ªË͵½loader£¬Ö®ºóÓÖ±»×ªÈëÄںˡ£ Õâ¸ö½á¹¹µÄ²¿·ÖÏîÄ¿ÓÉboot2É趨£¬ÆäÓàµÄÓÉloaderÉ趨¡£ Õâ¸ö½á¹¹ÖеÄÐÅÏ¢°üÀ¨ÄÚºËÎļþÃû¡¢BIOSÌṩµÄÓ²ÅÌÖùÃæ/´ÅÍ·/ÉÈÇøÊýÄ¿ÐÅÏ¢¡¢ BIOSÌṩµÄÒýµ¼É豸µÄÇý¶¯Æ÷±àºÅ£¬¿ÉÓõÄÎïÀíÄÚ´æ´óС£¬envp Ö¸Õë(»·¾³Ö¸Õë)µÈ¡£¶¨ÒåÈçÏ£º

/usr/include/machine/bootinfo.h
struct bootinfo {
	u_int32_t	bi_version;
	u_int32_t	bi_kernelname;		/* ÓÃÒ»¸ö×Ö½Ú±íʾ * */
	u_int32_t	bi_nfs_diskless;	/* struct nfs_diskless * */
		/* ÒÔÉÏΪ³£±¸Ïî */
#define	bi_endcommon	bi_n_bios_used
	u_int32_t	bi_n_bios_used;
	u_int32_t	bi_bios_geom[N_BIOS_GEOM];
	u_int32_t	bi_size;
	u_int8_t	bi_memsizes_valid;
	u_int8_t	bi_bios_dev;		/* Òýµ¼É豸µÄBIOSµ¥Ôª±àºÅ */
	u_int8_t	bi_pad[2];
	u_int32_t	bi_basemem;
	u_int32_t	bi_extmem;
	u_int32_t	bi_symtab;		/* struct symtab * */
	u_int32_t	bi_esymtab;		/* struct symtab * */
		/* ÒÔÏÂÏîÄ¿½ö¸ß¼¶bootloaderÌṩ */
	u_int32_t	bi_kernend;		/* Äں˿ռäÄ©¶Ë */
	u_int32_t	bi_envp;		/* »·¾³ */
	u_int32_t	bi_modulep;		/* Ô¤×°ÔØµÄÄ£¿é */
};

¡¡¡¡boot2 ½øÈëÒ»¸öÑ­»·µÈ´ýÓû§ÊäÈ룬Ȼºóµ÷Óà load()¡£Èç¹ûÓû§²»×öÈκÎÊäÈ룬ѭ»·½«ÔÚÒ»¶Îʱ¼äºó½áÊø£¬ load() ½«»á×°ÔØÈ±Ê¡Îļþ(/boot/loader)¡£ º¯Êý ino_t lookup(char *filename)ºÍ int xfsread(ino_t inode, void *buf, size_t nbyte) ÓÃÀ´½«ÎļþÄÚÈݶÁÈëÄÚ´æ¡£/boot/loaderÊÇÒ»¸öELF¸ñʽ¶þ½øÖÆÎļþ£¬ ²»¹ýËüµÄÍ·²¿±»»»³ÉÁËa.out¸ñʽÖеÄstruct exec½á¹¹¡£ load()ɨÃèloaderµÄELFÍ·²¿£¬×°ÔØ/boot/loader ÖÁÄڴ棬ȻºóÌø×ªÖÁÈë¿ÚÖ´ÐÐÖ®£º

sys/boot/i386/boot2/boot2.c:
    __exec((caddr_t)addr, RB_BOOTINFO | (opts & RBX_MASK),
	   MAKEBOOTDEV(dev_maj[dsk.type], 0, dsk.slice, dsk.unit, dsk.part),
	   0, 0, 0, VTOP(&bootinfo));

1.6 loader½×¶Î

¡¡¡¡loaderÒ²ÊÇÒ»¸ö BTX ¿Í»§£¬ÔÚÕâÀï²»×÷ÏêÊö¡£ ÒÑÓÐÒ»²¿ÄÚÈÝÈ«ÃæµÄÊÖ²á loader(8) £¬ÓÉMike SmithÊéд¡£ ±Èloader¸üµ×²ãµÄBTXµÄ»úÀíÒѾ­ÔÚÇ°ÃæÌÖÂÛ¹ý¡£

¡¡¡¡loader µÄÖ÷ÒªÈÎÎñÊÇÒýµ¼Äںˡ£µ±Äں˱»×°ÈëÄÚ´æºó£¬¼´±»loaderµ÷ÓÃ:

sys/boot/common/boot.c:
    /* ´ÓloaderÖе÷ÓÃÄÚºËÖжÔÓ¦µÄexec³ÌÐò */
    module_formats[km->m_loader]->l_exec(km);

1.7 Äں˳õʼ»¯

¡¡¡¡ÈÃÎÒÃÇÀ´¿´Ò»ÏÂÁ´½ÓÄں˵ÄÃüÁî¡£ ÕâÄܰïÖúÎÒÃÇÁ˽â loader ´«µÝ¸øÄں˵Ä׼ȷλÖᣠÕâ¸öλÖþÍÊÇÄÚºËÕæÊµµÄÈë¿Úµã¡£

sys/conf/Makefile.i386:
ld -elf -Bdynamic -T /usr/src/sys/conf/ldscript.i386  -export-dynamic \
-dynamic-linker /red/herring -o kernel -X locore.o \
<lots of kernel .o files>

¡¡¡¡ÔÚÕâÒ»ÐÐÖÐÓÐһЩÓÐȤµÄ¶«Î÷¡£Ê×ÏÈ£¬ÄÚºËÊÇÒ»¸öELF¶¯Ì¬Á´½Ó¶þ½øÖÆÎļþ£¬ ¿ÉÊǶ¯Ì¬Á´½ÓÆ÷È´ÊÇ/red/herring£¬Ò»¸öĪÐëÓеÄÎļþ¡£ Æä´Î£¬¿´Ò»ÏÂÎļþsys/conf/ldscript.i386£¬ ¿ÉÒÔ¶ÔÀí½â±àÒëÄÚºËʱldµÄÑ¡ÏîÓÐһЩÆô·¢¡£ ÔĶÁ×îǰ¼¸ÐУ¬×Ö·û´®

sys/conf/ldscript.i386:
ENTRY(btext)

¡¡¡¡±íʾÄں˵ÄÈë¿ÚµãÊÇ·ûºÅ `btext'¡£Õâ¸ö·ûºÅÔÚlocore.s Öж¨Òå:

sys/i386/i386/locore.s:
	.text
/**********************************************************************
 *
 * This is where the bootblocks start us, set the ball rolling...
 * Èë¿Ú
 */
NON_GPROF_ENTRY(btext)

¡¡¡¡Ê×ÏȽ«¼Ä´æÆ÷EFLAGSÉèΪһ¸öÔ¤¶¨ÒåµÄÖµ0x00000002£¬ È»ºó³õʼ»¯ËùÓжμĴæÆ÷:

sys/i386/i386/locore.s
/* ²»ÒªÏàÐÅBIOS¸ø³öµÄEFLAGSÖµ */
	pushl	$PSL_KERNEL
	popfl

/*
 * ²»ÒªÏàÐÅBIOS¸ø³öµÄ%fs¡¢%gsÖµ¡£ÏàÐÅÒýµ¼¹ý³ÌÖÐÉ趨µÄ%cs¡¢%ds¡¢%es¡¢%ssÖµ
 */
	mov	%ds, %ax
	mov	%ax, %fs
	mov	%ax, %gs

¡¡¡¡btextµ÷ÓÃÀý³Ìrecover_bootinfo(), identify_cpu(),create_pagetables()¡£ ÕâЩÀý³ÌÒ²¶¨ÔÚlocore.sÖ®ÖС£ÕâЩÀý³ÌµÄ¹¦ÄÜÈçÏ£º

recover_bootinfo Õâ¸öÀý³Ì·ÖÎöÓÉÒýµ¼³ÌÐò´«Ë͸øÄں˵IJÎÊý¡£Òýµ¼ÄÚºËÓÐ3ÖÖ·½Ê½: ÓÉloaderÒýµ¼(ÈçǰËùÊö), ÓÉÀÏʽ´ÅÅÌÒýµ¼¿éÒýµ¼,ÎÞÅÌÒýµ¼·½Ê½¡£ Õâ¸öº¯Êý¾ö¶¨Òýµ¼·½Ê½£¬²¢½«½á¹¹struct bootinfo ´æ´¢ÖÁÄÚºËÄÚ´æ¡£
identify_cpu Õâ¸öº¯ÊýÕì²âCPUÀàÐÍ£¬½«½á¹û´æ·ÅÔÚ±äÁ¿ _cpuÖС£
create_pagetables Õâ¸öº¯ÊýΪ·ÖÒ³±íÔÚÄÚºËÄÚ´æ¿Õ¼ä¶¥²¿·ÖÅäÒ»¿é¿Õ¼ä£¬²¢Ìîдһ¶¨ÄÚÈÝ

¡¡¡¡ÏÂÒ»²½ÊÇ¿ªÆôVME(Èç¹ûCPUÓÐÕâ¸ö¹¦ÄÜ):

	testl	$CPUID_VME, R(_cpu_feature)
	jz	1f
	movl	%cr4, %eax
	orl	$CR4_VME, %eax
	movl	%eax, %cr4

¡¡¡¡È»ºó£¬Æô¶¯·Öҳģʽ:

/* Now enable paging */
	movl	R(_IdlePTD), %eax
	movl	%eax,%cr3			/* load ptd addr into mmu */
	movl	%cr0,%eax			/* get control word */
	orl	$CR0_PE|CR0_PG,%eax		/* enable paging */
	movl	%eax,%cr0			/* and let's page NOW! */

¡¡¡¡ÓÉÓÚ·ÖҳģʽÒѾ­Æô¶¯£¬Ô­ÏȵÄʵµØÖ·Ñ°Ö··½Ê½Ë漴ʧЧ¡£ ËæºóÈýÐдúÂëÓÃÀ´Ìø×ªÖÁÐéÄâµØÖ·:

	pushl	$begin				/* jump to high virtualized address */
	ret

/* ÏÖÔÚÌø×ªÖÁKERNBASE£¬ÄÇÀïÊDzÙ×÷ϵͳÄں˱»Á´½ÓºóÕæÕýµÄÈë¿Ú */
begin:

¡¡¡¡º¯Êýinit386()±»µ÷Óã»Ëæ²ÎÊý´«µÝµÄÊÇÒ»¸öÖ¸Õ룬 Ö¸ÏòµÚÒ»¸ö¿ÕÏÐÎïÀíÒ³¡£ËæºóÖ´ÐÐmi_startup()¡£ init386ÊÇÒ»¸öÓëÓ²¼þϵͳÏà¹ØµÄ³õʼ»¯º¯Êý£¬ mi_startup()ÊǸöÓëÓ²¼þϵͳÎ޹صĺ¯Êý (ǰ׺'mi_'±íʾMachine Independent£¬²»ÒÀÀµÓÚ»úÆ÷)¡£ Äں˲»ÔÙ´Ómi_startup()Àï·µ»Ø£» µ÷ÓÃÕâ¸öº¯Êýºó£¬ÄÚºËÍê³ÉÒýµ¼:

sys/i386/i386/locore.s:
	movl	physfree, %esi
	pushl	%esi		/* Ë͸øinit386()µÄµÚÒ»¸ö²ÎÊý */
	call	_init386	/* ÉèÖÃ386оƬʹ֮ÊÊÓ¦UNIX¹¤×÷ */
	call	_mi_startup	/* ×Ô¶¯ÅäÖÃÓ²¼þ£¬¹Ò½Ó¸ùÎļþϵͳ£¬µÈ */
	hlt		/* ²»ÔÙ·µ»Øµ½ÕâÀ */

1.7.1 init386()

¡¡¡¡init386()¶¨ÒåÔÚ sys/i386/i386/machdep.cÖУ¬ ËüÕë¶ÔIntel 386оƬ½øÐеͼ¶³õʼ»¯¡£loaderÒѽ«CPUÇл»ÖÁ±£»¤Ä£Ê½¡£ loaderÒѾ­½¨Á¢ÁË×îÔçµÄÈÎÎñ¡£

ÒëÕß×¢: ÿ¸ö"ÈÎÎñ"¶¼ÊÇÓëÆäËü¡°ÈÎÎñ¡±Ïà¶Ô¶ÀÁ¢µÄÖ´Ðл·¾³¡£ ÈÎÎñÖ®¼ä¿ÉÒÔ·ÖʱÇл»£¬ÕâΪ²¢·¢½ø³Ì/Ï̵߳ÄʵÏÖÌṩÁ˱ØÒª»ù´¡¡£ ¶ÔÓÚIntel 80x86ÈÎÎñµÄÃèÊö£¬Ïê¼ûIntel¹«Ë¾¹ØÓÚ80386 CPU¼°ºóÐø²úÆ·µÄ×ÊÁÏ£¬ »òÕßÔÚÇ廪´óѧͼÊé¹Ý ¹Ý²Ø¼Ç¼ÖÐÓÃ"80386"×÷Ϊ¹Ø¼ü´ÊËù²éÕÒµ½µÄϵͳ½á¹¹·½ÃæµÄÊéÄ¿¡£

ÔÚÕâ¸öÈÎÎñÖУ¬Äں˽«¼ÌÐø¹¤×÷¡£ÔÚÌÖÂÛÆä´úÂëǰ£¬ ÎÒ½«´¦ÀíÆ÷¶Ô±£»¤Ä£Ê½±ØÐëÍê³ÉµÄһϵÁÐ×¼±¸¹¤×÷Ò»²¢Áгö:
  • ³õʼ»¯Äں˵Ŀɵ÷Õû²ÎÊý£¬ÕâЩ²ÎÊýÓÉÒýµ¼³ÌÐò´«À´

  • ×¼±¸GDT(È«¾ÖÃèÊö·û±í)

  • ×¼±¸IDT(ÖжÏÃèÊö·û±í)

  • ³õʼ»¯ÏµÍ³¿ØÖÆÌ¨

  • ³õʼ»¯DDB(Äں˵ĵãµ÷ÊÔÆ÷)£¬Èç¹ûËü±»±àÒë½øÄں˵ϰ

  • ³õʼ»¯TSS(ÈÎÎñ״̬¶Î)

  • ×¼±¸LDT(¾Ö²¿ÃèÊö·û±í)

  • ½¨Á¢proc0(0ºÅ½ø³Ì£¬¼´Äں˵Ľø³Ì)µÄpcb(½ø³Ì¿ØÖÆ¿é)

¡¡¡¡init386()Ê×Ïȳõʼ»¯Äں˵Ŀɵ÷Õû²ÎÊý£¬ ÕâЩ²ÎÊýÓÉÒýµ¼³ÌÐò´«À´¡£ÏÈÉèÖû·¾³Ö¸Õë(environment pointer, envp)µ÷Ó㬠ÔÙµ÷ÓÃinit_param1()¡£ envpÖ¸ÕëÒÑÓÉloader´æ·ÅÔڽṹbootinfoÖÐ:

sys/i386/i386/machdep.c:
		kern_envp = (caddr_t)bootinfo.bi_envp + KERNBASE;

	/* ³õʼ»¯»ù±¾¿Éµ÷ÕûÏî,ÈçhzµÈ */
	init_param1();

¡¡¡¡init_param1()¶¨ÒåÔÚ sys/kern/subr_param.cÖ®ÖС£ Õâ¸öÎļþÀïÓÐһЩsysctlÏ»¹ÓÐÁ½¸öº¯Êý£¬ init_param1()ºÍinit_param2()¡£ ÕâÁ½¸öº¯Êý´Óinit386()Öе÷ÓÃ:

sys/kern/subr_param.c
	hz = HZ;
	TUNABLE_INT_FETCH("kern.hz", &hz);

¡¡¡¡TUNABLE_<typename>_FETCHÓÃÀ´»ñÈ¡»·¾³±äÁ¿µÄÖµ:

/usr/src/sys/sys/kernel.h
#define	TUNABLE_INT_FETCH(path, var)	getenv_int((path), (var))

¡¡¡¡Sysctlkern.hzÊÇϵͳʱÖÓÆµÂÊ¡£Í¬Ê±£¬ ÕâЩsysctlÏî±»init_param1()É趨: kern.maxswzone, kern.maxbcache, kern.maxtsiz, kern.dfldsiz, kern.maxdsiz, kern.dflssiz, kern.maxssiz, kern.sgrowsiz¡£

¡¡¡¡È»ºóinit386() ×¼±¸È«¾ÖÃèÊö·û±í (Global Descriptors Table, GDT)¡£ÔÚx86ÉÏÿ¸öÈÎÎñ¶¼ÔËÐÐÔÚ×Ô¼ºµÄÐéÄâµØÖ·¿Õ¼äÀ Õâ¸ö¿Õ¼äÓÉ"¶ÎÖ·:Æ«ÒÆÁ¿"µÄÊý¶ÔÖ¸¶¨¡£¾Ù¸öÀý×Ó£¬µ±Ç°½«ÒªÓÉ´¦ÀíÆ÷Ö´ÐеÄÖ¸ÁîÔÚ CS:EIP£¬ÄÇôÕâÌõÖ¸ÁîµÄÏßÐÔÐéÄâµØÖ·¾ÍÊÇ¡°´úÂë¶ÎÐéÄâ¶ÎµØÖ·CS¡± + EIP¡£ ΪÁ˼ò±ã£¬¶ÎÆðʼÓÚÐéÄâµØÖ·0£¬ÖÕÖ¹ÓÚ½çÏÞ4G×Ö½Ú¡£ËùÒÔ£¬ÔÚÕâ¸öÀý×ÓÖУ¬ Ö¸ÁîµÄÏßÐÔÐéÄâµØÖ·ÕýÊÇEIPµÄÖµ¡£¶Î¼Ä´æÆ÷£¬ÈçCS¡¢DSµÈÊÇÑ¡Ôñ·û£¬ ¼´È«¾ÖÃèÊö·û±íÖеÄË÷Òý(¸ü¾«È·µÄ˵£¬Ë÷Òý²¢·ÇÑ¡Ôñ·ûµÄÈ«²¿£¬ ¶øÊÇÑ¡Ôñ·ûÖеÄINDEX²¿·Ö)¡£

ÒëÕß×¢: ¶ÔÓÚ80386£¬ Ñ¡Ôñ·ûÓÐ16룬INDEX²¿·ÖÊÇÆäÖеĸß13λ¡£

FreeBSDµÄÈ«¾ÖÃèÊö·û±íΪÿ¸öCPU±£´æ×Å15¸öÑ¡Ôñ·û:
sys/i386/i386/machdep.c:
union descriptor gdt[NGDT * MAXCPU];	/* È«¾ÖÃèÊö·û±í */

sys/i386/include/segments.h:
/*
 * È«¾ÖÃèÊö·û±í(GDT)ÖеÄÈë¿Ú
 */
#define	GNULL_SEL	0	/* ¿ÕÃèÊö·û */
#define	GCODE_SEL	1	/* Äں˴úÂëÃèÊö·û */
#define	GDATA_SEL	2	/* ÄÚºËÊý¾ÝÃèÊö·û */
#define	GPRIV_SEL	3	/* ¶Ô³Æ¶à´¦Àí(SMP)ÿ´¦ÀíÆ÷רÓÐÊý¾Ý */
#define	GPROC0_SEL	4	/* Task state process slot zero and up, ÈÎÎñ״̬½ø³Ì */
#define	GLDT_SEL	5	/* ÿ¸ö½ø³ÌµÄ¾Ö²¿ÃèÊö·û±í */
#define	GUSERLDT_SEL	6	/* Óû§×Ô¶¨ÒåµÄ¾Ö²¿ÃèÊö·û±í */
#define	GTGATE_SEL	7	/* ½ø³ÌÈÎÎñÇл»¹Ø¿Ú */
#define	GBIOSLOWMEM_SEL	8	/* BIOSµÍ¶ËÄÚ´æ·ÃÎÊ(±ØÐëÊÇÕâµÚ8¸öÈë¿Ú) */
#define	GPANIC_SEL	9	/* »áµ¼ÖÂȫϵͳÒì³£ÖÐÖ¹¹¤×÷µÄÈÎÎñ״̬ */
#define GBIOSCODE32_SEL	10	/* BIOS½Ó¿Ú(32λ´úÂë) */
#define GBIOSCODE16_SEL	11	/* BIOS½Ó¿Ú(16λ´úÂë) */
#define GBIOSDATA_SEL	12	/* BIOS½Ó¿Ú(Êý¾Ý) */
#define GBIOSUTIL_SEL	13	/* BIOS½Ó¿Ú(¹¤¾ß) */
#define GBIOSARGS_SEL	14	/* BIOS½Ó¿Ú(×Ô±äÁ¿£¬²ÎÊý) */

¡¡¡¡Çë×¢Ò⣬ÕâЩ#defines²¢·ÇÑ¡Ôñ·û±¾Éí£¬¶øÖ»ÊÇÑ¡Ôñ·ûÖеÄINDEXÓò£¬ Òò´ËËüÃÇÕýÊÇÈ«¾ÖÃèÊö·û±íÖеÄË÷Òý¡£ ÀýÈ磬Äں˴úÂëµÄÑ¡Ôñ·û(GCODE_SEL)µÄֵΪ0x08¡£

¡¡¡¡ÏÂÒ»²½Êdzõʼ»¯ÖжÏÃèÊö·û±í(Interrupt Descriptor Table, IDT)¡£ ÕâÕűíÔÚ·¢ÉúÈí¼þ»òÓ²¼þÖжÏʱ»á±»´¦ÀíÆ÷ÒýÓá£ÀýÈ磬ִÐÐϵͳµ÷ÓÃʱ£¬ Óû§Ó¦ÓóÌÐòÌá½»INT 0x80 Ö¸Áî¡£ÕâÊÇÒ»¸öÈí¼þÖжϣ¬ ´¦ÀíÆ÷ÓÃË÷ÒýÖµ0x80ÔÚÖжÏÃèÊö·û±íÖвéÕҼǼ¡£Õâ¸ö¼Ç¼ָÏò´¦ÀíÕâ¸öÖжϵÄÀý³Ì¡£ ÔÚÕâ¸öÌØ¶¨ÇéÐÎÖУ¬ÕâÊÇÄں˵Äϵͳµ÷Óùؿڡ£

ÒëÕß×¢: Intel 80386Ö§³Ö¡°µ÷ÓÃÃÅ¡±£¬¿ÉÒÔʹµÃÓû§³ÌÐòֻͨ¹ýÒ»ÌõcallÖ¸Áî ¾Íµ÷ÓÃÄÚºËÖеÄÀý³Ì¡£¿ÉÊÇFreeBSD²¢Î´²ÉÓÃÕâÖÖ»úÖÆ£¬ Ò²ÐíÊÇÒòΪʹÓÃÈíÖжϽӿڿÉÃâÈ¥¶¯Ì¬Á´½ÓµÄÂé·³°É¡£ÁíÍ⻹ÓÐÒ»¸ö¸½´øµÄºÃ´¦£º ÔÚ·ÂÕæLinuxʱ£¬µ±Óöµ½FreeBSDÄں˲»Ö§³ÖµÄ¶øÓÖ²¢·Ç¹Ø¼üÐÔµÄϵͳµ÷ÓÃʱ£¬ ÄÚºËÖ»»áÏÔʾһЩ³ö´íÐÅÏ¢£¬ÕâʹµÃ³ÌÐòÄܹ»¼ÌÐøÔËÐУ» ¶ø²»ÊÇÔÚÕæÕýÖ´ÐгÌÐò֮ǰµÄ³õʼ»¯¹ý³ÌÖоÍÒòΪ¶¯Ì¬Á´½Óʧ°Ü¶ø²»ÔÊÐí³ÌÐòÔËÐС£

ÖжÏÃèÊö·û±í×î¶à¿ÉÒÔÓÐ256 (0x100)Ìõ¼Ç¼¡£Äں˷ÖÅäNIDTÌõ¼Ç¼µÄÄÚ´æ¸øÖжÏÃèÊö·û±í£¬ ÕâÀïNIDT=256£¬ÊÇ×î´óÖµ£º
sys/i386/i386/machdep.c:
static struct gate_descriptor idt0[NIDT];
struct gate_descriptor *idt = &idt0[0];	/* ÖжÏÃèÊö·û±í */

¡¡¡¡Ã¿¸öÖж϶¼±»ÉèÖÃÒ»¸öºÏÊʵÄÖжϴ¦Àí³ÌÐò¡£ ϵͳµ÷ÓùؿÚINT 0x80Ò²ÊÇÈç´Ë:

sys/i386/i386/machdep.c:
 	setidt(0x80, &IDTVEC(int0x80_syscall),
			SDT_SYS386TGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));

¡¡¡¡ËùÒÔµ±Ò»¸öÓû§Ó¦ÓóÌÐòÌá½»INT 0x80Ö¸Áîʱ£¬ ȫϵͳµÄ¿ØÖÆÈ¨»á´«µÝ¸øº¯Êý_Xint0x80_syscall£¬ Õâ¸öº¯ÊýÔÚÄں˴úÂë¶ÎÖУ¬½«±»ÒÔ¹ÜÀíԱȨÏÞÖ´ÐС£

¡¡¡¡È»ºó£¬¿ØÖÆÌ¨ºÍDDB(µ÷ÊÔÆ÷)±»³õʼ»¯:

sys/i386/i386/machdep.c:
	cninit();
/* ÒÔÏ´úÂë¿ÉÄÜÒòΪ䶨ÒåºêDDB¶ø±»Ìø¹ý */
#ifdef DDB
	kdb_init();
	if (boothowto & RB_KDB)
		Debugger("Boot flags requested debugger");
#endif

¡¡¡¡ÈÎÎñ״̬¶Î(TSS)ÊÇÁíÒ»¸öx86±£»¤Ä£Ê½ÖеÄÊý¾Ý½á¹¹¡£µ±·¢ÉúÈÎÎñÇл»Ê±£¬ ÈÎÎñ״̬¶ÎÓÃÀ´ÈÃÓ²¼þ´æ´¢ÈÎÎñÏÖ³¡ÐÅÏ¢¡£

¡¡¡¡¾Ö²¿ÃèÊö·û±í(LDT)ÓÃÀ´Ö¸ÏòÓû§´úÂëºÍÊý¾Ý¡£ÏµÍ³¶¨ÒåÁ˼¸¸öÑ¡Ôñ·û£¬ Ö¸Ïò¾Ö²¿ÃèÊö·û±í£¬ËüÃÇÊÇϵͳµ÷ÓùؿںÍÓû§´úÂë¡¢Óû§Êý¾ÝÑ¡Ôñ·û:

/usr/include/machine/segments.h
#define	LSYS5CALLS_SEL	0	/* Intel BCSÇ¿ÖÆÒªÇóµÄ */
#define	LSYS5SIGR_SEL	1
#define	L43BSDCALLS_SEL	2	/* ÉÐÎÞ */
#define	LUCODE_SEL	3
#define	LSOL26CALLS_SEL	4	/* Solaris >=2.6°æÏµÍ³µ÷ÓÃ¹Ø¿Ú */
#define	LUDATA_SEL	5
/* separate stack, es,fs,gs sels ? ·Ö±ðµÄÕ»¡¢es¡¢fs¡¢gsÑ¡Ôñ·û£¿ */
/* #define	LPOSIXCALLS_SEL	5*/	/* notyet, ÉÐÎÞ */
#define LBSDICALLS_SEL	16	/* BSDI system call gate, BSDIϵͳµ÷ÓÃ¹Ø¿Ú */
#define NLDT		(LBSDICALLS_SEL + 1)

¡¡¡¡È»ºó£¬proc0(0ºÅ½ø³Ì£¬¼´ÄÚºËËù´¦µÄ½ø³Ì)µÄ½ø³Ì¿ØÖÆ¿é(Process Control Block) (struct pcb)½á¹¹±»³õʼ»¯¡£proc0ÊÇÒ»¸ö struct proc ½á¹¹£¬ÃèÊöÁËÒ»¸öÄں˽ø³Ì¡£ ÄÚºËÔËÐÐʱ£¬¸Ã½ø³Ì×ÜÊÇ´æÔÚ£¬ËùÒÔÕâ¸ö½á¹¹ÔÚÄÚºËÖб»¶¨ÒåΪȫ¾Ö±äÁ¿:

sys/kern/kern_init.c:
    struct	proc proc0;

¡¡¡¡½á¹¹struct pcbÊÇproc½á¹¹µÄÒ»²¿·Ö£¬ Ëü¶¨ÒåÔÚ/usr/include/machine/pcb.hÖ®ÖУ¬ ÄÚº¬Õë¶Ôi386Ó²¼þ½á¹¹×¨ÓеÄÐÅÏ¢£¬Èç¼Ä´æÆ÷µÄÖµ¡£


1.7.2 mi_startup()

¡¡¡¡Õâ¸öº¯ÊýÓÃðÅÝÅÅÐòËã·¨£¬½«ËùÓÐϵͳ³õʼ»¯¶ÔÏó£¬È»ºóÖð¸öµ÷ÓÃÿ¸ö¶ÔÏóµÄÈë¿Ú:

sys/kern/init_main.c:
	for (sipp = sysinit; *sipp; sipp++) {

		/* ... Ê¡ÂÔ ... */

		/* µ÷Óú¯Êý */
		(*((*sipp)->func))((*sipp)->udata);
		/* ... Ê¡ÂÔ ... */
	}

¡¡¡¡¾¡¹Üsysinit¿ò¼ÜÒѾ­ÔÚ¡¶FreeBSD¿ª·¢ÕßÊֲᡷÖÐÓÐËùÃèÊö£¬ ÎÒ»¹ÊÇÔÚÕâÀïÌÖÂÛÒ»ÏÂÆäÄÚ²¿Ô­Àí¡£

¡¡¡¡Ã¿¸öϵͳ³õʼ»¯¶ÔÏó(sysinit¶ÔÏó)ͨ¹ýµ÷Óú꽨Á¢¡£ ÈÃÎÒÃÇÒÔannounce sysinit¶ÔÏóΪÀý¡£ Õâ¸ö¶ÔÏó´òÓ¡°æÈ¨ÐÅÏ¢:

sys/kern/init_main.c:
static void
print_caddr_t(void *data __unused)
{
	printf("%s", (char *)data);
}
SYSINIT(announce, SI_SUB_COPYRIGHT, SI_ORDER_FIRST, print_caddr_t, copyright)

¡¡¡¡Õâ¸ö¶ÔÏóµÄ×Óϵͳ±êʶÊÇSI_SUB_COPYRIGHT(0x0800001)£¬ ÊýÖµ¸ÕºÃÅÅÔÚSI_SUB_CONSOLE(0x0800000)ºóÃæ¡£ ËùÒÔ£¬°æÈ¨ÐÅÏ¢½«ÔÚ¿ØÖÆÌ¨³õʼ»¯Ö®ºó¾Í±»ºÜÔçµÄ´òÓ¡³öÀ´¡£

¡¡¡¡ÈÃÎÒÃÇ¿´Ò»¿´ºêSYSINIT()µ½µ××öÁËЩʲô¡£ ËüÕ¹¿ª³ÉºêC_SYSINIT()¡£ ºêC_SYSINIT()È»ºóÕ¹¿ª³ÉÒ»¸ö¾²Ì¬½á¹¹ struct sysinit¡£½á¹¹ÀïÉêÃ÷Àïµ÷ÓÃÁËÁíÒ»¸öºê DATA_SET:

/usr/include/sys/kernel.h:
      #define C_SYSINIT(uniquifier, subsystem, order, func, ident) \
      static struct sysinit uniquifier ## _sys_init = { \ subsystem, \
      order, \ func, \ ident \ }; \ DATA_SET(sysinit_set,uniquifier ##
      _sys_init);

#define	SYSINIT(uniquifier, subsystem, order, func, ident)	\
	C_SYSINIT(uniquifier, subsystem, order,			\
	(sysinit_cfunc_t)(sysinit_nfunc_t)func, (void *)ident)

¡¡¡¡ºêDATA_SET()Õ¹¿ª³ÉMAKE_SET()£¬ ºêMAKE_SET()Ö¸ÏòËùÓÐÒþº¬µÄsysinit»ÃÊý:

/usr/include/linker_set.h
#define MAKE_SET(set, sym)						\
	static void const * const __set_##set##_sym_##sym = &sym;	\
	__asm(".section .set." #set ",\"aw\"");				\
	__asm(".long " #sym);						\
	__asm(".previous")
#endif
#define TEXT_SET(set, sym) MAKE_SET(set, sym)
#define DATA_SET(set, sym) MAKE_SET(set, sym)

¡¡¡¡»Øµ½ÎÒÃǵÄÀý×ÓÖУ¬¾­¹ýºêµÄÕ¹¿ª¹ý³Ì£¬½«»á²úÉúÈçÏÂÉùÃ÷:

static struct sysinit announce_sys_init = {
	SI_SUB_COPYRIGHT,
	SI_ORDER_FIRST,
	(sysinit_cfunc_t)(sysinit_nfunc_t)  print_caddr_t,
	(void *) copyright
};

static void const *const __set_sysinit_set_sym_announce_sys_init =
    &announce_sys_init;
__asm(".section .set.sysinit_set" ",\"aw\"");
__asm(".long " "announce_sys_init");
__asm(".previous");

¡¡¡¡µÚÒ»¸ö__asmÖ¸ÁîÔÚÄں˿ÉÖ´ÐÐÎļþÖн¨Á¢Ò»¸öELF½Ú(section)¡£ Õâ·¢ÉúÔÚÄÚºËÁ´½ÓµÄʱºò¡£ÕâÒ»½Ú½«±»ÃüÁîΪ.set.sysinit_set¡£ ÕâÒ»½ÚµÄÄÚÈÝÊÇÒ»¸ö32λֵ¡ª¡ªannounce_sys_init½á¹¹µÄµØÖ·£¬Õâ¸ö½á¹¹ÕýÊǵڶþ¸ö __asmÖ¸ÁîËù¶¨ÒåµÄ¡£µÚÈý¸ö__asmÖ¸Áî±ê¼Ç½ÚµÄ½áÊø¡£ Èç¹ûÇ°ÃæÓÐÃû×ÖÏàͬµÄ½Ú¶¨ÒåÓï¾ä£¬½ÚµÄÄÚÈÝ(ÄǸö32λֵ)½«±»Ìî¼Óµ½ÒÑ´æÔڵĽÚÀ ÕâÑù¾Í¹¹Ôì³öÁËÒ»¸ö32λָÕëÊý×é¡£

¡¡¡¡ÓÃobjdump²ì¿´Ò»¸öÄں˶þ½øÖÆÎļþ£¬ Ò²ÐíÄã»á×¢Òâµ½ÀïÃæÓÐÕâô¼¸¸öСµÄ½Ú:

% objdump -h /kernel
  7 .set.cons_set 00000014  c03164c0  c03164c0  002154c0  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  8 .set.kbddriver_set 00000010  c03164d4  c03164d4  002154d4  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  9 .set.scrndr_set 00000024  c03164e4  c03164e4  002154e4  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 10 .set.scterm_set 0000000c  c0316508  c0316508  00215508  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 11 .set.sysctl_set 0000097c  c0316514  c0316514  00215514  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 12 .set.sysinit_set 00000664  c0316e90  c0316e90  00215e90  2**2
                  CONTENTS, ALLOC, LOAD, DATA

¡¡¡¡ÕâÒ»ÆÁÐÅÏ¢ÏÔʾ±íÃ÷½Ú.set.sysinit_setÓÐ0x664×ֽڵĴóС£¬ ËùÒÔ0x664/sizeof(void *)¸ösysinit¶ÔÏó±»±àÒë½øÁËÄںˡ£ ÆäËü½Ú£¬Èç.set.sysctl_set±íʾÆäËüÁ´½ÓÆ÷¼¯ºÏ¡£

¡¡¡¡Í¨¹ý¶¨ÒåÒ»¸öÀàÐÍΪstruct linker_setµÄ±äÁ¿£¬ ½Ú.set.sysinit_set½«±»¡°ÊÕ¼¯¡±µ½ÄǸö±äÁ¿Àï:

sys/kern/init_main.c:
      extern struct linker_set sysinit_set; /* XXX */

¡¡¡¡struct linker_set¶¨ÒåÈçÏÂ:

/usr/include/linker_set.h:
  struct linker_set {
	int	ls_length;
	void	*ls_items[1];		/* ls_length¸öÏîµÄÊý×é, ÒÔNULL½áβ */
};

¡¡¡¡

ÒëÕß×¢: ʵ¼ÊÉÏÊÇ˵£¬ ÓÃCÓïÑԽṹÌålinker_setÀ´±í´ïÄǸöELF½Ú¡£

µÚÒ»ÏîÊÇsysinit¶ÔÏóµÄÊýÁ¿£¬µÚ¶þÏîÊÇÒ»¸öÒÔNULL½áβµÄÊý×飬 Êý×éÖÐÊÇÖ¸ÏòÄÇЩ¶ÔÏóµÄÖ¸Õë¡£

¡¡¡¡»Øµ½¶Ômi_startup()µÄÌÖÂÛ£¬ ÎÒÃÇÇå³þÁËsysinit¶ÔÏóÊÇÈçºÎ±»×éÖ¯ÆðÀ´µÄ¡£ º¯Êými_startup()½«ËüÃÇÅÅÐò£¬ ²¢µ÷ÓÃÿһ¸ö¶ÔÏó¡£×îºóÒ»¸ö¶ÔÏóÊÇϵͳµ÷¶ÈÆ÷:

/usr/include/sys/kernel.h:
enum sysinit_sub_id {
	SI_SUB_DUMMY		= 0x0000000,	/* ²»±»Ö´ÐУ¬½ö¹©Á´½ÓÆ÷ʹÓà */
	SI_SUB_DONE		= 0x0000001,	/* Òѱ»´¦Àí*/
	SI_SUB_CONSOLE		= 0x0800000,	/* ¿ØÖÆÌ¨*/
	SI_SUB_COPYRIGHT	= 0x0800001,	/* ×îÔçʹÓÿØÖÆÌ¨µÄ¶ÔÏó */
...
	SI_SUB_RUN_SCHEDULER	= 0xfffffff	/* µ÷¶ÈÆ÷:²»·µ»Ø */
};

¡¡¡¡ÏµÍ³µ÷¶ÈÆ÷sysinit¶ÔÏó¶¨ÒåÔÚÎļþsys/vm/vm_glue.cÖУ¬ Õâ¸ö¶ÔÏóµÄÈë¿ÚµãÊÇscheduler()¡£ Õâ¸öº¯Êýʵ¼ÊÉÏÊǸöÎÞÏÞÑ­»·£¬Ëü±íʾÄǸö½ø³Ì±êʶ(PID)Ϊ0µÄ½ø³Ì¡ª¡ªswapper½ø³Ì¡£ Ç°ÃæÌáµ½µÄproc0½á¹¹ÕýÊÇÓÃÀ´ÃèÊöÕâ¸ö½ø³Ì¡£

¡¡¡¡µÚÒ»¸öÓû§½ø³ÌÊÇinit£¬ ÓÉsysinit¶ÔÏóinit½¨Á¢:

sys/kern/init_main.c:
static void
create_init(const void *udata __unused)
{
	int error;
	int s;

	s = splhigh();
	error = fork1(&proc0, RFFDG | RFPROC, &initproc);
	if (error)
		panic("cannot fork init: %d\n", error);
	initproc->p_flag |= P_INMEM | P_SYSTEM;
	cpu_set_fork_handler(initproc, start_init, NULL);
	remrunqueue(initproc);
	splx(s);
}
SYSINIT(init,SI_SUB_CREATE_INIT, SI_ORDER_FIRST, create_init, NULL)

¡¡¡¡create_init()ͨ¹ýµ÷ÓÃfork1() ·ÖÅäÒ»¸öеĽø³Ì£¬µ«²¢²»½«Æä±ê¼ÇΪ¿ÉÔËÐС£µ±Õâ¸öнø³Ì±»µ÷¶ÈÆ÷µ÷¶ÈÖ´ÐÐʱ£¬ start_init()½«»á±»µ÷ÓᣠÄǸöº¯Êý¶¨ÒåÔÚinit_main.cÖС£ Ëü³¢ÊÔ×°ÔØ²¢Ö´Ðжþ½øÖÆ´úÂëinit£¬ Ïȳ¢ÊÔ/sbin/init£¬È»ºóÊÇ/sbin/oinit£¬ /sbin/init.bak£¬×îºóÊÇ/stand/sysinstall:

sys/kern/init_main.c:
static char init_path[MAXPATHLEN] =
#ifdef	INIT_PATH
    __XSTRING(INIT_PATH);
#else
    "/sbin/init:/sbin/oinit:/sbin/init.bak:/stand/sysinstall";
#endif

µÚ2Õ ¡¡ÄÚºËÖеÄËø

·­Ò룺intron@intron.ac.

¡¡¡¡ÕâÒ»ÕÂÓÉ FreeBSD SMP Next Generation Project ά»¤¡£ Ç뽫ÆÀÂۺͽ¨Òé·¢Ë͸øFreeBSD ¶Ô³Æ¶à´¦Àí (SMP) ÓʼþÁбí.

¡¡¡¡ÕâÆªÎĵµÌá¸ÙêüÁìµÄ½²ÊöÁËÔÚFreeBSDÄÚºËÖеÄËø£¬ÕâÐ©ËøÊ¹µÃÓÐЧµÄ¶à´¦Àí³ÉΪ¿ÉÄÜ¡£ Ëø¿ÉÒÔÓü¸ÖÖ·½Ê½»ñµÃ¡£Êý¾Ý½á¹¹¿ÉÒÔÓÃmutex»òlockmgr(9)±£»¤¡£ ¶ÔÓÚΪÊý²»¶àµÄÈô¸É¸ö±äÁ¿£¬¼ÙÈç×ÜÊÇʹÓÃÔ­×Ó²Ù×÷·ÃÎÊËüÃÇ£¬ÕâЩ±äÁ¿¾Í¿ÉÒԵõ½±£»¤¡£

ÒëÕß×¢: ½ö¶Á±¾ÕÂÄÚÈÝ£¬»¹²»×ãÒÔÕÒ³ö¡°mutex¡± ºÍ¡°¹²Ïí»¥³âËø¡±µÄÇø±ð¡£ËƺõËüÃǵŦÄÜÓÐÖØµþÖ®´¦£¬ ǰÕ߱ȺóÕߵŦÄÜÑ¡Ïî¸ü¶à¡£ËüÃÇËÆºõ¶¼ÊÇlockmgr(9)µÄ×Ó¼¯¡£


2.1 Mutex

¡¡¡¡Mutex¾ÍÊÇÒ»ÖÖÓÃÀ´½â¾ö¹²Ïí/ÅÅËüì¶ÜµÄËø¡£ Ò»¸ömutexÔÚÒ»¸öʱ¿ÌÖ»¿ÉÒÔ±»Ò»¸öʵÌåÓµÓС£Èç¹ûÁíÒ»¸öʵÌåÒª»ñµÃÒѾ­±»ÓµÓеÄmutex£¬ ¾Í»á½øÈëµÈ´ý£¬Ö±µ½Õâ¸ömutex±»ÊÍ·Å¡£ÔÚFreeBSDÄÚºËÖУ¬mutex±»½ø³ÌËùÓµÓС£

¡¡¡¡Mutex¿ÉÒÔ±»µÝ¹éµÄË÷Òª£¬µ«ÊÇmutexÒ»°ãÖ»±»Ò»¸öʵÌåÓµÓн϶̵ÄÒ»¶Îʱ¼ä£¬ Òò´ËÒ»¸öʵÌå²»ÄÜÔÚ³ÖÓÐmutexʱ˯Ãß¡£Èç¹ûÄãÐèÒªÔÚ³ÖÓÐmutexʱ˯Ãߣ¬ ¿ÉʹÓÃÒ»¸ö lockmgr(9) µÄËø¡£

¡¡¡¡Ã¿¸ömutexÓм¸¸öÁîÈ˸ÐÐËȤµÄÊôÐÔ:

±äÁ¿Ãû

ÔÚÄÚºËÔ´´úÂëÖÐstruct mtx±äÁ¿µÄÃû×Ö

Âß¼­Ãû

Óɺ¯Êýmtx_initÖ¸ÅɵÄmutexµÄÃû×Ö¡£ Õâ¸öÃû×ÖÏÔʾÔÚKTR¸ú×ÙÏûÏ¢ºÍwitness³ö´íÓ뾯¸æÐÅÏ¢Àï¡£ Õâ¸öÃû×Ö»¹ÓÃÓÚÇø·Ö±êʶÔÚwitness´úÂëÖеĸ÷¸ömutex

ÀàÐÍ

MutexµÄÀàÐÍ£¬ÓñêÖ¾MTX_*±íʾ¡£ ÿ¸ö±êÖ¾µÄÒâÒåÔÚmutex(9)ÓÐËùÃèÊö¡£

MTX_DEF

Ò»¸ö˯Ãßmutex

MTX_SPIN

Ò»¸öÑ­»·mutex

MTX_RECURSE

Õâ¸ömutexÔÊÐíµÝ¹é

±£»¤¶ÔÏó

Õâ¸öÈë¿ÚËùÒª±£»¤µÄÊý¾Ý½á¹¹Áбí»òÊý¾Ý½á¹¹³ÉÔ±ÁÐ±í¡£ ¶ÔÓÚÊý¾Ý½á¹¹³ÉÔ±£¬½«°´ÕÕ ½á¹¹Ãû.³ÉÔ±ÃûµÄÐÎʽÃüÃû¡£

ÒÀÀµº¯Êý

½öµ±mutex±»³ÖÓÐʱ²Å¿ÉÒÔ±»µ÷Óõĺ¯Êý

±í 2-1. MutexÁбí

±äÁ¿Ãû Âß¼­Ãû ÀàÐÍ ±£»¤¶ÔÏó ÒÀÀµº¯Êý
sched_lock ¡°sched lock¡±(µ÷¶ÈÆ÷Ëø) MTX_SPIN | MTX_RECURSE _gmonparam, cnt.v_swtch, cp_time, curpriority, mtx.mtx_blocked, mtx.mtx_contested, proc.p_procq, proc.p_slpq, proc.p_sflag, proc.p_stat, proc.p_estcpu, proc.p_cpticks proc.p_pctcpu, proc.p_wchan, proc.p_wmesg, proc.p_swtime, proc.p_slptime, proc.p_runtime, proc.p_uu, proc.p_su, proc.p_iu, proc.p_uticks, proc.p_sticks, proc.p_iticks, proc.p_oncpu, proc.p_lastcpu, proc.p_rqindex, proc.p_heldmtx, proc.p_blocked, proc.p_mtxname, proc.p_contested, proc.p_priority, proc.p_usrpri, proc.p_nativepri, proc.p_nice, proc.p_rtprio, pscnt, slpque, itqueuebits, itqueues, rtqueuebits, rtqueues, queuebits, queues, idqueuebits, idqueues, switchtime, switchticks setrunqueue, remrunqueue, mi_switch, chooseproc, schedclock, resetpriority, updatepri, maybe_resched, cpu_switch, cpu_throw, need_resched, resched_wanted, clear_resched, aston, astoff, astpending, calcru, proc_compare
vm86pcb_lock ¡°vm86pcb lock¡±(ÐéÄâ8086ģʽ½ø³Ì¿ØÖÆ¿éËø) MTX_DEF vm86pcb vm86_bioscall
Giant ¡°Giant¡±(¾ÞËø) MTX_DEF | MTX_RECURSE ¼¸ºõ¿ÉÒÔÊÇÈκζ«Î÷ Ðí¶à
callout_lock ¡°callout lock¡±(ÑÓʱµ÷ÓÃËø) MTX_SPIN | MTX_RECURSE callfree, callwheel, nextsoftcheck, proc.p_itcallout, proc.p_slpcallout, softticks, ticks  

2.2 ¹²Ïí»¥³âËø

¡¡¡¡ÕâÐ©ËøÌṩ»ù±¾µÄ¶Á/дÀàÐ͵ŦÄÜ£¬¿ÉÒÔ±»Ò»¸öÕýÔÚ˯ÃߵĽø³Ì³ÖÓС£ ÏÖÔÚËüÃDZ»Í³Ò»µ½lockmgr(9)Ö®ÖС£

±í 2-2. ¹²Ïí»¥³âËøÁбí

±äÁ¿Ãû ±£»¤¶ÔÏó
allproc_lock allproc zombproc pidhashtbl proc.p_list proc.p_hash nextpid
proctree_lock proc.p_children proc.p_sibling

2.3 Ô­×Ó±£»¤±äÁ¿

¡¡¡¡Ô­×Ó±£»¤±äÁ¿²¢·ÇÓÉÒ»¸öÏÔÔÚµÄËø±£»¤µÄÌØÊâ±äÁ¿£¬¶øÊÇ£º ¶ÔÕâЩ±äÁ¿µÄËùÓÐÊý¾Ý·ÃÎʶ¼ÒªÊ¹ÓÃÌØÊâµÄÔ­×Ó²Ù×÷(atomic(9))¡£ ¾¡¹ÜÆäËüµÄ»ù±¾Í¬²½»úÖÆ(ÀýÈçmutex)¾ÍÊÇÓÃÔ­×Ó±£»¤±äÁ¿ÊµÏֵģ¬ µ«ÊǺÜÉÙÓбäÁ¿Ö±½ÓʹÓÃÕâÖÖ´¦Àí·½Ê½¡£

  • mtx.mtx_lock


µÚ3Õ ¡¡Äں˶ÔÏó

·­Ò룺intron@intron.ac.

¡¡¡¡Äں˶ÔÏó£¬Ò²¾ÍÊÇKobj£¬ÎªÄÚºËÌṩÁËÒ»ÖÖÃæÏò¶ÔÏó µÄCÓïÑÔ±à³Ì·½Ê½¡£±»²Ù×÷µÄÊý¾ÝÒ²³ÐÔØ²Ù×÷ËüµÄ·½·¨¡£ ÕâʹµÃÔÚ²»ÆÆ»µ¶þ½øÖƼæÈÝÐÔµÄǰÌáÏ£¬Ä³Ò»¸ö½Ó¿ÚÄܹ»Ôö/¼õÏàÓ¦µÄ²Ù×÷¡£


3.1 ÊõÓï

¶ÔÏó

Êý¾Ý¼¯ºÏ-Êý¾Ý½á¹¹-Êý¾Ý·ÖÅäµÄ¼¯ºÏ

·½·¨

ijһÖÖ²Ù×÷©¤©¤º¯Êý

Àà

Ò»ÖÖ»ò¶àÖÖ·½·¨

½Ó¿Ú

Ò»ÖÖ»ò¶àÖÖ·½·¨µÄÒ»¸ö±ê×¼¼¯ºÏ


3.2 KobjµÄ¹¤×÷Á÷³Ì

ÒëÕß×¢: ÕâһС½ÚÁ½¶ÎÂäÖÐÔ­×÷ÕßµÄÓôÊÓÐЩº¬»ì£¬ Çë²Î¿¼ÎÒÔÚÀ¨ºÅÖеÄ×¢ÊÍÔĶÁ¡£

¡¡¡¡Kobj¹¤×÷ʱ£¬²úÉú·½·¨µÄÃèÊö¡£Ã¿¸öÃèÊöÓÐÒ»¸öΨһµÄ±êʶºÍÒ»¸öȱʡº¯Êý¡£ ij¸öÃèÊöµÄµØÖ·±»ÓÃÀ´ÔÚÒ»¸öÀàµÄ·½·¨±íÀïΨһµÄ±êʶ·½·¨¡£

¡¡¡¡¹¹½¨Ò»¸öÀ࣬¾ÍÊÇÒª½¨Á¢Ò»ÕÅ·½·¨±í£¬²¢½«ÕâÕÅ±í¹ØÁªµ½Ò»¸ö»ò¶à¸öº¯Êý(·½·¨)£» ÕâЩº¯Êý(·½·¨)¶¼´øÓз½·¨ÃèÊö¡£Ê¹ÓÃǰ£¬ÀàÒª±»±àÒë¡£±àÒëʱҪΪÕâ¸öÀà·ÖÅäһЩ»º´æ¡£ ÔÚ·½·¨±íÖеÄÿ¸ö·½·¨ÃèÊö¶¼»á±»Ö¸ÅÉÒ»¸öΨһµÄ±êʶ£¬ ³ý·ÇÒѾ­±»ÆäËüÒýÓÃËüµÄÀàÔÚ±àÒëʱָÅÉÁ˱êʶ¡£¶ÔÓÚÿ¸ö½«Òª±»Ê¹Óõķ½·¨£¬ ¶¼»áÓɽű¾Éú³ÉÒ»¸öº¯Êý(·½·¨²éÕÒº¯Êý)£¬ÒÔ½âÎöÍâÀ´²ÎÊý£¬ ²¢ÔÚ±»²éѯʱ¸ø³ö·½·¨ÃèÊöµÄµØÖ·¡£±»Éú³ÉµÄº¯Êý(·½·¨²éÕÒº¯Êý) ƾ×ÅÄǸö·½·¨ÃèÊöµÄΨһ±êʶ°´HashµÄ·½·¨²éÕÒ¶ÔÏóµÄÀàµÄ»º´æ¡£ Èç¹ûÕâ¸ö·½·¨²»ÔÚ»º´æÖУ¬º¯Êý»á²éÕÒʹÓÃÀàµÄ·½·¨±í¡£Èç¹ûÕâ¸ö·½·¨±»ÕÒµ½ÁË£¬ ÀàÀïµÄÏà¹Øº¯Êý(Ò²¾ÍÊÇij¸ö·½·¨µÄʵÏÖ´úÂë)¾Í»á±»Ê¹Óᣠ·ñÔò£¬Õâ¸ö·½·¨ÃèÊöµÄȱʡº¯Êý½«±»Ê¹Óá£

¡¡¡¡ÕâЩ¹ý³Ì¿É±»±íʾÈçÏ£º

¶ÔÏó->»º´æ<->Àà

3.3 ʹÓÃKobj

3.3.1 ½á¹¹

struct kobj_method

3.3.2 º¯Êý

void kobj_class_compile(kobj_class_t cls);
void kobj_class_compile_static(kobj_class_t cls, kobj_ops_t ops);
void kobj_class_free(kobj_class_t cls);
kobj_t kobj_create(kobj_class_t cls, struct malloc_type *mtype, int mflags);
void kobj_init(kobj_t obj, kobj_class_t cls);
void kobj_delete(kobj_t obj, struct malloc_type *mtype);

3.3.3 ºê

KOBJ_CLASS_FIELDS
KOBJ_FIELDS
DEFINE_CLASS(name, methods, size)
KOBJMETHOD(NAME, FUNC)

3.3.4 Í·Îļþ

<sys/param.h>
<sys/kobj.h>

3.3.5 ½¨Á¢Ò»¸ö½Ó¿ÚµÄÄ£°å

¡¡¡¡Ê¹ÓÃKobjµÄµÚÒ»²½Êǽ¨Á¢Ò»¸ö½Ó¿Ú¡£½¨Á¢½Ó¿Ú°üÀ¨½¨Á¢Ä£°åµÄ¹¤×÷¡£ ½¨Á¢Ä£°å¿ÉÓýű¾src/sys/kern/makeobjops.plÍê³É£¬ Ëü»á²úÉúÉêÃ÷·½·¨µÄÍ·ÎļþºÍ´úÂ룬½Å±¾»¹»áÉú³É·½·¨²éÕÒº¯Êý¡£

¡¡¡¡ÔÚÕâ¸öÄ£°åÖÐÈçϹؼü´Ê»á±»Ê¹ÓÃ: #include, INTERFACE, CODE, METHOD, STATICMETHOD, ºÍ DEFAULT.

¡¡¡¡#includeÓï¾äµÄÕûÐÐÄÚÈݽ«±»Ò»×Ö²»²îµÄ ¸´ÖƵ½±»Éú³ÉµÄ´úÂëÎļþµÄÍ·²¿¡£

¡¡¡¡ÀýÈç:

#include <sys/foo.h>

¡¡¡¡¹Ø¼ü´ÊINTERFACEÓÃÀ´¶¨Òå½Ó¿ÚÃû¡£ Õâ¸öÃû×Ö½«Óëÿ¸ö·½·¨Ãû½ÓºÏÔÚÒ»Æð£¬ÐÎ³É [interface name]_[method name]¡£ Óï·¨ÊÇ£ºINTERFACE [½Ó¿ÚÃû];

¡¡¡¡ÀýÈç:

INTERFACE foo;

¡¡¡¡¹Ø¼ü´ÊCODE»á½«ËüµÄ²ÎÊýÒ»×Ö²»²îµÄ¸´ÖƵ½´úÂëÎļþÖС£ Óï·¨ÊÇCODE { [ÈκδúÂë] };

¡¡¡¡ÀýÈç:

CODE {
	struct foo * foo_alloc_null(struct bar *)
	{
		return NULL;
}
};

¡¡¡¡¹Ø¼ü´ÊMETHODÓÃÀ´ÃèÊöÒ»¸ö·½·¨¡£Óï·¨ÊÇ: METHOD [·µ»ØÖµÀàÐÍ] [·½·¨Ãû] { [¶ÔÏó [, ²ÎÊýÈô¸É]] };

¡¡¡¡ÀýÈç:

METHOD int bar {
	struct object *;
	struct foo *;
	struct bar;
};

¡¡¡¡¹Ø¼ü´ÊDEFAULT¸úÔڹؼü´ÊMETHODÖ®ºó£¬ ÊǶԹؼü´ÊMETHODµÄ²¹³ä¡£Ëü¸øÕâ¸ö·½·¨²¹³äÉÏȱʡº¯Êý¡£Óï·¨ÊÇ£º METHOD [·µ»ØÖµÀàÐÍ] [·½·¨Ãû] { [¶ÔÏó; [ÆäËü²ÎÊý]] }DEFAULT [ȱʡº¯Êý];

¡¡¡¡ÀýÈç:

METHOD int bar {
	struct object *;
	struct foo *;
	int bar;
} DEFAULT foo_hack;

¡¡¡¡¹Ø¼ü´ÊSTATICMETHODÀàËÆ¹Ø¼ü´ÊMETHOD¡£ ¶ÔÓÚÿ¸öKobj¶ÔÏó£¬Ò»°ãÆäÍ·²¿¶¼ÓÐһЩKobjרÓеÄÊý¾Ý¡£ METHOD¶¨ÒåµÄ·½·¨¾Í¼ÙÉèÕâЩרÓÐÊý¾ÝλÓÚ¶ÔÏóÍ·²¿£» ¼ÙÈç¶ÔÏóÍ·²¿Ã»ÓÐÕâЩרÓÐÊý¾Ý£¬ÕâЩ·½·¨¶ÔÕâ¸ö¶ÔÏóµÄ·ÃÎʾͿÉÄܳö´í¡£ ¶øSTATICMETHOD¶¨ÒåµÄ¶ÔÏó¿ÉÒÔ²»ÊÜÕâ¸öÏÞÖÆ£º ÕâÑùÃèÊö³öµÄ·½·¨£¬Æä²Ù×÷µÄÊý¾Ý²»ÓÉÕâ¸öÀàµÄij¸ö¶ÔÏóʵÀý¸ø³ö£¬ ¶øÊÇÈ«¶¼Óɵ÷ÓÃÕâ¸ö·½·¨Ê±µÄ²Ù×÷Êý(ÒëÕß×¢:¼´²ÎÊý)¸ø³ö¡£ ÕâÒ²¶ÔÓÚÔÚij¸öÀàµÄ·½·¨±íÖ®Íâµ÷ÓÃÕâ¸ö·½·¨ÓÐÓá£

ÒëÕß×¢: ÕâÒ»¶ÎµÄÓïÑÔÓëÔ­ÎÄÏà±Èµ÷ÕûºÜ´ó¡£ ¾²Ì¬·½·¨ÊDz»ÒÀÀµÓÚ¶ÔÏóʵÀýµÄ·½·¨¡£ ²Î¿´C++ÀàÖеġ°¾²Ì¬º¯Êý¡±µÄ¸ÅÄî¡£

¡¡¡¡ÆäËüÍêÕûµÄÀý×Ó:

src/sys/kern/bus_if.m
src/sys/kern/device_if.m

3.3.6 ½¨Á¢Ò»¸öÀà

¡¡¡¡Ê¹ÓÃKobjµÄµÚ¶þ²½Êǽ¨Á¢Ò»¸öÀà¡£Ò»¸öÀàµÄ×éÓÐÃû×Ö¡¢·½·¨±í£» ¼ÙÈçʹÓÃÁËKobjµÄ¡°¶ÔÏó¹ÜÀí¹¤¾ß¡±(Object Handling Facilities)£¬ ÀàÖл¹°üº¬¶ÔÏóµÄ´óС¡£½¨Á¢ÀàʱʹÓúêDEFINE_CLASS()¡£ ½¨Á¢·½·¨±íʱ£¬Ð뽨Á¢Ò»¸ökobj_method_tÊý×飬ÓÃNULLÏî½áβ¡£ ÿ¸ö·ÇNULLÏî¿ÉÓúêKOBJMETHOD()½¨Á¢¡£

¡¡¡¡ÀýÈç:

DEFINE_CLASS(fooclass, foomethods, sizeof(struct foodata));

kobj_method_t foomethods[] = {
	KOBJMETHOD(bar_doo, foo_doo),
	KOBJMETHOD(bar_foo, foo_foo),
	{ NULL, NULL}
};

¡¡¡¡ÀàÐë±»¡°±àÒ롱¡£¸ù¾Ý¸ÃÀà±»³õʼ»¯Ê±ÏµÍ³µÄ״̬£¬ ½«ÒªÓõ½Ò»¸ö¾²Ì¬·ÖÅäµÄ»º´æºÍ¡°²Ù×÷Êý±í¡±(ops table£¬ ÒëÕß×¢£º¼´¡°²ÎÊý±í¡±)¡£ÕâЩ²Ù×÷¿Éͨ¹ýÉùÃ÷Ò»¸ö½á¹¹Ìå struct kobj_ops²¢Ê¹Óà kobj_class_compile_static()£¬ »òÊÇֻʹÓÃkobj_class_compile()À´Íê³É¡£


3.3.7 ½¨Á¢Ò»¸ö¶ÔÏó

¡¡¡¡Ê¹ÓÃKobjµÄµÚÈý²½ÊǶ¨Òå¶ÔÏó¡£Kobj¶ÔÏó½¨Á¢³ÌÐò¼Ù¶¨Kobj רÓÐÊý¾ÝÔÚÒ»¸ö¶ÔÏóµÄÍ·²¿¡£Èç¹û²»ÊÇÈç´Ë£¬Ó¦µ±ÏÈ×ÔÐзÖÅä¶ÔÏó£¬ ÔÙʹÓÃkobj_init()³õʼ»¯¶ÔÏóÖеÄKobjרÓÐÊý¾Ý£» Æäʵ¿ÉÒÔʹÓÃkobj_create()·ÖÅä¶ÔÏó£¬ ²¢×Ô¶¯³õʼ»¯¶ÔÏóÖеÄKobjרÓÐÄÚÈÝ¡£kobj_init() Ò²¿ÉÒÔÓÃÀ´¸Ä±äÒ»¸ö¶ÔÏóËùʹÓõÄÀà¡£

¡¡¡¡½«KobjµÄÊý¾Ý¼¯³Éµ½¶ÔÏóÖÐҪʹÓúêKOBJ_FIELDS¡£

¡¡¡¡ÀýÈç

struct foo_data {
	KOBJ_FIELDS;
	foo_foo;
	foo_bar;
};

3.3.8 µ÷Ó÷½·¨

¡¡¡¡Ê¹ÓÃKobjµÄ×îºóÒ»²¿¾ÍÊÇͨ¹ýÉú³ÉµÄº¯Êýµ÷ÓöÔÏóÀàÖеķ½·¨¡£ µ÷ÓÃʱ£¬½Ó¿ÚÃûÓë·½·¨ÃûÓÃ'_'½ÓºÏ£¬¶øÇÒÈ«²¿Ê¹Óôóд×Öĸ¡£

¡¡¡¡ÀýÈ磬½Ó¿ÚÃûΪfoo£¬·½·¨Îªbar£¬µ÷ÓþÍÊÇ:

[·µ»ØÖµ = ] FOO_BAR(¶ÔÏó [, ÆäËü²ÎÊý]);

3.3.9 ÉÆºó´¦Àí

¡¡¡¡µ±Ò»¸öÓÃkobj_create()²»ÔÙÐèÒª±»Ê¹ÓÃʱ£¬ ¿É¶ÔÕâ¸ö¶ÔÏóµ÷ÓÃkobj_delete()¡£ µ±Ò»¸öÀ಻ÔÙÐèÒª±»Ê¹ÓÃʱ£¬ ¿É¶ÔÕâ¸öÀàµ÷ÓÃkobj_class_free()¡£


µÚ4Õ ¡¡Jail×Óϵͳ

Evan Sarmiento°æÈ¨ © 2001 Evan Sarmiento·­Ò룺intron@intron.ac.

¡¡¡¡ÔÚ´ó¶àÊýUNIX®ÏµÍ³ÖУ¬Óû§rootÊÇÍòÄܵġ£ÕâÒ²¾ÍÔö¼ÓÁËÐí¶àΣÏÕ¡£ Èç¹ûÒ»¸ö¹¥»÷Õß»ñµÃÁËÒ»¸öϵͳÖеÄroot£¬¾Í¿ÉÒÔÔÚËûµÄÖ¸¼âÕÆÎÕϵͳÖÐËùÓеŦÄÜ¡£ ÔÚFreeBSDÀÓÐһЩsysctlÏîÏ÷ÈõÁËrootµÄȨÏÞ£¬ ÕâÑù¾Í¿ÉÒÔ½«¹¥»÷ÕßÔì³ÉµÄË𺦼õСµ½×îµÍÏÞ¶È¡£ÕâЩ°²È«¹¦ÄÜÖУ¬ÓÐÒ»Öֽа²È«¼¶±ð¡£ ÁíÒ»ÖÖÔÚFreeBSD 4.0¼°ÒÔºó°æ±¾ÖÐÌṩµÄ°²È«¹¦ÄÜ£¬¾ÍÊÇjail(8)¡£ Jail½«Ò»¸öÔËÐл·¾³µÄÎļþÊ÷¸ùÇл»µ½Ä³Ò»Ìض¨Î»Ö㬠²¢ÇÒ¶ÔÕâÑù»·¾³Öвæ·ÖÉú³ÉµÄ½ø³Ì×ö³öÏÞÖÆ¡£ÀýÈ磬 Ò»¸ö±»¼à½ûµÄ½ø³Ì²»ÄÜÓ°ÏìÕâ¸öjailÖ®ÍâµÄ½ø³Ì¡¢²»ÄÜʹÓÃÒ»Ð©ÌØ¶¨µÄϵͳµ÷Ó㬠Ҳ¾Í²»ÄܶÔÖ÷¼ÆËã»úÔì³ÉÆÆ»µ¡£

ÒëÕß×¢: Ó¢Îĵ¥´Ê¡°jail¡±µÄÖÐÎÄÒâ˼ÊÇ¡°Çô½û¡¢¼à½û¡±¡£

¡¡¡¡JailÒѾ­³ÉΪһÖÖÐÂÐ͵ݲȫģÐÍ¡£ ÈËÃÇ¿ÉÒÔÔÚjailÖÐÔËÐи÷ÖÖ¿ÉÄܴܺàÈõµÄ·þÎñÆ÷³ÌÐò£¬ÈçApache¡¢ BINDºÍsendmail¡£ ÕâÑùÒ»À´£¬¼´Ê¹Óй¥»÷ÕßÈ¡µÃÁËjailÖеÄroot£¬ Õâ×î¶àÈÃÈËÃÇÖåÖåüͷ£¬¶ø²»»áʹÈËÃǾª»Åʧ´ë¡£ ±¾ÎÄÖ÷Òª¹Ø×¢jailµÄÄÚ²¿Ô­Àí(Ô´´úÂë)¡£ Èç¹ûÄãÕýÔÚѰÕÒÉèÖÃJailµÄÖ¸ÄÏÐÔÎĵµ£¬ ÎÒ½¨ÒéÄãÔĶÁÎÒµÄÁíһƪÎÄÕ£¬·¢±íÔÚSys Admin Magazine, May 2001, ¡¶Securing FreeBSD using Jail¡·¡£


4.1 JailµÄϵͳ½á¹¹

¡¡¡¡JailÓÉÁ½²¿·Ö×é³É£ºÓû§¼¶³ÌÐò£¬ Ò²¾ÍÊÇjail(8)£»»¹ÓÐÔÚÄÚºËÖÐJailµÄʵÏÖ´úÂ룺jail(2) ϵͳµ÷ÓúÍÏà¹ØµÄÔ¼Êø¡£ÎÒ½«ÌÖÂÛÓû§¼¶³ÌÐòºÍjailÔÚÄÚºËÖеÄʵÏÖÔ­Àí¡£


4.1.1 Óû§¼¶´úÂë

¡¡¡¡JailµÄÓû§¼¶Ô´´úÂëÔÚ/usr/src/usr.sbin/jail£¬ ÓÉÒ»¸öÎļþjail.c×é³É¡£Õâ¸ö³ÌÐòÓÐÕâЩ²ÎÊý£ºjailµÄ·¾¶£¬ Ö÷»úÃû£¬IPµØÖ·£¬»¹ÓÐÐèÒªÖ´ÐеÄÃüÁî¡£


4.1.1.1 Êý¾Ý½á¹¹

¡¡¡¡ÔÚjail.cÖУ¬ÎÒ½«×îÏÈ×¢½âµÄÊÇÒ»¸öÖØÒª½á¹¹Ìå struct jail j;µÄÉùÃ÷£¬Õâ¸ö½á¹¹ÀàÐ͵ÄÉùÃ÷°üº¬ÔÚ /usr/include/sys/jail.hÖ®ÖС£

¡¡¡¡jail½á¹¹µÄ¶¨ÒåÊÇ£º

/usr/include/sys/jail.h: 

struct jail {
        u_int32_t       version;
        char            *path;
        char            *hostname;
        u_int32_t       ip_number;
};

¡¡¡¡ÕýÈçÄãËù¼û£¬´«Ë͸øÃüÁîjail(8)µÄÿ¸ö²ÎÊý¶¼ÔÚÕâÀïÓжÔÓ¦µÄÒ»Ïî¡£ ÊÂʵÉÏ£¬µ±ÃüÁîjail(8)±»Ö´ÐÐʱ£¬ÕâЩ²ÎÊý²ÅÓÉÃüÁîÐÐÕæÕý´«È룺

/usr/src/usr.sbin/jail.c
char path[PATH_MAX];
...
if(realpath(argv[0], path) == NULL)
    err(1, "realpath: %s", argv[0]);
if (chdir(path) != 0)
    err(1, "chdir: %s", path);
memset(&j, 0, sizeof(j));
j.version = 0; 
j.path = path;
j.hostname = argv[1];

4.1.1.2 ÍøÂç

¡¡¡¡´«¸øjail(8)µÄ²ÎÊýÖÐÓÐÒ»¸öÊÇIPµØÖ·¡£ÕâÊÇÔÚÍøÂçÉÏ·ÃÎÊjailʱµÄµØÖ·¡£ jail(8)½«IPµØÖ··­Òë³ÉÍøÂç×Ö½Ú˳Ðò£¬²¢´æÈëj(jailÀàÐ͵ĽṹÌå)¡£

/usr/src/usr.sbin/jail/jail.c:
struct in_addr in; 
... 
if (inet_aton(argv[2], &in) == 0)
    errx(1, "Could not make sense of ip-number: %s", argv[2]);
j.ip_number = ntohl(in.s_addr);

¡¡¡¡º¯Êýinet_aton(3)¡°½«Ö¸¶¨µÄ×Ö·û´®½âÊÍΪһ¸öInternetµØÖ·£¬ ²¢½«Æäת´æµ½Ö¸¶¨µÄ½á¹¹ÌåÖС±¡£inet_aton(3)É趨Á˽ṹÌåin£¬ Ö®ºóinÖеÄÄÚÈÝÔÙÓÃntohl(3)ת»»³ÉÖ÷»ú×Ö½Ú˳Ðò£¬ ²¢ÖÃÈëjail½á¹¹ÌåµÄip_number³ÉÔ±¡£


4.1.1.3 Çô½û½ø³Ì

¡¡¡¡×îºó£¬Óû§¼¶³ÌÐòÇô½û½ø³Ì¡£ÏÖÔÚJail×ÔÉí±ä³ÉÁËÒ»¸ö±»Çô½ûµÄ½ø³Ì£¬ ²¢Ê¹ÓÃexecv(3)Ö´ÐÐÓû§Ö¸¶¨µÄÃüÁî¡£

/usr/src/usr.sbin/jail/jail.c
i = jail(&j); 
...
if (execv(argv[3], argv + 3) != 0)
    err(1, "execv: %s", argv[3]);

¡¡¡¡ÕýÈçÄãËù¼û£¬º¯Êýjail()±»µ÷Ó㬲ÎÊýÊǽṹÌåjailÖб»ÌîÈëÊý¾ÝÏ ¶øÈçǰËùÊö£¬ÕâЩÊý¾ÝÏîÓÖÀ´×Ôjail(8)µÄÃüÁîÐвÎÊý¡£ ×îºó£¬Ö´ÐÐÁËÓû§Ö¸¶¨µÄÃüÁî¡£ÏÂÃæÎÒ½«¿ªÊ¼ÌÖÂÛjailÔÚÄÚºËÖеÄʵÏÖ¡£


4.1.2 Ïà¹ØµÄÄÚºËÔ´´úÂë

¡¡¡¡ÏÖÔÚÎÒÃÇÀ´¿´Îļþ/usr/src/sys/kern/kern_jail.c¡£ ÔÚÕâÀﶨÒåÁËjail(2)µÄϵͳµ÷Óá¢Ïà¹ØµÄsysctlÏ»¹ÓÐÍøÂ纯Êý¡£


4.1.2.1 sysctlÏî

¡¡¡¡ÔÚkern_jail.cÀﶨÒåÁËÈçÏÂsysctlÏî:

/usr/src/sys/kern/kern_jail.c:

int     jail_set_hostname_allowed = 1;
SYSCTL_INT(_security_jail, OID_AUTO, set_hostname_allowed, CTLFLAG_RW,
    &jail_set_hostname_allowed, 0,
    "Processes in jail can set their hostnames");
    /* JailÖеĽø³Ì¿ÉÉ趨×ÔÉíµÄÖ÷»úÃû */

int     jail_socket_unixiproute_only = 1;
SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
    &jail_socket_unixiproute_only, 0,
    "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
    /* JailÖеĽø³Ì±»ÏÞÖÆÖ»Äܽ¨Á¢UNIXÌ×½Ó×Ö¡¢IPv4Ì×½Ó×Ö¡¢Â·ÓÉÌ×½Ó×Ö */

int     jail_sysvipc_allowed = 0;
SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
    &jail_sysvipc_allowed, 0,
    "Processes in jail can use System V IPC primitives");
    /* JailÖеĽø³Ì¿ÉÒÔʹÓÃSystem V½ø³Ì¼äͨѶԭÓï */

static int jail_enforce_statfs = 2;
SYSCTL_INT(_security_jail, OID_AUTO, enforce_statfs, CTLFLAG_RW,
    &jail_enforce_statfs, 0,
    "Processes in jail cannot see all mounted file systems");
    /* jail ÖеĽø³Ì²é¿´ÏµÍ³ÖйҽӵÄÎļþϵͳʱÊܵ½ºÎÖÖÏÞÖÆ */

int    jail_allow_raw_sockets = 0;
SYSCTL_INT(_security_jail, OID_AUTO, allow_raw_sockets, CTLFLAG_RW,
    &jail_allow_raw_sockets, 0,
    "Prison root can create raw sockets");
    /* jail ÖÐµÄ root Óû§ÊÇ·ñ¿ÉÒÔ´´½¨ raw socket */

int    jail_chflags_allowed = 0;
SYSCTL_INT(_security_jail, OID_AUTO, chflags_allowed, CTLFLAG_RW,
    &jail_chflags_allowed, 0,
    "Processes in jail can alter system file flags");
    /* jail ÖеĽø³ÌÊÇ·ñ¿ÉÒÔÐÞ¸Äϵͳ¼¶Îļþ±ê¼Ç */

int     jail_mount_allowed = 0;
SYSCTL_INT(_security_jail, OID_AUTO, mount_allowed, CTLFLAG_RW,
    &jail_mount_allowed, 0,
    "Processes in jail can mount/unmount jail-friendly file systems");
    /* jail ÖеĽø³ÌÊÇ·ñ¿ÉÒÔ¹ÒÔØ»òÐ¶ÔØ¶ÔjailÓѺõÄÎļþϵͳ */

¡¡¡¡ÕâЩsysctlÏîÖеÄÿһ¸ö¶¼¿ÉÒÔÓÃÃüÁîsysctl(8)·ÃÎÊ¡£ÔÚÕû¸öÄÚºËÖУ¬ ÕâЩsysctlÏî°´Ãû³Æ±êʶ¡£ÀýÈ磬ÉÏÊöµÚÒ»¸ösysctlÏîµÄÃû×ÖÊÇ security.jail.set_hostname_allowed¡£


4.1.2.2 jail(2)ϵͳµ÷ÓÃ

¡¡¡¡ÏñËùÓеÄϵͳµ÷ÓÃÒ»Ñù£¬ÏµÍ³µ÷ÓÃjail(2)´øÓÐÁ½¸ö²ÎÊý£¬ struct thread *tdºÍstruct jail_args *uap¡£ tdÊÇÒ»¸öÖ¸Ïòthread½á¹¹ÌåµÄÖ¸Õ룬¸ÃÖ¸ÕëÓÃÓÚÃèÊöµ÷ÓÃjail(2)µÄÏ̡߳£ ÔÚÕâ¸öÉÏÏÂÎÄÖУ¬uapÖ¸ÏòÒ»¸ö½á¹¹Ì壬Õâ¸ö½á¹¹ÌåÖаüº¬ÁËÒ»¸öÖ¸Ïò´ÓÓû§¼¶ jail.c´«Ë͹ýÀ´µÄjail½á¹¹ÌåµÄÖ¸Õë¡£ ÔÚÇ°ÃæÎÒ½²ÊöÓû§¼¶³ÌÐòʱ£¬ÄãÒѾ­¿´µ½¹ýÒ»¸öjail½á¹¹Ìå±»×÷Ϊ²ÎÊý´«Ë͸øÏµÍ³µ÷Óà jail(2)¡£

/usr/src/sys/kern/kern_jail.c:
/*
 * struct jail_args {
 *      struct jail *jail;
 * };
 */
int
jail(struct thread *td, struct jail_args *uap)

¡¡¡¡ÓÚÊÇuap->jail¿ÉÒÔÓÃÓÚ·ÃÎʱ»´«µÝ¸øjail(2)µÄjail½á¹¹Ìå¡£ È»ºó£¬jail(2)ʹÓÃcopyin(9)½«jail½á¹¹Ì叴֯µ½ÄÚºËÄÚ´æ¿Õ¼äÖС£ copyin(9)ÐèÒªÈý¸ö²ÎÊý£ºÒª¸´ÖƽøÄÚºËÄÚ´æ¿Õ¼äµÄÊý¾ÝµÄµØÖ· uap->jail£¬ÔÚÄÚºËÄÚ´æ¿Õ¼ä´æ·ÅÊý¾ÝµÄj£¬ ÒÔ¼°Êý¾ÝµÄ´óС¡£uap->jailÖ¸ÏòµÄJail½á¹¹Ìå±»¸´ÖƽøÄÚºËÄÚ´æ¿Õ¼ä£¬ ²¢±»´æ·ÅÔÚÁíÒ»¸öjail½á¹¹ÌåjÀï¡£

/usr/src/sys/kern/kern_jail.c: 
error = copyin(uap->jail, &j, sizeof(j));

¡¡¡¡ÔÚjail.hÖж¨ÒåÁËÁíÒ»¸öÖØÒªµÄ½á¹¹ÌåÐÍprison¡£ ½á¹¹ÌåprisonÖ»±»ÓÃÔÚÄں˿ռäÖС£ ÏÂÃæÊÇprison½á¹¹ÌåµÄ¶¨Òå¡£

/usr/include/sys/jail.h:
struct prison {
        LIST_ENTRY(prison) pr_list;                     /* (a) all prisons */
        int              pr_id;                         /* (c) prison id */
        int              pr_ref;                        /* (p) refcount */
        char             pr_path[MAXPATHLEN];           /* (c) chroot path */
        struct vnode    *pr_root;                       /* (c) vnode to rdir */
        char             pr_host[MAXHOSTNAMELEN];       /* (p) jail hostname */
        u_int32_t        pr_ip;                         /* (c) ip addr host */
        void            *pr_linux;                      /* (p) linux abi */
        int              pr_securelevel;                /* (p) securelevel */
        struct task      pr_task;                       /* (d) destroy task */
        struct mtx       pr_mtx;
        void            **pr_slots;                     /* (p) additional data */
};

¡¡¡¡È»ºó£¬ÏµÍ³µ÷ÓÃjail(2)Ϊһ¸öprison½á¹¹Ìå·ÖÅäÒ»¿éÄڴ棬 ²¢ÔÚjailºÍprison½á¹¹ÌåÖ®¼ä¸´ÖÆÊý¾Ý¡£

/usr/src/sys/kern/kern_jail.c:
MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO);
...
error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0);
if (error)
    goto e_killmtx;
...
error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
if (error)
        goto e_dropvnref;
pr->pr_ip = j.ip_number;

¡¡¡¡ÏÂÃæ£¬ÎÒÃǽ«ÌÖÂÛÁíÍâÒ»¸öÖØÒªµÄϵͳµ÷ÓÃjail_attach(2)£¬ËüʵÏÖÁ˽«½ø³Ì¼à½ûµÄ¹¦ÄÜ¡£

/usr/src/sys/kern/kern_jail.c
/*
 * struct jail_attach_args {
 *      int jid;
 * };
 */
int
jail_attach(struct thread *td, struct jail_attach_args *uap)

¡¡¡¡Õâ¸öϵͳµ÷ÓÃ×ö³öһЩ¿ÉÒÔÓÃÓÚÇø·Ö±»¼à½ûºÍδ±»¼à½ûµÄ½ø³ÌµÄ¸Ä±ä¡£ ÒªÀí½âjail_attach(2)ΪÎÒÃÇ×öÁËʲô£¬ÎÒÃÇÊ×ÏÈÒªÀí½âһЩ±³¾°ÐÅÏ¢¡£

¡¡¡¡ÔÚFreeBSDÖУ¬Ã¿¸ö¶ÔÄں˿ɼûµÄÏß³ÌÊÇͨ¹ýÆäthread½á¹¹ÌåÀ´Ê¶±ðµÄ£¬ ͬʱ£¬½ø³Ì¶¼ÓÉËüÃÇ×Ô¼ºµÄproc½á¹¹ÌåÃèÊö¡£ Äã¿ÉÒÔÔÚ/usr/include/sys/proc.hÖÐÕÒµ½threadºÍproc½á¹¹ÌåµÄ¶¨Òå¡£ ÀýÈ磬ÔÚÈκÎϵͳµ÷ÓÃÖУ¬²ÎÊýtdʵ¼ÊÉÏÊǸöÖ¸Ïòµ÷ÓÃÏ̵߳Äthread½á¹¹ÌåµÄÖ¸Õ룬 ÕýÈçÇ°ÃæËù˵µÄÄÇÑù¡£tdËùÖ¸ÏòµÄthread½á¹¹ÌåÖеÄtd_proc³ÉÔ±ÊÇÒ»¸öÖ¸Õ룬 Õâ¸öÖ¸ÕëÖ¸ÏòtdËù±íʾµÄÏß³ÌËùÊô½ø³ÌµÄproc½á¹¹Ìå¡£ ½á¹¹Ìåproc°üº¬µÄ³ÉÔ±¿ÉÒÔÃèÊöËùÓÐÕßµÄÉí·Ý (p_ucred)£¬½ø³Ì×ÊÔ´ÏÞÖÆ(p_limit)£¬ µÈµÈ¡£ÔÚÓÉproc½á¹¹ÌåµÄp_ucred³ÉÔ±ËùÖ¸ÏòµÄucred½á¹¹ÌåµÄ¶¨ÒåÖУ¬ »¹ÓÐÒ»¸öÖ¸Ïòprison½á¹¹ÌåµÄÖ¸Õë(cr_prison)¡£

/usr/include/sys/proc.h: 
struct thread {
    ...
    struct proc *td_proc;
    ...
};
struct proc {
    ...
    struct ucred *p_ucred;
    ...
};
/usr/include/sys/ucred.h
struct ucred {
    ...
    struct prison *cr_prison;
    ...
};

¡¡¡¡ÔÚkern_jail.cÖУ¬º¯Êýjail()ÒÔ¸ø¶¨µÄjid µ÷Óú¯Êýjail_attach()¡£Ëæºójail_attach()µ÷Óú¯Êýchange_root()ÒÔ¸Ä±ä µ÷Óýø³ÌµÄ¸ùĿ¼¡£½ÓÏÂÀ´£¬jail_attach()´´½¨Ò»¸öеÄucred½á¹¹Ì壬²¢ÔÚ ³É¹¦µØ½«prison½á¹¹ÌåÁ¬½Óµ½Õâ¸öucred½á¹¹Ìåºó£¬½«Õâ¸öucred½á¹¹ÌåÁ¬½Ó µ½µ÷Óýø³ÌÉÏ¡£´Ó´ËʱÆð£¬Õâ¸öµ÷Óýø³Ì¾Í»á±»Ê¶±ðΪ±»¼à½ûµÄ¡£ µ±ÎÒÃÇÒÔд´½¨µÄÕâ¸öucred½á¹¹ÌåΪ²ÎÊýµ÷ÓÃÄں˷¾¶jailed()ʱ£¬ Ëü½«·µ»Ø1À´ËµÃ÷Õâ¸öÓû§Éí·ÝÊǺÍÒ»¸öjailÏàÁ¬µÄ¡£ ÔÚjailÖвæ·Ö³öÀ´µÄËùÓнø³ÌµÄµÄ¹«¹²×æÏȽø³Ì¾ÍÊÇÕâ¸öÖ´ÐÐÁËjail(2)µÄ½ø³Ì£¬ ÒòΪÕýÊÇËüµ÷ÓÃÁËjail(2)ϵͳµ÷Óᣵ±Ò»¸ö³ÌÐòͨ¹ýexecve(2)¶ø±»Ö´ÐÐʱ£¬ Ëü½«´ÓÆä¸¸½ø³ÌµÄucred½á¹¹Ìå¼Ì³Ð±»¼à½ûµÄÊôÐÔ£¬ Òò¶øËüÒ²»áÓµÓÐÒ»¸ö±»¼à½ûµÄucred½á¹¹Ìå¡£

/usr/src/sys/kern/kern_jail.c
int
jail(struct thread *td, struct jail_args *uap)
{
...
    struct jail_attach_args jaa;
...
    error = jail_attach(td, &jaa);
    if (error)
        goto e_dropprref;
...
}
  
int
jail_attach(struct thread *td, struct jail_attach_args *uap)
{
    struct proc *p;
    struct ucred *newcred, *oldcred;
    struct prison *pr;
...
    p = td->td_proc;
...
    pr = prison_find(uap->jid);
...
    change_root(pr->pr_root, td);
...
    newcred->cr_prison = pr;
    p->p_ucred = newcred;
...
}

¡¡¡¡µ±Ò»¸ö½ø³Ì±»´ÓÆä¸¸½ø³Ì²æ·ÖÀ´µÄʱºò£¬ ϵͳµ÷ÓÃfork(2)½«ÓÃcrhold()À´Î¬»¤ÆäÉí·Ýƾ֤¡£ ÕâÑù£¬ºÜ×ÔÈ»µÄ¾Í±£³ÖÁË×Ó½ø³ÌµÄÉí·Ýƾ֤ÓÚÆä¸¸½ø³ÌÒ»Ö£¬ËùÒÔ×Ó½ø³ÌÒ²ÊDZ»¼à½ûµÄ¡£

/usr/src/sys/kern/kern_fork.c:
p2->p_ucred = crhold(td->td_ucred);
...
td2->td_ucred = crhold(p2->p_ucred);

4.2 ϵͳ¶Ô±»Çô½û³ÌÐòµÄÏÞÖÆ

¡¡¡¡ÔÚÕû¸öÄÚºËÖУ¬ÓÐһϵÁжԱ»Çô½û³ÌÐòµÄÔ¼Êø´ëÊ©¡£ ͨ³££¬ÕâÐ©Ô¼ÊøÖ»¶Ô±»Çô½ûµÄ³ÌÐòÓÐЧ¡£Èç¹ûÕâЩ³ÌÐòÊÔÍ¼Í»ÆÆÕâÐ©Ô¼Êø£¬ Ïà¹ØµÄº¯Êý½«³ö´í·µ»Ø¡£ÀýÈç:

if (jailed(td->td_ucred)) 
    return EPERM;

4.2.1 SysV½ø³Ì¼äͨÐÅ(IPC)

¡¡¡¡System V ½ø³Ì¼äͨÐÅ (IPC) ÊÇͨ¹ýÏûϢʵÏֵġ£ ÿ¸ö½ø³Ì¶¼¿ÉÒÔÏòÆäËü½ø³Ì·¢ËÍÏûÏ¢£¬ ¸æËß¶Ô·½¸Ã×öʲô¡£ ´¦ÀíÏûÏ¢µÄº¯ÊýÊÇ£º msgctl(3)¡¢msgget(3)¡¢msgsnd(3) ºÍ msgrcv(3)¡£Ç°ÃæÒѾ­Ìáµ½£¬Ò»Ð© sysctl ¿ª¹Ø¿ÉÒÔÓ°Ïì jail µÄÐÐΪ£¬ ÆäÖÐÓÐÒ»¸öÊÇ security.jail.sysvipc_allowed¡£ ÔÚ´ó¶àÊýϵͳÉÏ£¬ Õâ¸ö sysctl Ïî»áÉè³É0¡£ Èç¹û½«ËüÉèΪ1£¬ Ôò»áÍêȫʧȥ jail µÄÒâÒ壺 ÒòΪÄÇÑùÔÚ jail ÖÐÌØÈ¨½ø³Ì¾Í¿ÉÒÔÓ°Ïì±»¼à½ûµÄ»·¾³ÍâµÄ½ø³ÌÁË¡£ ÏûÏ¢ÓëÐźŵÄÇø±ðÊÇ£ºÏûÏ¢½öÓÉÒ»¸öÐźűàºÅ×é³É¡£

¡¡¡¡/usr/src/sys/kern/sysv_msg.c:

  • msgget(key, msgflg): msgget·µ»Ø(Ò²¿ÉÄÜ´´½¨)Ò»¸öÏûÏ¢ÃèÊö·û£¬ ÒÔÖ¸ÅÉÒ»¸öÔÚÆäËüº¯ÊýÖÐʹÓõÄÏûÏ¢¶ÓÁС£

  • msgctl(msgid, cmd, buf): ͨ¹ýÕâ¸öº¯Êý£¬ Ò»¸ö½ø³Ì¿ÉÒÔ²éѯһ¸öÏûÏ¢ÃèÊö·ûµÄ״̬¡£

  • msgsnd(msgid, msgp, msgsz, msgflg): msgsndÏòÒ»¸ö½ø³Ì·¢ËÍÒ»ÌõÏûÏ¢¡£

  • msgrcv(msgid, msgp, msgsz, msgtyp, msgflg): ½ø³ÌÓÃÕâ¸öº¯Êý½ÓÊÕÏûÏ¢¡£

¡¡¡¡ÔÚÕâЩº¯Êý¶ÔÓ¦µÄϵͳµ÷ÓõĴúÂëÖУ¬¶¼ÓÐÕâÑùÒ»¸öÌõ¼þÅжϣº

/usr/src/sys/kern/sysv_msg.c:
if (!jail_sysvipc_allowed && jailed(td->td_ucred))
    return (ENOSYS);

¡¡¡¡ÐźÅÁ¿ÏµÍ³µ÷ÓÃʹµÃ½ø³Ì¿ÉÒÔͨ¹ýһϵÁÐÔ­×Ó²Ù×÷ʵÏÖͬ²½¡£ ÐźÅÁ¿Îª½ø³ÌËø¶¨×ÊÔ´ÌṩÁËÓÖÒ»ÖÖ;¾¶¡£ È»¶ø£¬½ø³Ì½«ÎªÕýÔÚ±»Ê¹ÓõÄÐźÅÁ¿½øÈëµÈ´ý״̬£¬Ò»Ö±ÐÝÃßµ½×ÊÔ´±»ÊÍ·Å¡£ ÔÚjailÖÐÈçϵÄÐźÅÁ¿ÏµÍ³µ÷Óý«»áʧЧ: semget(2), semctl(2) ºÍsemop(2)¡£

¡¡¡¡/usr/src/sys/kern/sysv_sem.c:

  • semctl(semid, num, cmd, ...): semctl¶ÔÔÚÐźÅÁ¿¶ÓÁÐÖÐÓÃsemid±êʶµÄÐźÅÁ¿Ö´ÐÐcmdÖ¸¶¨µÄÃüÁî¡£

  • semget(key, nsems, flag): semget½¨Á¢Ò»¸ö¶ÔÓ¦ÓÚkeyµÄÐźÅÁ¿Êý×é¡£

    ²ÎÊýkeyºÍflagÓëËûÃÇÔÚmsgget()µÄÒâÒåÏàͬ¡£

  • setop(semid, array, nops): semop¶Ôsemid±êʶµÄÐźÅÁ¿Íê³ÉÒ»×éÓÉarrayËùÖ¸¶¨µÄ²Ù×÷¡£

¡¡¡¡System V IPCʹ½ø³Ì¼ä¿ÉÒÔ¹²ÏíÄÚ´æ¡£½ø³ÌÖ®¼ä¿ÉÒÔͨ¹ýËüÃÇÐéÄâµØÖ·¿Õ¼ä µÄ¹²Ïí²¿·ÖÒÔ¼°Ïà¹ØÊý¾Ý¶Áд²Ù×÷Ö±½ÓͨѶ¡£ÕâЩϵͳµ÷ÓÃÔÚ±»¼à½ûµÄ»·¾³Öн«»áʧЧ: shmdt(2)¡¢shmat(2)¡¢shmctl(2)ºÍshmget(2)

¡¡¡¡/usr/src/sys/kern/sysv_shm.c:

  • shmctl(shmid, cmd, buf): shmctl¶Ôid±êʶµÄ¹²ÏíÄÚ´æÇøÓò×ö¸÷ÖÖ¸÷ÑùµÄ¿ØÖÆ¡£

  • shmget(key, size, flag): shmget½¨Á¢/´ò¿ªsize×ֽڵĹ²ÏíÄÚ´æÇøÓò¡£

  • shmat(shmid, addr, flag): shmat½«shmid±êʶµÄ¹²ÏíÄÚ´æÇøÓòÖ¸Åɵ½½ø³ÌµÄµØÖ·¿Õ¼äÀï¡£

  • shmdt(addr): shmdtÈ¡Ïû¹²ÏíÄÚ´æÇøÓòµÄµØÖ·Ö¸ÅÉ¡£


4.2.2 Ì×½Ó×Ö

¡¡¡¡JailÒÔÒ»ÖÖÌØÊâµÄ·½Ê½´¦Àísocket(2)ϵͳµ÷ÓúÍÏà¹ØµÄµÍ¼¶Ì×½Ó×Öº¯Êý¡£ ΪÁ˾ö¶¨Ò»¸öÌ×½Ó×ÖÊÇ·ñÔÊÐí±»´´½¨£¬ËüÏȼì²ésysctlÏî security.jail.socket_unixiproute_onlyÊÇ·ñ±»ÉèÖÃΪ1¡£ Èç¹û±»ÉèΪ1£¬Ì×½Ó×Ö½¨Á¢Ê±½«Ö»ÄÜÖ¸¶¨ÕâЩЭÒé×壺 PF_LOCAL, PF_INET, PF_ROUTE¡£·ñÔò£¬socket(2)½«»á·µ»Ø³ö´í¡£

/usr/src/sys/kern/uipc_socket.c:
int
socreate(int dom, struct socket **aso, int type, int proto,
    struct ucred *cred, struct thread *td)
{
    struct protosw *prp;
...
    if (jailed(cred) && jail_socket_unixiproute_only &&
        prp->pr_domain->dom_family != PF_LOCAL &&
        prp->pr_domain->dom_family != PF_INET &&
        prp->pr_domain->dom_family != PF_ROUTE) {
        return (EPROTONOSUPPORT);
    }
...
}

4.2.3 Berkeley°ü¹ýÂËÆ÷

¡¡¡¡Berkeley°ü¹ýÂËÆ÷ÌṩÁËÒ»¸öÓëЭÒéÎ޹صģ¬Ö±½ÓͨÏòÊý¾ÝÁ´Â·²ãµÄµÍ¼¶½Ó¿Ú¡£ ÏÖÔÚBPFÊÇ·ñ¿ÉÒÔÔÚ¼à½ûµÄ»·¾³Öб»Ê¹ÓÃÊÇͨ¹ýdevfs(8)À´¿ØÖƵġ£


4.2.4 ÍøÂçЭÒé

¡¡¡¡ÍøÂçЭÒéTCP, UDP, IPºÍICMPºÜ³£¼û¡£IPºÍICMP´¦ÓÚͬһЭÒé²ã´Î£ºµÚ¶þ²ã£¬ ÍøÂç²ã¡£µ±²ÎÊýnam±»ÉèÖÃʱ£¬ ÓÐһЩÏÞÖÆ´ëÊ©»á·ÀÖ¹±»Çô½ûµÄ³ÌÐò°ó¶¨µ½Ò»Ð©ÍøÂç½Ó¿ÚÉÏ¡£ namÊÇÒ»¸öÖ¸Ïòsockaddr½á¹¹ÌåµÄÖ¸Õ룬 ÃèÊö¿ÉÒ԰󶨷þÎñµÄµØÖ·¡£Ò»¸ö¸üÈ·Çе͍Ò壺sockaddr¡°ÊÇÒ»¸öÄ£°å£¬°üº¬Á˵ØÖ·µÄ±êʶ·ûºÍµØÖ·µÄ³¤¶È¡±¡£ ÔÚº¯Êýin_pcbbind_setup()ÖÐsinÊÇÒ»¸öÖ¸Ïòsockaddr_in½á¹¹ÌåµÄÖ¸Õ룬 Õâ¸ö½á¹¹Ìå°üº¬ÁËÌ×½Ó×Ö¿ÉÒ԰󶨵Ķ˿ڡ¢µØÖ·¡¢³¤¶È¡¢Ð­Òé×å¡£ Õâ¾Í½ûÖ¹ÁËÔÚjailÖеĽø³ÌÖ¸¶¨²»ÊôÓÚÕâ¸ö½ø³ÌËù´æÔÚÓÚµÄjailµÄIPµØÖ·¡£

/usr/src/sys/kern/netinet/in_pcb.c: 
int
in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
    u_short *lportp, struct ucred *cred)
{
    ...
    struct sockaddr_in *sin;
    ...
    if (nam) {
        sin = (struct sockaddr_in *)nam;
        ...
        if (sin->sin_addr.s_addr != INADDR_ANY)
            if (prison_ip(cred, 0, &sin->sin_addr.s_addr))
                return(EINVAL);
        ...
        if (lport) {
            ...
            if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr))
                return (EADDRNOTAVAIL);
            ...
        }
    }
    if (lport == 0) {
        ...
        if (laddr.s_addr != INADDR_ANY)
            if (prison_ip(cred, 0, &laddr.s_addr))
                return (EINVAL);
        ...
    }
...
    if (prison_ip(cred, 0, &laddr.s_addr))
        return (EINVAL);
...
}

¡¡¡¡ÄãÒ²ÐíÏëÖªµÀº¯Êýprison_ip()×öʲô¡£ prison_ip()ÓÐÈý¸ö²ÎÊý£¬Ò»¸öÖ¸ÏòÉí·Ýƾ֤µÄÖ¸Õë(ÓÃcred±íʾ)£¬ һЩ±êÖ¾ºÍÒ»¸öIPµØÖ·¡£µ±Õâ¸öIPµØÖ·²»ÊôÓÚÕâ¸öjailʱ£¬·µ»Ø1£» ·ñÔò·µ»Ø0¡£ÕýÈçÄã´Ó´úÂëÖп´¼ûµÄ£¬Èç¹û£¬ÄǸöIPµØÖ·È·Êµ²»ÊôÓÚÕâ¸öjail£¬ ¾Í²»ÔÙÔÊÐíÏòÕâ¸öÍøÂçµØÖ·°ó¶¨Ð­Òé¡£

/usr/src/sys/kern/kern_jail.c:
int
prison_ip(struct ucred *cred, int flag, u_int32_t *ip)
{
    u_int32_t tmp;

    if (!jailed(cred))
        return (0);
    if (flag)
        tmp = *ip;
    else
        tmp = ntohl(*ip);
    if (tmp == INADDR_ANY) {
        if (flag)
            *ip = cred->cr_prison->pr_ip;
        else
            *ip = htonl(cred->cr_prison->pr_ip);
        return (0);
    }
    if (tmp == INADDR_LOOPBACK) {
        if (flag)
            *ip = cred->cr_prison->pr_ip;
        else
            *ip = htonl(cred->cr_prison->pr_ip);
        return (0);
    }
    if (cred->cr_prison->pr_ip != tmp)
        return (1);
    return (0);
}

4.2.5 Îļþϵͳ

¡¡¡¡Èç¹ûÍêÈ«¼¶±ð´óÓÚ0£¬¼´±ãÊÇjailÀïÃæµÄroot£¬ Ò²²»ÔÊÐíÔÚJailÖÐÈ¡Ïû»ò¸ü¸ÄÎļþ±êÖ¾£¬Èç¡°²»¿ÉÐ޸ġ±¡¢¡°Ö»¿ÉÌí¼Ó¡±¡¢¡°²»¿Éɾ³ý¡±±êÖ¾¡£

/usr/src/sys/ufs/ufs/ufs_vnops.c:
static int
ufs_setattr(ap)
    ...
{
    ...
        if (!priv_check_cred(cred, PRIV_VFS_SYSFLAGS, 0)) {
            if (ip->i_flags
                & (SF_NOUNLINK | SF_IMMUTABLE | SF_APPEND)) {
                    error = securelevel_gt(cred, 0);
                    if (error)
                        return (error);
            }
            ...
        }
}
/usr/src/sys/kern/kern_priv.c
int
priv_check_cred(struct ucred *cred, int priv, int flags)
{
    ...
    error = prison_priv_check(cred, priv);
    if (error)
        return (error);
    ...
}
/usr/src/sys/kern/kern_jail.c
int
prison_priv_check(struct ucred *cred, int priv)
{
    ...
    switch (priv) {
    ...
    case PRIV_VFS_SYSFLAGS:
        if (jail_chflags_allowed)
            return (0);
        else
            return (EPERM);
    ...
    }
    ...
}

µÚ5Õ ¡¡SYSINIT¿ò¼Ü

·­Ò룺intron@intron.ac.

¡¡¡¡SYSINITÊÇÒ»¸öͨÓõĵ÷ÓÃÅÅÐòÓë·Ö±ðÖ´ÐлúÖÆµÄ¿ò¼Ü¡£ FreeBSDĿǰʹÓÃËüÀ´½øÐÐÄں˵Ķ¯Ì¬³õʼ»¯¡£ SYSINITʹµÃFreeBSDµÄÄں˸÷×Óϵͳ¿ÉÒÔÔÚÄں˻òÄ£¿é¶¯Ì¬¼ÓÔØÁ´½Óʱ±»ÖØÕû¡¢ Ìí¼Ó¡¢É¾³ý¡¢Ìæ»»£¬ÕâÑù£¬Äں˺ÍÄ£¿é¼ÓÔØÊ±¾Í²»±ØÈ¥ÐÞ¸ÄÒ»¸ö¾²Ì¬µÄÓÐÐò³õʼ»¯ °²ÅűíÉõÖÁÖØÐ±àÒëÄںˡ£Õâ¸öÌåϵҲʹµÃÄÚºËÄ£¿é (ÏÖÔÚ³ÆÎªKLD¿ÉÒÔÓëÄں˲»Í¬Ê±±àÒë¡¢Á´½Ó¡¢ ÔÚÒýµ¼ÏµÍ³Ê±¼ÓÔØ£¬ÉõÖÁÔÚϵͳÔËÐÐʱ¼ÓÔØ¡£ÕâЩ²Ù×÷ÊÇͨ¹ý ¡°ÄÚºËÁ´½ÓÆ÷¡±(kernel linker)ºÍ¡°Á´½ÓÆ÷¼¯ºÏ¡± (linker set)Íê³ÉµÄ¡£


5.1 ÊõÓï

Á´½ÓÆ÷¼¯ºÏ(Linker Set)

Ò»ÖÖÁ´½Ó·½·¨¡£ÕâÖÖ·½·¨½«Õû¸ö³ÌÐòÔ´ÎļþÖо²Ì¬ÉêÃ÷µÄÊý¾ÝÊÕ¼¯µ½ Ò»¸ö¿ÉÁÚ½üѰַµÄÊý¾Ýµ¥ÔªÖС£


5.2 SYSINIT²Ù×÷

¡¡¡¡SYSINITÒªÒÀ¿¿Á´½ÓÆ÷»ñÈ¡±é²¼Õû¸ö³ÌÐòÔ´´úÂë¶à´¦ÉêÃ÷µÄ¾²Ì¬Êý¾Ý ²¢°ÑËüÃÇ×é³ÉÒ»¸ö±Ë´ËÏàÁÚµÄÊý¾Ý¿é¡£ÕâÖÖÁ´½Ó·½·¨±»³ÆÎª ¡°Á´½ÓÆ÷¼¯ºÏ¡±(linker set)¡£ SYSINITʹÓÃÁ½¸öÁ´½ÓÆ÷¼¯ºÏÒÔά»¤Á½¸öÊý¾Ý¼¯ºÏ£¬ °üº¬Ã¿¸öÊý¾ÝÌõÄ¿µÄµ÷ÓÃ˳Ðò¡¢º¯Êý¡¢Ò»¸ö»á±»Ìá½»¸ø¸Ãº¯ÊýµÄÊý¾ÝÖ¸Õë¡£

¡¡¡¡SYSINIT°´ÕÕÁ½ÀàÓÅÏȼ¶±êʶ¶Ôº¯ÊýÅÅÐòÒÔ±ãÖ´ÐС£ µÚÒ»ÀàÓÅÏȼ¶µÄ±êʶÊÇ×ÓϵͳµÄ±êʶ£¬ ¸ø³öSYSINIT·Ö±ðÖ´ÐÐ×ÓϵͳµÄº¯ÊýµÄÈ«¾Ö˳Ðò£¬ ¶¨ÒåÔÚ<sys/kernel.h>ÖеÄö¾Ù sysinit_sub_idÄÚ¡£µÚ¶þÀàÓÅÏȼ¶±êʶÔÚ×ÓϵͳÖеÄÔªËØµÄ˳Ðò£¬ ¶¨ÒåÔÚ<sys/kernel.h>ÖеÄö¾Ù sysinit_elem_orderÄÚ¡£

¡¡¡¡ÓÐÁ½ÖÖʱ¿ÌÐèҪʹÓÃSYSINIT£ºÏµÍ³Æô¶¯»òÄÚºËÄ£¿é¼ÓÔØÊ±£¬ ϵͳÎö¹¹»òÄÚºËÄ£¿éÐ¶ÔØÊ±¡£ÄÚºË×Óϵͳͨ³£ÔÚϵͳÆô¶¯Ê±Ê¹ÓÃSYSINIT µÄ¶¨ÒåÏîÒÔ³õʼ»¯Êý¾Ý½á¹¹¡£ÀýÈ磬½ø³Ìµ÷¶È×ÓϵͳʹÓÃÒ»¸öSYSINIT ¶¨ÒåÏîÀ´³õʼ»¯ÔËÐжÓÁÐÊý¾Ý½á¹¹¡£É豸Çý¶¯³ÌÐòÓ¦±ÜÃâÖ±½ÓʹÓà SYSINIT()£¬¶ÔÓÚ×ÜÏ߽ṹÉϵÄÎïÀíÕæÊµÉ豸ӦʹÓà DRIVER_MODULE()µ÷Óõĺ¯ÊýÏÈÕì²âÉ豸µÄ´æÔÚ£¬ Èç¹û´æÔÚ£¬ÔÙ½øÐÐÉ豸µÄ³õʼ»¯¡£Õâһϵͳ¹ý³ÌÖУ¬ »á×öһЩרÃÅÕë¶ÔÉ豸µÄÊÂÇ飬Ȼºóµ÷ÓÃSYSINIT()±¾Éí¡£ ¶ÔÓÚ·Ç×ÜÏ߽ṹһ²¿·ÖµÄÐéÉ豸£¬Ó¦¸ÄÓÃDEV_MODULE()¡£


5.3 ʹÓÃSYSINIT

5.3.1 ½Ó¿Ú

5.3.1.1 Í·Îļþ

<sys/kernel.h>

5.3.1.2 ºê

SYSINIT(uniquifier, subsystem, order, func, ident)
SYSUNINIT(uniquifier, subsystem, order, func, ident)

5.3.2 Æô¶¯

¡¡¡¡ºêSYSINIT()ÔÚSYSINITÆô¶¯Êý¾Ý¼¯ºÏÖÐ ½¨Á¢Ò»¸öSYSINITÊý¾ÝÏÒÔ±ãSYSINITÔÚϵͳÆô¶¯»òÄ£¿é¼ÓÔØÊ±ÅÅÐò ²¢Ö´ÐÐÆäÖеĺ¯Êý¡£SYSINIT()ÓÐÒ»¸ö²ÎÊýuniquifier£¬ SYSINITÓÃËüÀ´±êʶÊý¾ÝÏî£¬ËæºóÊÇ×Óϵͳ˳ÐòºÅ¡¢×ÓÏµÍ³ÔªËØË³ÐòºÅ¡¢ ´ýµ÷Óú¯Êý¡¢´«µÝ¸øº¯ÊýµÄÊý¾Ý¡£ËùÓеĺ¯Êý±ØÐëÓÐÒ»¸öºãÁ¿Ö¸Õë²ÎÊý¡£

Àý 5-1. SYSINIT()µÄÀý×Ó

#include <sys/kernel.h>

void foo_null(void *unused)
{
        foo_doo();
}
SYSINIT(foo, SI_SUB_FOO, SI_ORDER_FOO, foo_null, NULL);

struct foo foo_voodoo = {
        FOO_VOODOO;
}

void foo_arg(void *vdata)
{
        struct foo *foo = (struct foo *)vdata;
        foo_data(foo);
}
SYSINIT(bar, SI_SUB_FOO, SI_ORDER_FOO, foo_arg, &foo_voodoo);
	

¡¡¡¡×¢Ò⣬SI_SUB_FOOºÍSI_ORDER_FOO Ó¦µ±·Ö±ðÔÚÉÏÃæÌáµ½µÄö¾Ùsysinit_sub_idºÍ sysinit_elem_orderÖ®ÖС£¼È¿ÉÒÔʹÓÃÒÑÓеÄö¾ÙÏ Ò²¿ÉÒÔ½«×Ô¼ºµÄö¾ÙÏîÌí¼Óµ½ÕâÁ½¸öö¾ÙµÄ¶¨ÒåÖ®ÖС£ Äã¿ÉÒÔʹÓÃÊýѧ±í´ïʽ΢µ÷SYSINITµÄÖ´ÐÐ˳Ðò¡£ ÒÔϵÄÀý×ÓʾÀýÁËÒ»¸öÐèÒª¸ÕºÃÒªÔÚÄں˲ÎÊýµ÷ÕûµÄSYSINIT֮ǰִÐеÄSYSINIT¡£

Àý 5-2. µ÷ÕûSYSINIT()˳ÐòµÄÀý×Ó

static void
mptable_register(void *dummy __unused)
{

	apic_register_enumerator(&mptable_enumerator);
}

SYSINIT(mptable_register, SI_SUB_TUNABLES - 1, SI_ORDER_FIRST,
    mptable_register, NULL);

5.3.3 Îö¹¹

¡¡¡¡ºêSYSUNINIT()µÄÐÐΪÓëSYSINIT()µÄÏ൱£¬ Ö»ÊÇËü½«Êý¾ÝÏîÌî¼ÓÖÁSYSINITµÄÎö¹¹Êý¾Ý¼¯ºÏ¡£

Àý 5-3. SYSUNINIT()µÄÀý×Ó

#include <sys/kernel.h>

void foo_cleanup(void *unused)
{
        foo_kill();
}
SYSUNINIT(foobar, SI_SUB_FOO, SI_ORDER_FOO, foo_cleanup, NULL);

struct foo_stack foo_stack = {
        FOO_STACK_VOODOO;
}

void foo_flush(void *vdata)
{
}
SYSUNINIT(barfoo, SI_SUB_FOO, SI_ORDER_FOO, foo_flush, &foo_stack);
	

µÚ6Õ ¡¡TrustedBSD MAC ¿ò¼Ü

Chris Costello ºÍ Robert Watson. ·­Ò룺coolcoold.

6.1 MAC Îĵµ°æÈ¨ÉùÃ÷

¡¡¡¡±¾ÎĵµÊÇ×÷Ϊ DARPA CHATS Ñо¿¼Æ»®µÄÒ»²¿·Ö£¬Óɹ©Ö°ÓÚ Security Research Division of Network Associates ¹«Ë¾Safeport Network Services and Network Associates Laboratories µÄChris CostelloÒÀ¾Ý DARPA/SPAWAR ºÏͬ N66001-01-C-8035 (¡°CBOSS¡±)£¬Îª FreeBSD ÏîÄ¿±àдµÄ¡£

¡¡¡¡Redistribution and use in source (SGML DocBook) and 'compiled' forms (SGML, HTML, PDF, PostScript, RTF and so forth) with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code (SGML DocBook) must retain the above copyright notice, this list of conditions and the following disclaimer as the first lines of this file unmodified.

  2. Redistributions in compiled form (transformed to other DTDs, converted to PDF, PostScript, RTF and other formats) must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

ÖØÒª: THIS DOCUMENTATION IS PROVIDED BY THE NETWORKS ASSOCIATES TECHNOLOGY, INC "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NETWORKS ASSOCIATES TECHNOLOGY, INC BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

ÖØÒª: ±¾ÎÄÖÐÐí¿ÉÖ¤µÄ·Ç¹Ù·½ÖÐÎÄ·­Òë½ö¹©²Î¿¼£¬ ²»×÷ΪÅж¨ÈκÎÔðÈεÄÒÀ¾Ý¡£ÈçÓëÓ¢ÎÄÔ­ÎÄÓгöÈ룬ÔòÒÔÓ¢ÎÄÔ­ÎÄΪ׼¡£

¡¡¡¡ÔÚÂú×ãÏÂÁÐÐí¿ÉÌõ¼þµÄǰÌáÏ£¬ÔÊÐíÔÙ·Ö·¢»òÒÔÔ´´úÂë (SGML DocBook) »ò ¡°±àÒ롱 (SGML, HTML, PDF, PostScript, RTF µÈ) µÄ¾­¹ýÐ޸ĻòδÐ޸ĵÄÐÎʽ£º

  1. ÔÙ·Ö·¢Ô´´úÂë (SGML DocBook) ±ØÐë²»¼ÓÐ޸ĵı£ÁôÉÏÊö°æÈ¨¸æÊ¾¡¢±¾Ìõ¼þÇåµ¥ºÍÏÂÊöÆúȨÊé×÷Ϊ¸ÃÎļþµÄ×îÏÈÈô¸ÉÐС£

  2. ÔÙ·Ö·¢±àÒëµÄÐÎʽ (ת»»ÎªÆäËüDTD¡¢ PDF¡¢ PostScript¡¢ RTF »òÆäËüÐÎʽ)£¬±ØÐ뽫ÉÏÊö°æÈ¨¸æÊ¾¡¢ ±¾Ìõ¼þÇåµ¥ºÍÏÂÊöÆúȨÊ鏴֯µ½Óë·Ö·¢Æ·Ò»Í¬ÌṩµÄÎļþ£¬ÒÔ¼°ÆäËü²ÄÁÏÖС£

ÖØÒª: ±¾ÎĵµÓÉ NETWORKS ASSOCIATES TECHNOLOGY, INC ¡°°´ÏÖ×´Ìõ¼þ¡±Ìṩ£¬²¢ÔÚ´ËÃ÷ʾ²»ÌṩÈκÎÃ÷ʾ»ò°µÊ¾µÄ±£ÕÏ£¬ °üÀ¨µ«²»ÏÞÓÚ¶ÔÉÌÒµÊÊÏúÐÔ¡¢¶ÔÌØ¶¨Ä¿µÄµÄÊÊÓÃÐԵݵʾ±£ÕÏ¡£ÈκÎÇé¿öÏ£¬ NETWORKS ASSOCIATES TECHNOLOGY, INC ¾ù²»¶ÔÈκÎÖ±½Ó¡¢ ¼ä½Ó¡¢ żȻ¡¢ ÌØÊâ¡¢ ³Í·£ÐԵģ¬ »ò±ØÈ»µÄËðʧ (°üÀ¨µ«²»ÏÞÓÚÌæ´úÉÌÆ·»ò·þÎñµÄ²É¹º¡¢ ʹÓᢠÊý¾Ý»òÀûÒæµÄËðʧ»òÓªÒµÖжÏ) ¸ºÔ𣬠ÎÞÂÛÊÇÈçºÎµ¼ÖµIJ¢ÒÔÈκÎÓÐÔðÈÎÂß¼­µÄ£¬ ÎÞÂÛÊÇ·ñÊÇÔÚ±¾ÎĵµÊ¹ÓÃÒÔÍâÒÔÈκη½Ê½²úÉúµÄÆõÔ¼¡¢ÑϸñÔðÈλòÊÇÃñÊÂÇÖȨÐÐΪ(°üÀ¨Êèºö»òÆäËü)Öеģ¬ ¼´Ê¹Òѱ»¸æÖª·¢Éú¸ÃËðʧµÄ¿ÉÄÜÐÔ¡£


6.2 ÊõÓï½âÎö

¡¡¡¡FreeBSD ÒÔÒ»¸öÄں˰²È«À©Õ¹ÐÔ¿ò¼Ü(TrustedBSD MAC ¿ò¼Ü)µÄ·½Ê½£¬ÎªÈô¸ÉÇ¿ÖÆ·ÃÎÊ¿ØÖƲßÂÔ£¨Ò²³Æ¡°¼¯È¨Ê½·ÃÎÊ¿ØÖƲßÂÔ¡±£© ÌṩÊÔÑéÐÔÖ§³Ö¡£MAC ¿ò¼ÜÊÇÒ»¸ö²åÈëʽµÄ·ÃÎÊ¿ØÖÆ¿ò¼Ü£¬ÔÊÐíÐµİ²È«²ßÂÔ¸ü·½±ãµØÈÚÈëÄÚºË:°²È«²ßÂÔ¿ÉÒÔ¾²Ì¬Á´ÈëÄÚºË,Ò²¿ÉÒÔ ÔÚÒýµ¼Ê±¼ÓÔØ,ÉõÖÁÔÚÔËÐÐʱ¶¯Ì¬¼ÓÔØ¡£¸Ã¿ò¼ÜËùÌṩµÄ±ê×¼»¯½Ó¿Ú,ʹµÃÔËÐÐÔÚÆäÉϵݲȫ²ßÂÔÄ£¿éÄܶÔϵͳ¶ÔÏóµÄ°²È«ÊôÐÔ½øÐÐÖîÈç±ê¼ÇµÈһϵÁвÙ×÷¡£ MAC ¿ò¼ÜµÄ´æÔÚ£¬¼ò»¯ÁËÕâЩ²Ù×÷ÔÚ²ßÂÔÄ£¿éÖеÄʵÏÖ£¬´Ó¶øÏÔÖø½µµÍÁËа²È«²ßÂÔÄ£¿éµÄ¿ª·¢ÄѶȡ£

¡¡¡¡±¾Õ½«½éÉÜ MAC ²ßÂÔ¿ò¼Ü£¬Îª¶ÁÕßÌṩһ¸öʾÀýÐ﵀ MAC ²ßÂÔÄ£¿éÎĵµ¡£


6.3 ¸ÅÊö

¡¡¡¡TrustedBSD MAC ¿ò¼ÜÌṩµÄ»úÖÆ,ÔÊÐíÔÚÆäÉÏÔËÐеÄÄÚºËÄ£¿éÔÚÄں˱àÒë»òÕßÔËÐÐʱ£¬¶ÔÄں˵ķÃÎÊ¿ØÖÆÄ£ÐͽøÐÐÀ©Õ¹¡£ еÄϵͳ°²È«²ßÂÔ×÷Ϊһ¸öÄÚºËÄ£¿éʵÏÖ,²¢±»Á´½Óµ½ÄÚºËÖУ»Èç¹ûϵͳÖÐͬʱ´æÔÚ¶à¸ö°²È«²ßÂÔÄ£¿é£¬ÔòËüÃǵľö²ß½á¹û½«ÒÔijÖÖÈ·¶¨µÄ·½Ê½×éºÏ¡£ ΪÁ˸ø¼ò»¯Ð°²È«²ßÂԵĿª·¢£¬MAC ÏòÉÏÌṩÁË´óÁ¿ÓÃÓÚ·ÃÎÊ¿ØÖƵĻù´¡ÉèÊ©£¬ÌرðÊÇ£¬¶ÔÁÙʱµÄ»òÕ߳־õġ¢²ßÂÔÎ޹صĶÔÏó°²È«±ê¼ÇµÄÖ§³Ö¡£ ¸ÃÖ§³ÖĿǰÈÔÊÇÊÔÑéÐÔÖʵġ£

¡¡¡¡±¾ÕÂËùÌṩµÄÐÅÏ¢²»½ö½«Ê¹ÔÚ MAC ʹÄÜ»·¾³Ï¹¤×÷µÄDZÔÚÓû§ÊÜÒæ£¬ Ò²¿ÉÒÔΪÐèÒªÁ˽â MAC ¿ò¼ÜÊÇÈçºÎÖ§³Ö¶ÔÄں˷ÃÎÊ¿ØÖƽøÐÐÀ©Õ¹µÄ²ßÂÔÄ£¿é¿ª·¢ÈËÔ±ËùÓá£


6.4 °²È«²ßÂÔ±³¾°ÖªÊ¶

¡¡¡¡Ç¿ÖÆ·ÃÎÊ¿ØÖÆ£¨¼ò³Æ MAC£©£¬ÊÇÖ¸ÓɲÙ×÷ÏµÍ³Ç¿ÖÆÊµÊ©µÄÒ»×éÕë¶ÔÓû§µÄ·ÃÎÊ¿ØÖƲßÂÔ¡£ ÔÚijЩÇé¿öÏÂ,Ç¿ÖÆ·ÃÎÊ¿ØÖƵIJßÂÔ¿ÉÄÜ»áÓë×ÔÖ÷·ÃÎÊ¿ØÖÆ£¨¼ò³Æ DAC£©ËùÌṩµÄ±£»¤´ëÊ©·¢Éú³åÍ»£¬ ºóÕßÊÇÓÃÀ´Ïò·Ç¹ÜÀíÔ±Óû§¶ÔÊý¾Ý²ÉÈ¡±£»¤´ëÊ©Ìṩ֧³ÖµÄ¡£ÔÚ´«Í³µÄ UNIX ϵͳÖУ¬ DAC ±£»¤´ëÊ©°üÀ¨Îļþ·ÃÎÊģʽºÍ·ÃÎÊ¿ØÖÆÁÐ±í£»¶ø MAC ÔòÌṩ½ø³Ì¿ØÖƺͷÀ»ðǽµÈ¡£ ²Ù×÷ϵͳÉè¼ÆÕߺͰ²È«»úÖÆÑо¿ÈËÔ±¶ÔÐí¶à¾­µäµÄ MAC °²È«²ßÂÔ×÷ÁËÐÎʽ»¯µÄ±íÊö£¬±ÈÈ磬 ¶à¼¶°²È«£¨MLS)»úÃÜÐÔ²ßÂÔ£¬Biba ÍêÕûÐÔ²ßÂÔ£¬»ùÓÚ½ÇÉ«µÄ·ÃÎÊ¿ØÖƲßÂÔ£¨RBAC£©£¬ÓòºÍÐͲþö²ßÂÔ(DTE),ÒÔ¼°ÐͲþö²ßÂÔ(TE)¡£ °²È«²ßÂÔµÄÐÎʽ»¯±íÊö±»³ÆÎª°²È«Ä£ÐÍ¡£Ã¿¸öÄ£Ð͸ù¾ÝһϵÁÐÌõ¼þ×ö³ö°²È«Ïà¹ØµÄ¾ö²ß£¬ÕâЩÌõ¼þ°üÀ¨£¬ Óû§µÄÉí·Ý¡¢½ÇÉ«ºÍ°²È«ÐÅÈÎ×´£¬ÒÔ¼°¶ÔÏóµÄ°²È«±ê¼Ç(ÓÃÀ´´ú±í¸Ã¶ÔÏóÊý¾ÝµÄ»úÃÜÐÔ/ÍêÕûÐÔ¼¶±ð)¡£

¡¡¡¡TrustedBSD MAC ¿ò¼ÜËùÌṩµÄ¶Ô²ßÂÔÄ£¿éµÄÖ§³Ö£¬²»½ö¿ÉÒÔÓÃÀ´ÊµÏÖÉÏÊöËùÓвßÂÔ£¬ »¹ÄÜÓÃÓÚʵÏÖÆäËûÀûÓÃÒÑÓа²È«ÊôÐÔ(È磬Óû§ºÍ×éID¡¢ÎļþÀ©Õ¹ÊôÐԵȣ©¾ö²ßµÄϵͳ°²È«Ç¿»¯²ßÂÔ¡£ ´ËÍ⣬ÒòΪ¾ßÌå²ßÂÔÄ£¿éÔÚ·ÃÎÊÊÚȨ·½ÃæËùÓµÓеĸ߶ÈÁé»îÐÔºÍ×ÔÖ÷ÐÔ£¬ËùÒÔMAC ¿ò¼ÜͬÑù¿ÉÒÔÓÃÀ´ÊµÏÖÍêÈ«×ÔÖ÷ʽµÄ°²È«²ßÂÔ.


6.5 MAC ¿ò¼ÜµÄÄÚºËÌåϵ½á¹¹

¡¡¡¡TrustedBSD MAC ¿ò¼ÜΪ´ó¶àÊýµÄ·ÃÎÊ¿ØÖÆÄ£¿éÌṩ»ù±¾ÉèÊ©£¬ÔÊÐíËüÃÇÒÔÄÚºËÄ£¿éµÄÐÎʽÁé»îµØÀ©Õ¹ÏµÍ³ÖÐʵʩµÄ°²È«²ßÂÔ¡£ Èç¹ûϵͳÖÐͬʱ¼ÓÔØÁ˶à¸ö²ßÂÔ£¬MAC ¿ò¼Ü½«¸ºÔ𽫸÷¸ö²ßÂÔµÄÊÚȨ½á¹ûÒÔÒ»ÖÖ£¨Ä³Ö̶ֳÈÉÏ£©ÓÐÒâÒåµÄ·½Ê½×éºÏ£¬ÐγÉ×îºóµÄ¾ö²ß¡£


6.5.1 ÄÚºËÔªËØ

¡¡¡¡MAC ¿ò¼ÜÓÉÏÂÁÐÄÚºËÔªËØ×é³É£º

  • ¿ò¼Ü¹ÜÀí½Ó¿Ú

  • ²¢·¢Óëͬ²½Ô­Óï

  • ²ßÂÔ×¢²á

  • Äں˶ÔÏóµÄÀ©Õ¹ÐÔ°²È«±ê¼Ç

  • ²ßÂÔÈë¿Úº¯ÊýµÄ×éºÏ²Ù×÷

  • ±ê¼Ç¹ÜÀíÔ­Óï

  • ÓÉÄں˷þÎñµ÷ÓõÄÈë¿Úº¯Êý API

  • ²ßÂÔÄ£¿éµÄÈë¿Úº¯Êý API

  • Èë¿Úº¯ÊýµÄʵÏÖ£¨°üÀ¨²ßÂÔÉúÃüÖÜÆÚ¹ÜÀí¡¢±ê¼Ç¹ÜÀíºÍ·ÃÎÊ¿ØÖƼì²éÈý²¿·Ö£©

  • ¹ÜÀí²ßÂÔÎ޹رê¼ÇµÄϵͳµ÷ÓÃ

  • ¸´ÓõÄmac_syscall() ϵͳµ÷ÓÃ

  • ÒÔ MAC µÄ²ßÂÔ¼ÓÔØÄ£¿éÐÎʽʵÏֵĸ÷ÖÖ°²È«²ßÂÔ


6.5.2 ¿ò¼Ü¹ÜÀí½Ó¿Ú

¡¡¡¡¶Ô TrustedBSD MAC ¿ò¼Ü½øÐÐÖ±½Ó¹ÜÀíµÄ·½Ê½ÓÐÈýÖÖ:ͨ¹ý sysctl ×Óϵͳ¡¢Í¨¹ý loader ÅäÖÃ, »òÕßʹÓÃϵͳµ÷Óá£

¡¡¡¡¶àÊýÇé¿öÏ£¬Óëͬһ¸öÄÚºËÄÚ²¿±äÁ¿Ïà¹ØÁªµÄ sysctl ±äÁ¿ºÍ loader ²ÎÊýµÄÃû×ÖÊÇÏàͬµÄ£¬ ͨ¹ýÉèÖÃËüÃÇ£¬¿ÉÒÔ¿ØÖƱ£»¤´ëÊ©µÄʵʩϸ½Ú£¬±ÈÈ磬ij¸ö²ßÂÔÔÚ¸÷¸öÄÚºË×ÓϵͳÖеÄʵʩÓë·ñµÈµÈ¡£ ÁíÍ⣬Èç¹ûÔÚÄں˱àÒëʱѡÔñÖ§³Ö MAC µ÷ÊÔÑ¡ÏÄں˽«Î¬»¤Èô¸É¼ÆÊýÆ÷ÒÔ¸ú×Ù±ê¼ÇµÄ·ÖÅäʹÓÃÇé¿ö¡£ ͨ³£²»½¨ÒéÔÚʵÓû·¾³ÏÂͨ¹ýÔÚ²»Í¬×ÓϵͳÉÏÉèÖò»Í¬µÄ±äÁ¿»ò²ÎÊýÀ´ÊµÊ©¿ØÖÆ£¬ÒòΪÕâÖÖ·½·¨½«»á×÷ÓÃÓÚϵͳÖÐËùÓеĻîÔ¾²ßÂÔ¡£ Èç¹ûÏ£Íû¶Ô¾ßÌå²ßÂÔʵʩ¹ÜÀí¶ø²»ÏàÓ°ÏìÆäËû»îÔ¾²ßÂÔ,ÔòÓ¦µ±Ê¹ÓòßÂÔ¼¶±ðµÄ¿ØÖÆ£¬ÒòΪÕâÖÖ·½·¨µÄ¿ØÖÆÁ£¶È¸üϸ£¬ ²¢ÄܸüºÃµØ±£Ö¤²ßÂÔÄ£¿éµÄ¹¦ÄÜÒ»ÖÂÐÔ¡£

¡¡¡¡ÓëÆäËûÄÚºËÄ£¿éÒ»Ñù£¬ÏµÍ³¹ÜÀíÔ±¿ÉÒÔͨ¹ýϵͳµÄÄ£¿é¹ÜÀíϵͳµ÷ÓÃºÍÆäËûϵͳ½Ó¿Ú£¬°üÀ¨ boot loader ±äÁ¿£¬¶Ô²ßÂÔÄ£¿éÖ´ÐмÓÔØÓëÐ¶ÔØ²Ù×÷£» ²ßÂÔÄ£¿é¿ÉÒÔÔÚ¼ÓÔØÊ±,ÉèÖüÓÔØ±êÖ¾,À´Ö¸Ê¾ÏµÍ³¶ÔÆä¼ÓÔØ¡¢Ð¶ÔزÙ×÷½øÐÐÏàÓ¦¿ØÖÆ£¬±ÈÈç×èÖ¹·ÇÆÚÍûµÄÐ¶ÔØ²Ù×÷¡£


6.5.3 ²ßÂÔÁ´±íµÄ²¢·¢Óëͬ²½

¡¡¡¡ÔÚÔËÐÐʱ,ϵͳÖлîÔ¾µÄ²ßÂÔ¼¯ºÏ¿ÉÄÜ·¢Éú±ä»¯£¬È»¶ø¶Ô²ßÂÔÈë¿Úº¯ÊýµÄʹÓòÙ×÷²¢²»ÊÇÔ­×ÓÐԵģ¬Òò´Ë£¬µ±Ä³Ò»¸öÈë¿Úº¯ÊýÕý±»Ê¹ÓÃʱ£¬ ϵͳÐèÒªÌṩ¶îÍâµÄͬ²½»úÖÆÀ´×èÖ¹¶Ô¸Ã²ßÂÔÄ£¿éµÄ¼ÓÔØÓëÐ¶ÔØ£¬ÒÔÈ·±£µ±Ç°»îÔ¾µÄ²ßÂÔ¼¯ºÏ²»»áÔڴ˹ý³ÌÖз¢Éú¸Ä±ä¡£ ͨ¹ýʹÓÃ"¿ò¼Ü桱¼ÆÊýÆ÷,¾Í¿ÉÒÔ×öµ½ÕâÒ»µã£ºÒ»µ©Ä³¸öÈë¿Úº¯Êý±»µ÷Ó㬼ÆÊýÆ÷µÄÖµ±»Ôö¼Ó1£»¶øÃ¿µ±Ò»¸öÈë¿Úº¯Êýµ÷ÓýáÊøÊ±£¬¼ÆÊýÆ÷µÄÖµ±»¼õÉÙ1¡£ ¼ì²é¼ÆÊýÆ÷µÄÖµ£¬Èç¹ûÆäֵΪÕý£¬¿ò¼Ü½«×èÖ¹¶Ô²ßÂÔÁ´±íµÄÐ޸IJÙ×÷£¬ÇëÇó²Ù×÷µÄÏ߳̽«±»ÆÈ½øÈë˯Ãߣ¬Ö±µ½¼ÆÊýÆ÷µÄÖµÖØÐ¼õÉÙµ½0Ϊֹ¡£ ¼ÆÊýÆ÷±¾ÉíÓÉÒ»¸ö»¥³âËø±£»¤£¬Í¬Ê±½áºÏÒ»¸öÌõ¼þ±äÁ¿(ÓÃÓÚ»½Ðѵȴý¶Ô²ßÂÔÁ´±í½øÐÐÐ޸IJÙ×÷µÄ˯ÃßÏß³Ì)¡£ ²ÉÓÃÕâÖÖͬ²½Ä£Ð͵ÄÒ»¸ö¸±×÷ÓÃÊÇ£¬ÔÚͬһ¸ö²ßÂÔÄ£¿éÄÚ²¿£¬ÔÊÐíǶÌ׵ص÷Óÿò¼Ü£¬²»¹ýÕâÖÖÇé¿öÆäʵºÜÉÙ³öÏÖ¡£

¡¡¡¡ÎªÁ˼õÉÙÓÉÓÚ²ÉÓüÆÊýÆ÷ÒýÈëµÄ¶îÍ⿪Ïú£¬Éè¼ÆÕß²ÉÓÃÁ˸÷ÖÖÓÅ»¯´ëÊ©¡£ÆäÖаüÀ¨£¬µ±²ßÂÔÁ´±íΪ¿Õ»òÕ߯äÖнöº¬Óо²Ì¬±íÏî £¨ÄÇЩֻÄÜÔÚϵͳÔËÐÐ֮ǰ¼ÓÔØ¶øÇÒ²»Äܶ¯Ì¬Ð¶ÔصIJßÂÔ£©Ê±£¬¿ò¼Ü²»¶Ô¼ÆÊýÆ÷½øÐвÙ×÷£¬ÆäÖµ×ÜÊÇΪ0£¬´Ó¶ø½«´ËʱµÄͬ²½¿ªÏú¼õµ½0¡£ ÁíÒ»¸ö¼«¶ËµÄ°ì·¨ÊÇ£¬Ê¹ÓÃÒ»¸ö±àÒëÑ¡ÏîÀ´½ûÖ¹ÔÚÔËÐÐʱ¶Ô¼ÓÔØµÄ²ßÂÔÁ´±í½øÐÐÐ޸쬴Ëʱ²»ÔÙÐèÒª¶Ô²ßÂÔÁ´±íµÄʹÓýøÐÐͬ²½±£»¤¡£

¡¡¡¡ÒòΪ MAC ¿ò¼Ü²»ÔÊÐíÔÚijЩÈë¿Úº¯ÊýÖ®ÄÚ×èÈû£¬ËùÒÔ²»ÄÜʹÓÃÆÕͨµÄ˯ÃßËø¡£ ¹Ê¶ø£¬¼ÓÔØ»òÐ¶ÔØ²Ù×÷¿ÉÄÜ»áΪµÈ´ý¿ò¼Ü¿ÕÏжø±»×èÈûÏ൱³¤µÄÒ»¶Îʱ¼ä¡£


6.5.4 ±ê¼Çͬ²½

¡¡¡¡MAC ¿ò¼Ü±ØÐë¶ÔÆä¸ºÔðά»¤µÄ°²È«ÊôÐÔ±ê¼ÇµÄ´æ´¢·ÃÎÊÌṩͬ²½±£»¤¡£ÏÂÁÐÁ½ÖÖÇéÐΣ¬¿ÉÄܵ¼Ö¶԰²È«ÊôÐÔ±ê¼ÇµÄ²»Ò»Ö·ÃÎÊ£º µÚÒ»£¬×÷Ϊ°²È«ÊôÐÔ±ê¼ÇµÄ³ÖÓÐÕߣ¬Äں˶ÔÏó±¾Éí¿ÉÄÜͬʱ±»¶à¸öÏ̷߳ÃÎÊ£»µÚ¶þ£¬MAC ¿ò¼Ü´úÂëÊÇ¿ÉÖØÈëµÄ£¬ ¼´ÔÊÐí¶à¸öÏß³ÌͬʱÔÚ¿ò¼ÜÄÚÖ´ÐС£Í¨³££¬MAC ¿ò¼ÜʹÓÃÄں˶ÔÏóÊý¾ÝÉÏÒÑÓеÄÄÚºËͬ²½»úÖÆÀ´±£»¤¸ÃÆäÉϸ½¼ÓµÄ MAC °²È«±ê¼Ç¡£ ÀýÈ磬Ì×½Ó×ÖÉ쵀 MAC ±ê¼ÇÓÉÒÑÓеÄÌ×½Ó×Ö»¥³âËø±£»¤¡£ÀàËÆµÄ£¬¶ÔÓÚ°²È«±ê¼ÇµÄ²¢·¢·ÃÎʵĹý³ÌÓë¶ÔÆäËùÔÚ¶ÔÏó½øÐеIJ¢·¢·ÃÎÊÔÚÓïÒåÉÏÊÇÒ»ÑùµÄ£¬ ÀýÈ磬ÐÅÈÎ×´°²È«±ê¼Ç,½«±£³ÖÓë¸ÃÊý¾Ý½á¹¹ÖÐÆäËûÄÚÈÝÒ»ÖµÄ"дʱ¸´ÖÆ"µÄ¸üйý³Ì¡£ MAC ¿ò¼ÜÔÚÒýÓÃÒ»¸öÄں˶ÔÏóʱ£¬½«Ê×ÏȶԷÃÎʸöÔÏóÉϵıê¼ÇÐèÒªÓõ½µÄËø½øÐжÏÑÔ¡£ ²ßÂÔÄ£¿éµÄ±àдÕß±ØÐëÁ˽âÕâЩͬ²½ÓïÒ壬 ÒòΪËüÃÇ¿ÉÄÜ»áÏÞÖÆ¶Ô°²È«±ê¼ÇËùÄܽøÐеķÃÎÊÀàÐÍ¡£ ¾Ù¸öÀý×Ó£¬Èç¹ûͨ¹ýÈë¿Úº¯Êý´«¸ø²ßÂÔÄ£¿éµÄÊǶÔij¸öÐÅÈÎ×´µÄÖ»¶ÁÒýÓã¬ÄÇôÔÚ²ßÂÔÄÚ²¿£¬Ö»ÄܶÁ¸Ã½á¹¹¶ÔÓ¦µÄ±ê¼Ç״̬¡£


6.5.5 ²ßÂÔ¼äµÄͬ²½Óë²¢·¢

¡¡¡¡FreeBSD ÄÚºËÊÇÒ»¸ö¿ÉÇÀռʽµÄÄںˣ¬Òò´Ë£¬×÷ΪÄÚºËÒ»²¿·ÖµÄ²ßÂÔÄ£¿éÒ²±ØÐëÊÇ¿ÉÖØÈëµÄ£¬Ò²¾ÍÊÇ˵£¬ ÔÚ¿ª·¢²ßÂÔÄ£¿éʱ±ØÐë¼ÙÉè¶à¸öÄÚºËÏ߳̿ÉÒÔͬʱͨ¹ý²»Í¬µÄÈë¿Úº¯Êý½øÈë¸ÃÄ£¿é¡£ Èç¹û²ßÂÔÄ£¿éʹÓÿɱ»Ð޸ĵÄÄÚºË״̬£¬ÄÇô»¹ÐèÒªÔÚ²ßÂÔÄÚ²¿Ê¹ÓÃÇ¡µ±µÄͬ²½Ô­Óȷ±£ÔÚ²ßÂÔÄÚ²¿µÄ¶à¸öÏ̲߳»»áÒò´Ë¹Û²ìµ½²»Ò»ÖµÄÄÚºË״̬£¬ ´Ó¶ø±ÜÃâÓɴ˲úÉúµÄ²ßÂÔÎó²Ù×÷¡£Îª´Ë£¬²ßÂÔ¿ÉÒÔʹÓà FreeBSD ÏÖÓеÄͬ²½Ô­Ó°üÀ¨»¥³âËø¡¢Ë¯ÃßËø¡¢Ìõ¼þ±äÁ¿ºÍ¼ÆÊýÐźÅÁ¿¡£ ¶ÔÕâЩͬ²½Ô­ÓïµÄʹÓñØÐëÉ÷ÖØ£¬ÐèÒªÌØ±ð×¢ÒâÁ½µã£ºµÚÒ»£¬±£³ÖÏÖÓеÄÄÚºËÉÏËø´ÎÐò£» µÚ¶þ£¬ÔÚ·Ç˯ÃßµÄÈë¿Úº¯ÊýÖ®ÄÚ²»ÒªÊ¹Óû¥³âËøºÍ»½ÐѲÙ×÷¡£

¡¡¡¡Îª±ÜÃâÎ¥·´ÄÚºËÉÏËø´ÎÐò»òÔì³ÉµÝ¹éÉÏËø£¬²ßÂÔÄ£¿éÔÚµ÷ÓÃÆäËûÄÚºË×Óϵͳ֮ǰ£¬Í¨³£ÒªÊÍ·ÅËùÓÐÔÚ²ßÂÔÄÚ²¿ÉêÇëµÄËø¡£ ÕâÑù×öµÄ½á¹ûÊÇ£¬ÔÚÈ«¾ÖÉÏËø´ÎÐòÐγɵÄÍØÆÓ½á¹¹ÖУ¬²ßÂÔÄÚ²¿µÄËø×ÜÊÇ×÷ΪҶ×ӽڵ㣬 ´Ó¶ø±£Ö¤ÁËÕâÐ©ËøµÄʹÓò»»áµ¼ÖÂÓÉÓÚÉÏËø´ÎÐò»ìÂÒÔì³ÉµÄËÀËø¡£


6.5.6 ²ßÂÔ×¢²á

¡¡¡¡ÎªÁ˼Ǽµ±Ç°Ê¹ÓõIJßÂÔÄ£¿é¼¯ºÏ£¬MAC ¿ò¼Üά»¤Á½¸öÁ´±í£ºÒ»¸ö¾²Ì¬Á´±íºÍÒ»¸ö¶¯Ì¬Á´±í¡£ Á½¸öÁ´±íµÄÊý¾Ý½á¹¹ºÍ²Ù×÷»ù±¾Ïàͬ£¬Ö»ÊǶ¯Ì¬Á´±í»¹¶îÍâʹÓÃÁËÒ»¸ö"ÒýÓüÆÊý"ÒÔͬ²½¶ÔÆäµÄ·ÃÎʲÙ×÷¡£ µ±°üº¬ MAC ¿ò¼Ü²ßÂÔµÄÄÚºËÄ£¿é±»¼ÓÔØÊ±£¬¸Ã²ßÂÔÄ£¿é»áͨ¹ý SYSINIT µ÷ÓÃÒ»¸ö×¢²áº¯Êý£» Ïà¶ÔÓ¦µÄ£¬Ã¿µ±Ò»¸ö²ßÂÔÄ£¿é±»Ð¶ÔØ£¬SYSINIT Ò²»áµ÷ÓÃÒ»¸ö×¢Ïúº¯Êý¡£ Ö»Óе±Óöµ½ÏÂÁÐÇé¿ö֮һʱ£¬×¢²á¹ý³Ì²Å»áʧ°Ü£º Ò»¸ö²ßÂÔÄ£¿é±»¼ÓÔØ¶à´Î£¬»òÕßϵͳ×ÊÔ´²»×ã²»ÄÜÂú×ã×¢²á¹ý³ÌµÄÐèÒª£¨ ÀýÈ磬²ßÂÔÄ£¿éÐèÒª¶ÔÄں˶ÔÏóÌí¼Ó±ê¼Ç¶ø¿ÉÓÃ×ÊÔ´²»×㣩£¬»òÕ߯äËûµÄ²ßÂÔ¼ÓÔØÇ°ÌáÌõ¼þ²»Âú×㣨ÓÐЩ²ßÂÔÒªÇóÖ»ÄÜÔÚϵͳÒýµ¼Ö®Ç°¼ÓÔØ£©¡£ ÀàËÆµÄ£¬Èç¹ûÒ»¸ö²ßÂÔ±»±ê¼ÇΪ²»¿ÉÐ¶ÔØµÄ£¬¶ÔÆäµ÷ÓÃ×¢Ïú¹ý³Ì½«»áʧ°Ü¡£


6.5.7 Èë¿Úº¯Êý

¡¡¡¡Äں˷þÎñÓë MAC ¿ò¼ÜÖ®¼ä½øÐн»»¥ÓÐÁ½ÖÖ;¾¶£º Ò»ÊÇ£¬Äں˷þÎñµ÷ÓÃһϵÁÐ API ֪ͨ MAC ¿ò¼Ü°²È«Ê¼þµÄ·¢Éú£» ¶þÊÇ£¬Äں˷þÎñÏò MAC ¿ò¼ÜÌṩһ¸öÖ¸Ïò°²È«¶ÔÏóµÄ²ßÂÔÎ޹ذ²È«±ê¼ÇÊý¾Ý½á¹¹µÄÖ¸Õë¡£ ±ê¼ÇÖ¸ÕëÓÉ MAC ¿ò¼Ü¾­Óɱê¼Ç¹ÜÀíÈë¿Úº¯Êý½øÐÐά»¤£¬ ²¢ÇÒ£¬Ö»Òª¶Ô¹ÜÀíÏà¹Ø¶ÔÏóµÄÄÚºË×ÓϵͳÉÔ×÷Ð޸ģ¬¾Í¿ÉÒÔÔÊÐí MAC ¿ò¼ÜÏò²ßÂÔÄ£¿éÌṩ±ê¼Ç·þÎñ¡£ ÀýÈ磬ÔÚ½ø³Ì¡¢½ø³ÌÐÅÈÎ×´¡¢Ì×½Ó×Ö¡¢¹ÜµÀ¡¢Mbuf¡¢ÍøÂç½Ó¿Ú¡¢IP ÖØ×é¶ÓÁÐºÍÆäËû¸÷ÖÖ°²È«Ïà¹ØµÄÊý¾Ý½á¹¹ÖоùÔö¼ÓÁËÖ¸Ïò°²È«±ê¼ÇµÄÖ¸Õë¡£ ÁíÍ⣬µ±ÐèÒª×ö³öÖØÒªµÄ°²È«¾ö²ßʱ£¬Äں˷þÎñÒ²»áµ÷Óà MAC ¿ò¼Ü£¬ÒÔ±ã¸÷¸ö²ßÂÔÄ£¿é¸ù¾ÝÆä×Ô¼ºµÄ±ê×¼£¨¿ÉÒÔʹÓô洢ÔÚ°²È«±ê¼ÇÖеÄÊý¾Ý£©ÍêÉÆÕâЩ¾ö²ß¡£ ¾ø´ó¶àÊý°²È«Ïà¹ØµÄ¹Ø¼ü¾ö²ßÊÇÏÔʽµÄ·ÃÎÊ¿ØÖƼì²é£» Ò²ÓÐÉÙÊýÉæ¼°¸ü¼ÓÒ»°ãµÄ¾ö²ßº¯Êý£¬±ÈÈ磬Ì×½Ó×ÖµÄÊý¾Ý°üÆ¥ÅäºÍ³ÌÐòÖ´ÐÐʱ¿ÌµÄ±ê¼Çת»»¡£


6.5.8 ²ßÂÔ×éºÏ

¡¡¡¡Èç¹ûÄÚºËÖÐͬʱ¼ÓÔØÁ˶à¸ö²ßÂÔÄ£¿é£¬ÕâЩ²ßÂԵľö²ß½á¹û½«ÓÉ¿ò¼ÜʹÓÃÒ»¸öºÏ³ÉÔËËã×ÓÀ´½øÐÐ×éºÏ»ã×Ü£¬µÃ³ö×îÖյĽá¹û¡£ Ŀǰ£¬¸ÃËã×ÓÊÇÓ²±àÂëµÄ£¬²¢ÇÒÖ»Óе±ËùÓеĻîÔ¾²ßÂÔ¾ù¶ÔÇëÇó±íʾͬÒâʱ²Å»á·µ»Ø³É¹¦¡£ ÓÉÓÚ¸÷¸ö²ßÂÔ·µ»ØµÄ³ö´íÌõ¼þ¿ÉÄܲ¢²»Ïàͬ£¨³É¹¦¡¢·ÃÎʱ»¾Ü¾ø¡¢ÇëÇó¶ÔÏó²»´æÔڵȵȣ©£¬ ÐèҪʹÓÃÒ»¸öÑ¡Ôñ×ÓÏÈ´Ó¸÷¸ö²ßÂÔ·µ»ØµÄ´íÎóÌõ¼þ¼¯ºÏÖÐÑ¡Ôñ³öÒ»¸ö×÷Ϊ×îÖÕ·µ»Ø½á¹û¡£ Ò»°ãÇé¿öÏ£¬Óë¡°·ÃÎʱ»¾Ü¾ø¡±Ïà±È£¬½«¸üÇãÏòÓÚÑ¡Ôñ¡°ÇëÇó¶ÔÏó²»´æÔÚ¡±¡£ ¾¡¹Ü²»ÄÜ´ÓÀíÂÛÉϱ£Ö¤ºÏ³É½á¹ûµÄÓÐЧÐÔÓ밲ȫÐÔ£¬µ«ÊÔÑé½á¹û±íÃ÷£¬¶ÔÓÚÐí¶àʵÓõIJßÂÔ¼¯ºÏÀ´Ëµ£¬ÊÂʵµÄÈ·Èç´Ë¡£ ÀýÈ磬´«Í³µÄ¿ÉÐÅϵͳ³£³£²ÉÓÃÀàËÆµÄ·½·¨¶Ô¶à¸ö°²È«²ßÂÔ½øÐÐ×éºÏ¡£


6.5.9 ±ê¼ÇÖ§³Ö

¡¡¡¡ÓëÐí¶àÐèÒª¸ø¶ÔÏóÌí¼Ó°²È«±ê¼ÇµÄ·ÃÎÊ¿ØÖÆÀ©Õ¹Ò»Ñù£¬MAC ¿ò¼ÜΪ¸÷ÖÖÓû§¿É¼ûµÄ¶ÔÏóÌṩÁËÒ»×éÓÃÓÚ¹ÜÀí²ßÂÔÎ޹رê¼ÇµÄϵͳµ÷Óᣠ³£Óõıê¼ÇÀàÐÍÓУ¬partition±êʶ·û¡¢»úÃÜÐÔ±ê¼Ç¡¢ÍêÕûÐÔ±ê¼Ç¡¢Çø¼ä£¨·ÇµÈ¼¶Àà±ð£©¡¢Óò¡¢½ÇÉ«ºÍÐÍ¡£ ¡°²ßÂÔÎ޹ء±µÄÒâ˼ÊÇÖ¸£¬±ê¼ÇµÄÓï·¨ÓëʹÓÃËüµÄ¾ßÌå²ßÂÔÄ£¿éÎ޹أ¬¶øÍ¬Ê±²ßÂÔÄ£¿éÄܹ»ÍêÈ«¶ÀÁ¢µØ¶¨ÒåºÍʹÓÃÓë¶ÔÏóÏà¹ØÁªµÄÔªÊý¾ÝµÄÓïÒå¡£ Óû§Ó¦ÓóÌÐòÌṩͳһ¸ñʽµÄ»ùÓÚ×Ö·û´®µÄ±ê¼Ç£¬ÓÉʹÓÃËüµÄ²ßÂÔÄ£¿é¸ºÔð½âÎöÆäÄÚÔÚº¬Òå²¢¾ö¶¨ÆäÍâÔÚ±íʾ¡£ Èç¹ûÐèÒª£¬Ó¦ÓóÌÐò¿ÉÒÔʹÓöàÖØ±ê¼ÇÔªËØ¡£

¡¡¡¡ÄÚ´æÖеıê¼ÇʵÀý±»´æ·ÅÔÚÓÉ slab ·ÖÅäµÄstruct labelÊý¾Ý½á¹¹ÖС£ ¸Ã½á¹¹ÊÇÒ»¸ö¹Ì¶¨³¤¶ÈµÄÊý×飬ÿ¸öÔªËØÊÇÓÉÒ»¸ö void * Ö¸ÕëºÍÒ»¸ö long×é³ÉµÄÁªºÏ½á¹¹¡£ ÉêÇë±ê¼Ç´æ´¢µÄ²ßÂÔÄ£¿éÔÚÏò MAC ×¢²áʱ£¬½«±»·ÖÅäÒ»¸ö¡°slot¡±Öµ£¬×÷Ϊ¿ò¼Ü·ÖÅ䏸ÆäʹÓõIJßÂÔ±ê¼ÇÔªËØÔÚÕû¸ö±ê¼Ç´æ´¢½á¹¹ÖеÄλÖÃË÷Òý¡£ ¶øËù·ÖÅäµÄ´æ´¢¿Õ¼äµÄÓïÒåÔòÍêÈ«ÓɸòßÂÔÄ£¿éÀ´¾ö¶¨£ºMAC ¿ò¼ÜÏò²ßÂÔÄ£¿éÌṩÁËһϵÁÐÈë¿Úº¯ÊýÓÃÓÚ¶ÔÄں˶ÔÏóÉúÃüÖÜÆÚµÄ¸÷ÖÖʼþ½øÐпØÖÆ£¬°üÀ¨£¬ ¶ÔÏóµÄ³õʼ»¯¡¢±ê¼ÇµÄ¹ØÁª/´´½¨ºÍ¶ÔÏóµÄ×¢Ïú¡£Ê¹ÓÃÕâЩ½Ó¿Ú£¬¿ÉÒÔʵÏÖÖîÈç·ÃÎʼÆÊýµÈ´æ´¢Ä£ÐÍ¡£ MAC ¿ò¼Ü×ÜÊǸøÈë¿Úº¯Êý´«ÈëÒ»¸öÖ¸ÏòÏà¹Ø¶ÔÏóµÄÖ¸ÕëºÍÒ»¸öÖ¸Ïò¸Ã¶ÔÏó±ê¼ÇµÄÖ¸Õ룬Òò´Ë£¬²ßÂÔÄ£¿éÄܹ»Ö±½Ó·ÃÎʱê¼Ç¶øÎÞÐè֪Ϥ¸Ã¶ÔÏóµÄÄÚ²¿½á¹¹¡£ ΨһµÄÀýÍâÊǽø³ÌÐÅÈÎ×´½á¹¹£¬Ö¸ÏòÆä±ê¼ÇµÄÖ¸Õë±ØÐëÓɲßÂÔÄ£¿éÊÖ¶¯½âÎö¼ÆËã¡£½ñºóµÄ MAC ¿ò¼ÜʵÏÖ¿ÉÄÜ»á¶Ô´Ë½øÐиĽø¡£

¡¡¡¡³õʼ»¯Èë¿Úº¯Êýͨ³£ÓÐÒ»¸ö˯Ãß±ê־룬ÓÃÀ´±íÃ÷Ò»¸ö³õʼ»¯²Ù×÷ÊÇ·ñÔÊÐíÖÐ;˯Ãߵȴý£» Èç¹û²»ÔÊÐí£¬Ôò¿ÉÄÜ»áʧ°Ü·µ»Ø£¬²¢ÒªÇó³·Ïú´Ë´Î±ê¼Ç·ÖÅä²Ù×÷£¨ÄËÖÁ¶ÔÏó·ÖÅä²Ù×÷£©¡£ ÀýÈ磬Èç¹ûÔÚÍøÂçÕ»ÉÏ´¦ÀíÖжÏʱÒòΪ²»ÔÊÐí˯Ãß»òÕßµ÷ÓÃÕß³ÖÓÐÒ»¸ö»¥³âËø£¬¾Í¿ÉÄܳöÏÖÕâÖÖÇé¿ö¡£ ¿¼Âǵ½ÔÚ´¦ÀíÖеÄÍøÂçÊý¾Ý°ü£¨Mbufs£©ÉÏά»¤±ê¼ÇµÄÐÔÄÜËðʧ̫´ó£¬²ßÂÔ±ØÐë¾Í×Ô¼º¶Ô Mbuf ½øÐбê¼ÇµÄÒªÇóÏò MAC ¿ò¼Ü×ö³öÌØ±ðÉùÃ÷¡£ ¶¯Ì¬¼ÓÔØµ½ÏµÍ³ÖжøÓÖʹÓñê¼ÇµÄ²ßÂÔ±ØÐëΪ´¦Àíδ±»Æä³õʼ»¯º¯Êý´¦Àí¹ýµÄ¶ÔÏó×÷ºÃ×¼±¸£¬ ÕâЩ¶ÔÏóÔÚ²ßÂÔ¼ÓÔØÖ®Ç°¾ÍÒѾ­´æÔÚ,¹Ê¶øÎÞ·¨ÔÚ³õʼ»¯Ê±µ÷ÓòßÂÔµÄÏà¹Øº¯Êý½øÐд¦Àí¡£ MAC ¿ò¼ÜÏò²ßÂÔ±£Ö¤£¬Ã»Óб»³õʼ»¯µÄ±ê¼Ç slot µÄÖµ±ØÎª0»òÕß NULL£¬²ßÂÔ¿ÉÒÔ½è´Ë¼ì²âµ½Î´³õʼ»¯µÄ±ê¼Ç¡£ ÐèҪעÒâµÄÊÇ£¬ÒòΪ¶Ô Mbuf ±ê¼ÇµÄ´æ´¢·ÖÅäÊÇÓÐÌõ¼þµÄ£¬Òò´ËÐèҪʹÓÃÆä±ê¼ÇµÄ¶¯Ì¬¼ÓÔØ²ßÂÔ»¹¿ÉÄÜÐèÒª´¦Àí Mbuf ÖÐֵΪ NULL µÄ±ê¼ÇÖ¸Õë¡£

¡¡¡¡¶ÔÓÚÎļþϵͳ¶ÔÏóµÄ±ê¼Ç£¬MAC ¿ò¼ÜÔÚÎļþµÄÀ©Õ¹ÊôÐÔÖÐΪÆä·ÖÅäÓÀ¾Ã´æ´¢¡£ Ö»Òª¿ÉÄÜ£¬À©Õ¹ÊôÐÔµÄÔ­×Ó»¯µÄÊÂÎñ²Ù×÷¾Í±»ÓÃÓÚ±£Ö¤¶Ô vnode Éϰ²È«±ê¼ÇµÄ¸´ºÏ¸üвÙ×÷µÄÒ»ÖÂÐÔ£­£­Ä¿Ç°£¬¸ÃÌØÐÔÖ»±» UFS2 Îļþϵͳ֧³Ö¡£ ΪÁËʵÏÖϸÁ£¶ÈµÄÎļþϵͳ¶ÔÏó±ê¼Ç£¨¼´Ã¿¸öÎļþϵͳ¶ÔÏóÒ»¸ö±ê¼Ç£©£¬²ßÂÔ±àдÕß¿ÉÄÜÑ¡ÔñʹÓÃÒ»¸ö£¨»òÕßÈô¸É£©À©Õ¹ÊôÐÔ¿é¡£ ΪÁËÌá¸ßÐÔÄÜ£¬ vnode Êý¾Ý½á¹¹ÖÐÓÐÒ»¸ö±ê¼Ç (v_label)×ֶΣ¬ÓÃ×÷´ÅÅ̱ê¼ÇµÄ»º³å£» vnode ½á¹¹ÊµÀý»¯Ê±£¬²ßÂÔ¿ÉÒÔ½«±ê¼ÇÖµ×°Èë¸Ã»º³å£¬²¢ÔÚÐèҪʱ¶ÔÆä½øÐиüС£ Èç´Ë£¬²»±ØÔÚÿ´Î½øÐзÃÎÊ¿ØÖƼì²éʱ£¬¾ùÎÞÌõ¼þµØ·ÃÎÊ´ÅÅÌÉϵÄÀ©Õ¹ÊôÐÔ¡£

×¢Òâ: Ŀǰ£¬Èç¹ûÒ»¸öʹÓñê¼ÇµÄ²ßÂÔÔÊÐí±»¶¯Ì¬Ð¶ÔØ£¬ÔòÐ¶ÔØ¸ÃÄ£¿éÖ®ºó,Æä״̬ slot ÉÐÎÞ·¨±»ÏµÍ³»ØÊÕÖØÓ㬠Óɴ˵¼ÖÂÁË MAC ¿ò¼Ü¶Ô±ê¼Ç²ßÂÔÐ¶ÔØ£­ÖØÔزÙ×÷ÊýÄ¿ÉϵÄÑϸñÏÞÖÆ¡£


6.5.10 Ïà¹ØÏµÍ³µ÷ÓÃ

¡¡¡¡MAC ¿ò¼ÜÏòÓ¦ÓóÌÐòÌṩÁËÒ»×éϵͳµ÷ÓãºÆäÖдó¶àÊýÓÃÓÚÏò½øÐвéѯºÍÐ޸IJßÂÔÎ޹رê¼Ç²Ù×÷µÄÓ¦Óà APIÌṩ֧³Ö¡£

¡¡¡¡ÕâЩ±ê¼Ç¹ÜÀíϵͳµ÷Ó㬽ÓÊÜÒ»¸ö±ê¼ÇÃèÊö½á¹¹£¬ struct mac£¬×÷ΪÊäÈë²ÎÊý¡£ Õâ¸ö½á¹¹µÄÖ÷ÌåÊÇÒ»¸öÊý×飬ÆäÖÐÿ¸öÔªËØ°üº¬ÁËÒ»¸öÓ¦Óü¶µÄ MAC ±ê¼ÇÐÎʽ¡£Ã¿¸öÔªËØÓÖÓÉÁ½²¿·Ö×é³É:Ò»¸ö×Ö·û´®Ãû×Ö£¬ºÍÆä¶ÔÓ¦µÄÖµ¡£ ÿ¸ö²ßÂÔ¿ÉÒÔÏòϵͳÉùÃ÷Ò»¸öÌØ¶¨µÄÔªËØÃû×Ö£¬ÕâÑùÒ»À´£¬Èç¹ûÐèÒª£¬¾Í¿ÉÒÔ½«Èô¸É¸öÏ໥¶ÀÁ¢µÄÔªËØ×÷Ϊһ¸öÕûÌå½øÐд¦Àí¡£ ²ßÂÔÄ£¿é¾­ÓÉÈë¿Úº¯Êý£¬ÔÚÄں˱ê¼ÇºÍÓû§ÌṩµÄ±ê¼ÇÖ®¼ä×÷·­Òëת»»µÄ¹¤×÷£¬ÕâÖÖʵÏÖÌṩÁ˱ê¼ÇÔªËØÓïÒåÉϵĸ߶ÈÁé»îÐÔ¡£ ±ê¼Ç¹ÜÀíϵͳµ÷ÓÃͨ³£ÓжÔÓ¦µÄ¿âº¯Êý°ü×°£¬ÕâЩ°ü×°º¯Êý¿ÉÒÔÌṩÄÚ´æ·ÖÅäºÍ´íÎó´¦Àí¹¦ÄÜ£¬´Ó¶ø¼ò»¯ÁËÓû§Ó¦ÓóÌÐòµÄ±ê¼Ç¹ÜÀí¹¤×÷¡£

¡¡¡¡Ä¿Ç°µÄFreeBSD ÄÚºËÌṩÁËÏÂÁÐ MAC Ïà¹ØµÄϵͳµ÷Óãº

  • mac_get_proc() ÓÃÓÚ²éѯµ±Ç°½ø³ÌµÄ°²È«±ê¼Ç¡£

  • mac_set_proc() ÓÃÓÚÇëÇó¸Ä±äµ±Ç°½ø³ÌµÄ°²È«±ê¼Ç¡£

  • mac_get_fd() ÓÃÓÚ²éѯÓÉÎļþÃèÊö·ûËùÒýÓõĶÔÏó£¨ Îļþ¡¢ Ì×½Ó×Ö¡¢ ¹ÜµÀÎļþµÈµÈ£© µÄ°²È«±ê¼Ç¡£

  • mac_get_file() ÓÃÓÚ²éѯÓÉÎļþϵͳ·¾¶ËùÃèÊöµÄ¶ÔÏóµÄ°²È«±ê¼Ç¡£

  • mac_set_fd() ÓÃÓÚÇëÇó¸Ä±äÓÉÎļþÃèÊö·ûËùÒýÓõĶÔÏó£¨ Îļþ¡¢Ì×½Ó×Ö¡¢ ¹ÜµÀÎļþµÈµÈ£© µÄ°²È«±ê¼Ç¡£

  • mac_set_file() ÓÃÓÚÇëÇó¸Ä±äÓÉÎļþϵͳ·¾¶ËùÃèÊöµÄ¶ÔÏóµÄ°²È«±ê¼Ç¡£

  • mac_syscall() ͨ¹ý¸´ÓøÃϵͳµ÷ÓÃ,²ßÂÔÄ£¿éÄܹ»ÔÚ²»ÐÞ¸Äϵͳµ÷ÓñíµÄǰÌáÏ´´½¨ÐµÄϵͳµ÷Óã» Æäµ÷ÓòÎÊý°üÀ¨£ºÄ¿±ê²ßÂÔÃû×Ö¡¢ ²Ù×÷±àºÅºÍ½«±»¸Ã²ßÂÔÄÚ²¿Ê¹ÓõIJÎÊý¡£

  • mac_get_pid() ÓÃÓÚ²éѯÓɽø³ÌºÅÖ¸¶¨µÄÁíÒ»¸ö½ø³ÌµÄ°²È«±ê¼Ç¡£

  • mac_get_link() Óë mac_get_file() ¹¦ÄÜÏàͬ£¬ Ö»Êǵ±Â·¾¶²ÎÊýµÄ×îºóÒ»ÏîΪ·ûºÅÁ´½Óʱ£¬ ǰÕß½«·µ»Ø¸Ã·ûºÅÁ´½ÓµÄ°²È«±ê¼Ç£¬ ¶øºóÕß½«·µ»ØÆäËùÖ¸ÎļþµÄ°²È«±ê¼Ç¡£

  • mac_set_link() Óë mac_set_file() ¹¦ÄÜÏàͬ£¬ Ö»Êǵ±Â·¾¶²ÎÊýµÄ×îºóÒ»ÏîΪ·ûºÅÁ´½Óʱ£¬ ǰÕß½«ÉèÖø÷ûºÅÁ´½ÓµÄ°²È«±ê¼Ç£¬ ¶øºóÕß½«ÉèÖÃÆäËùÖ¸ÎļþµÄ°²È«±ê¼Ç¡£

  • mac_execve() Óë execve() ¹¦ÄÜÀàËÆ£¬ Ö»ÊÇǰÕß»¹¿ÉÒÔÔÚ¿ªÊ¼Ö´ÐÐÒ»¸öгÌÐòʱ,¸ù¾Ý´«ÈëµÄÇëÇó²ÎÊý,ÉèÖÃÖ´Ðнø³ÌµÄ°²È«±ê¼Ç¡£ ÓÉÓÚÖ´ÐÐÒ»¸öгÌÐò¶øµ¼ÖµĽø³Ì°²È«±ê¼ÇµÄ¸Ä±ä,±»³ÆÎª¡°×ª»»¡±¡£

  • mac_get_peer()£¬ ͨ¹ýÒ»¸öÌ×½Ó×ÖÑ¡Ïî×Ô¶¯ÊµÏÖ£¬ ÓÃÓÚ²éѯһ¸öÔ¶³ÌÌ×½Ó×Ö¶ÔµÈʵÌåµÄ°²È«±ê¼Ç¡£

¡¡¡¡³ýÁËÉÏÊöϵͳµ÷ÓÃÖ®Í⣬ Ò²¿ÉÒÔͨ¹ý SIOCSIGMAC ºÍ SIOCSIFMAC ÍøÂç½Ó¿ÚµÄ ioctl Ààϵͳµ÷ÓÃÀ´²éѯºÍÉèÖÃÍøÂç½Ó¿ÚµÄ°²È«±ê¼Ç¡£


6.6 MAC²ßÂÔÄ£¿éÌåϵ½á¹¹

¡¡¡¡°²È«²ßÂÔ¿ÉÒÔÖ±½Ó±àÈëÄںˣ¬Ò²¿ÉÒÔ±àÒë³É¶ÀÁ¢µÄÄÚºËÄ£¿é£¬ÔÚϵͳÒýµ¼Ê±»òÕßÔËÐÐʱʹÓÃÄ£¿é¼ÓÔØÃüÁî¼ÓÔØ¡£ ²ßÂÔÄ£¿éͨ¹ýÒ»×éÔ¤Ïȶ¨ÒåºÃµÄÈë¿Úº¯ÊýÓëϵͳ½»»¥¡£Í¨¹ýËüÃÇ£¬²ßÂÔÄ£¿éÄܹ»ÕÆÎÕijЩϵͳʼþµÄ·¢Éú£¬²¢ÇÒÔÚ±ØÒªµÄʱºòÓ°ÏìϵͳµÄ·ÃÎÊ¿ØÖƾö²ß¡£ ÿ¸ö²ßÂÔÄ£¿é°üº¬ÏÂÁÐ×é³É²¿·Ö£º

  • ¿ÉÑ¡£º²ßÂÔÅäÖòÎÊý

  • ²ßÂÔÂß¼­ºÍ²ÎÊýµÄ¼¯ÖÐʵÏÖ

  • ¿ÉÑ¡£º²ßÂÔÉúÃüÖÜÆÚʼþµÄʵÏÖ£¬±ÈÈ磬²ßÂԵijõʼ»¯ºÍÏú»Ù

  • ¿ÉÑ¡£º¶ÔËùÑ¡Äں˶ÔÏóµÄ°²È«±ê¼Ç½øÐгõʼ»¯¡¢Î¬»¤ºÍÏú»ÙµÄÖ§³Ö

  • ¿ÉÑ¡£º¶ÔËùÑ¡¶ÔÏóµÄʹÓýø³Ì½øÐÐ¼à¿ØÒÔ¼°Ð޸ĶÔÏó°²È«±ê¼ÇµÄÖ§³Ö

  • ²ßÂÔÏà¹ØµÄ·ÃÎÊ¿ØÖÆÈë¿Úº¯ÊýµÄʵÏÖ

  • ¶Ô²ßÂÔ±êÖ¾¡¢Ä£¿éÈë¿Úº¯ÊýºÍ²ßÂÔÌØÐÔµÄÉùÃ÷


6.6.1 ²ßÂÔ×¢Ïú

¡¡¡¡²ßÂÔÄ£¿é¿ÉÒÔʹÓà MAC_POLICY_SET() ºêÀ´ÉùÃ÷¡£ ¸ÃºêÍê³ÉÒÔϹ¤×÷£ºÎª¸Ã²ßÂÔÃüÃû£¨ÏòϵͳÉùÃ÷¸Ã²ßÂÔÌṩµÄÃû×Ö£©£»Ìá½»²ßÂÔ¶¨ÒåµÄ MAC Èë¿Úº¯ÊýÏòÁ¿µÄµØÖ·£» °´ÕÕ²ßÂÔµÄÒªÇóÉèÖøòßÂԵļÓÔØ±ê־룬±£Ö¤ MAC ¿ò¼Ü½«ÒÔ²ßÂÔËùÆÚÍûµÄ·½Ê½¶ÔÆä½øÐвÙ×÷£» ÁíÍ⣬»¹¿ÉÄÜÇëÇó¿ò¼ÜΪ²ßÂÔ·ÖÅä±ê¼Ç״̬ slot Öµ¡£

static struct mac_policy_ops mac_policy_ops =
{                                   
        .mpo_destroy = mac_policy_destroy,
        .mpo_init = mac_policy_init,
        .mpo_init_bpfdesc_label = mac_policy_init_bpfdesc_label,  
        .mpo_init_cred_label = mac_policy_init_label,
/* ... */
        .mpo_check_vnode_setutimes = mac_policy_check_vnode_setutimes,
        .mpo_check_vnode_stat = mac_policy_check_vnode_stat,
        .mpo_check_vnode_write = mac_policy_check_vnode_write,
};

¡¡¡¡ÈçÉÏËùʾ£¬MAC ²ßÂÔÈë¿Úº¯ÊýÏòÁ¿£¬mac_policy_ops£¬ ½«²ßÂÔÄ£¿éÖж¨ÒåµÄ¹¦Äܺ¯Êý¹Ò½Óµ½Ìض¨µÄÈë¿Úº¯ÊýµØÖ·ÉÏ¡£ ÔÚÉÔºóµÄ¡°Èë¿Úº¯Êý²Î¿¼¡±Ð¡½ÚÖУ¬½«Ìṩ¿ÉÓÃÈë¿Úº¯Êý¹¦ÄÜÃèÊöºÍÔ­Ð͵ÄÍêÕûÁÐ±í¡£ ÓëÄ£¿é×¢²áÏà¹ØµÄÈë¿Úº¯ÊýÓÐÁ½¸ö£º.mpo_destroyºÍ.mpo_init¡£ µ±Ä³¸ö²ßÂÔÏòÄ£¿é¿ò¼Ü×¢²á²Ù×÷³É¹¦Ê±£¬.mpo_init½«±»µ÷Ó㬴˺óÆäËûµÄÈë¿Úº¯Êý²ÅÄܱ»Ê¹ÓᣠÕâÖÖÌØÊâµÄÉè¼ÆÊ¹µÃ²ßÂÔÓлú»á¸ù¾Ý×Ô¼ºµÄÐèÒª£¬½øÐÐÌØ¶¨µÄ·ÖÅäºÍ³õʼ»¯²Ù×÷£¬±ÈÈç¶ÔÌØÊâÊý¾Ý»òËøµÄ³õʼ»¯¡£ Ð¶ÔØÒ»¸ö²ßÂÔÄ£¿éʱ£¬½«µ÷Óà .mpo_destroy ÓÃÀ´ÊͷŲßÂÔ·ÖÅäµÄÄÚ´æ¿Õ¼ä»ò×¢ÏúÆäÉêÇëµÄËø¡£ Ŀǰ£¬ÎªÁË·ÀÖ¹ÆäËûÈë¿Úº¯Êý±»Í¬Ê±µ÷Ó㬵÷ÓÃÉÏÊöÁ½¸öÈë¿Úº¯ÊýµÄ½ø³Ì±ØÐë³ÖÓÐ MAC ²ßÂÔÁ´±íµÄ»¥³âËø£ºÕâÖÖÏÞÖÆ½«±»·Å¿ª£¬ µ«Óë´Ëͬʱ£¬½«ÒªÇó²ßÂÔ±ØÐë½÷É÷ʹÓÃÄÚºËÔ­Óï,ÒÔ±ÜÃâÓÉÓÚÉÏËø´ÎÐò»ò˯ÃßÔì³ÉËÀËø¡£

¡¡¡¡Ö®ËùÒÔÏò²ßÂÔÉùÃ÷Ìṩģ¿éÃû×ÖÓò£¬ÊÇΪÁËÄܹ»Î¨Ò»±êʶ¸ÃÄ£¿é£¬ÒÔ±ã½âÎöÄ£¿éÒÀÀµ¹ØÏµ¡£Ñ¡ÔñʹÓÃÇ¡µ±µÄ×Ö·û´®×÷ΪÃû×Ö¡£ ÔÚ²ßÂÔ¼ÓÔØºÍÐ¶ÔØÊ±£¬²ßÂÔµÄÍêÕû×Ö·û´®Ãû×Ö½«¾­ÓÉÄÚºËÈÕÖ¾ÏÔʾ¸øÓû§¡£ÁíÍ⣬µ±ÏòÓû§½ø³Ì±¨¸æ×´Ì¬ÐÅϢʱҲ»á°üº¬¸Ã×Ö·û´®¡£


6.6.2 ²ßÂÔ±êÖ¾

¡¡¡¡ÔÚÉùÃ÷ʱÌṩ±êÖ¾²ÎÊýÓòµÄ»úÖÆ£¬ÔÊÐí²ßÂÔÄ£¿éÔÚ×÷Ϊģ¿é±»¼ÓÔØÊ±£¬¾Í×ÔÉíÌØÐÔÏò MAC ¿ò¼ÜÌṩ˵Ã÷¡£ Ŀǰ£¬ÒѾ­¶¨ÒåµÄ±êÖ¾ÓÐÈý¸ö£º

MPC_LOADTIME_FLAG_UNLOADOK

±íʾ¸Ã²ßÂÔÄ£¿é¿ÉÒÔ±»Ð¶ÔØ¡£ Èç¹ûδÌṩ¸Ã±êÖ¾£¬Ôò±íʾ¸Ã²ßÂÔÄ£¿é¾Ü¾ø±»Ð¶ÔØ¡£ ÄÇЩʹÓð²È«±ê¼ÇµÄ״̬£¬¶øÓÖ²»ÄÜÔÚÔËÐÐʱÊͷŸÃ״̬µÄÄ£¿é¿ÉÄÜ»áÉèÖøñêÖ¾¡£

MPC_LOADTIME_FLAG_NOTLATE

±íʾ¸Ã²ßÂÔÄ£¿é±ØÐëÔÚϵͳÒýµ¼¹ý³Ìʱ½øÐмÓÔØºÍ³õʼ»¯¡£ Èç¹û¸Ã±êÖ¾±»ÉèÖã¬ÄÇôÔÚϵͳÒýµ¼Ö®ºó×¢²á¸ÃÄ£¿éµÄÇëÇ󽫱» MAC ¿ò¼ÜËù¾Ü¾ø¡£ ÄÇЩÐèҪΪ´ó·¶Î§µÄϵͳ¶ÔÏó½øÐа²È«±ê¼Ç³õʼ»¯¹¤×÷£¬¶øÓÖ²»ÄÜ´¦Àíº¬ÓÐδ±»ÕýÈ·³õʼ»¯°²È«±ê¼ÇµÄ¶ÔÏóµÄ²ßÂÔÄ£¿é¿ÉÄÜ»áÉèÖøñêÖ¾¡£

MPC_LOADTIME_FLAG_LABELMBUFS

±íʾ¸Ã²ßÂÔÄ£¿éÒªÇóΪ Mbuf Ö¸¶¨°²È«±ê¼Ç£¬²¢ÇÒΪ´æ´¢Æä±ê¼ÇËùÐèµÄÄÚ´æ¿Õ¼ä×ÜÊÇÌáǰ·ÖÅäºÃµÄ¡£ ȱʡÇé¿öÏ£¬MAC ¿ò¼Ü²¢²»»áΪ Mbuf ·ÖÅä±ê¼Ç´æ´¢£¬³ý·ÇϵͳÖÐ×¢²áµÄ²ßÂÔÄ£¿éÖÐÖÁÉÙÓÐÒ»¸öÉèÖÃÁ˸ñêÖ¾¡£ ÕâÖÖ×ö·¨ÔÚûÓвßÂÔÐèÒª¶Ô Mbuf ×ö±ê¼Çʱ£¬ÏÔÖøµØÌáÉýÁËÏµÍ³ÍøÂçÐÔÄÜ¡£ÁíÍ⣬ÔÚÄ³Ð©ÌØÊâ»·¾³Ï£¬¿ÉÒÔͨ¹ýÉèÖÃÄÚºËÑ¡Ï MAC_ALWAYS_LABEL_MBUF£¬Ç¿ÖÆ MAC ¿ò¼ÜΪ Mbuf µÄ°²È«±ê¼Ç·ÖÅä´æ´¢£¬¶ø²»ÂÛÉÏÊö±êÖ¾ÈçºÎÉèÖá£

×¢Òâ: ÄÇЩʹÓÃÁË MPC_LOADTIME_FLAG_LABELMBUFS ±êÖ¾µ«Ã»ÓÐÉèÖà MPC_LOADTIME_FLAG_NOTLATE ±êÖ¾µÄ ²ßÂÔÄ£¿é±ØÐëÄܹ»ÕýÈ·µØ´¦Àíͨ¹ýÈë¿Úº¯Êý´«ÈëµÄֵΪ NULL µÄ Mbuf °²È«±ê¼ÇÖ¸Õë¡£ ÕâÊÇÒòΪÄÇЩûÓзÖÅä±ê¼Ç´æ´¢µÄ´¦ÀíÖÐµÄ Mbuf ÔÚÒ»¸öÐèÒª Mbuf °²È«±ê¼ÇµÄ²ßÂÔÄ£¿é¼ÓÔØÖ®ºó£¬ Æä°²È«±ê¼ÇµÄÖ¸Õ뽫ÈÔȻΪ¿Õ¡£ Èç¹û²ßÂÔÔÚÍøÂç×Óϵͳ»îԾ֮ǰ±»¼ÓÔØ£¨¼´£¬¸Ã²ßÂÔ²»ÊDZ»ÍƳټÓÔØµÄ£©£¬ÄÇôËùÓÐµÄ Mbuf µÄ±ê¼Ç´æ´¢µÄ·ÖÅä¾Í¿ÉÒԵõ½±£Ö¤¡£


6.6.3 ²ßÂÔÈë¿Úº¯Êý

¡¡¡¡MAC ¿ò¼ÜΪע²áµÄ²ßÂÔÌṩËÄÖÖÀàÐ͵ÄÈë¿Úº¯Êý£º ²ßÂÔ×¢²áºÍ¹ÜÀíÈë¿Úº¯Êý£» ÓÃÓÚ´¦ÀíÄں˶ÔÏóÉùÃ÷ÖÜÆÚʼþ£¬Èç³õʼ»¯¡¢ ´´½¨ºÍÏú»Ù£¬µÄÈë¿Úº¯Êý£» ´¦Àí¸Ã²ßÂÔÄ£¿é¸ÐÐËȤµÄ·ÃÎÊ¿ØÖƾö²ßʼþµÄÈë¿Úº¯Êý£» ÒÔ¼°ÓÃÓÚ¹ÜÀí¶ÔÏó°²È«±ê¼ÇµÄµ÷ÓÃÈë¿Úº¯Êý¡£ ´ËÍ⣬ »¹ÓÐÒ»¸ö mac_syscall() Èë¿Úº¯Êý£¬ ±»²ßÂÔÄ£¿éÓÃÓÚÔÚ²»×¢²áеÄϵͳµ÷ÓõÄǰÌáÏ£¬ À©Õ¹Äں˽ӿڡ£

¡¡¡¡²ßÂÔÄ£¿éµÄ±àдÈËÔ±³ýÁ˱ØÐëÇå³þÔÚ½øÈëÌØ¶¨Èë¿Úº¯ÊýÖ®ºó£¬ ÄÄЩ¶ÔÏóËøÊÇ¿ÉÓõÄÖ®Í⣬ »¹Ó¦¸ÃÊìÖªÄÚºËËù²ÉÓõļÓËø²ßÂÔ¡£ ±à³ÌÈËÔ±ÔÚÈë¿Úº¯ÊýÖ®ÄÚÓ¦¸Ã±ÜÃâʹÓ÷ÇÒ¶½ÚµãËø£¬ ²¢ÇÒ×ñÑ­·ÃÎʺÍÐ޸ĶÔÏóʱµÄ¼ÓËø¹æ³Ì£¬ ÒÔ½µµÍµ¼ÖÂËÀËøµÄ¿ÉÄÜÐÔ¡£ ÌØ±ðµØ£¬ ³ÌÐòÔ±Ó¦¸ÃÇå³þ£¬ ËäÈ»ÔÚͨ³£Çé¿öÏ£¬ ½øÈëÈë¿Úº¯ÊýÖ®ºó£¬ ÒѾ­ÉÏÁËÒ»Ð©Ëø£¬ ¿ÉÒÔ°²È«µØ·ÃÎʶÔÏó¼°Æä°²È«±ê¼Ç£¬ µ«ÊÇÕâ²¢²»Äܱ£Ö¤¶ÔËüÃǽøÐÐÐ޸ģ¨ °üÀ¨¶ÔÏó±¾ÉíºÍÆä°²È«±ê¼Ç£© Ò²Êǰ²È«µÄ¡£ Ïà¹ØµÄÉÏËøÐÅÏ¢£¬¿ÉÒԲο¼ MAC ¿ò¼ÜÈë¿Úº¯ÊýµÄÏà¹ØÎĵµ¡£

¡¡¡¡²ßÂÔÈë¿Úº¯Êý°ÑÁ½¸ö·Ö±ðÖ¸Ïò¶ÔÏó±¾ÉíºÍÆä°²È«±ê¼ÇµÄÖ¸Õë´«µÝ¸ø²ßÂÔÄ£¿é¡£ ÕâÑùÒ»À´£¬¼´Ê¹²ßÂÔ²¢²»ÊìϤ¶ÔÏóÄÚ²¿½á¹¹£¬Ò²ÄÜ»ùÓÚ±ê¼Ç×÷³öÕýÈ·¾ö²ß¡£ Ö»Óнø³ÌÐÅÈÎ×´Õâ¸ö¶ÔÏóÀýÍ⣺MAC ¿ò¼Ü×ÜÊǼÙÉèËùÓеIJßÂÔÄ£¿éÊÇÀí½âÆäÄÚ²¿½á¹¹µÄ¡£


6.7 MAC²ßÂÔÈë¿Úº¯Êý²Î¿¼

6.7.1 ͨÓõÄÄ£¿éÈë¿Úº¯Êý

6.7.1.1 mpo_init

void mpo_init(struct mac_policy_conf *conf);

²ÎÊý ˵Ã÷ Ëø¶¨
conf MAC ²ßÂÔ¶¨Òå  

¡¡¡¡²ßÂÔ¼ÓÔØÊ¼þ¡£µ±Ç°½ø³ÌÕý³ÖÓвßÂÔÁ´±íÉϵĻ¥³âËø£¬Òò´ËÊÇ·Ç˯Ãߵģ¬¶ÔÆäËûÄÚºË×ÓϵͳµÄµ÷ÓÃÒ²ÐëÉ÷ÖØ¡£ Èç¹ûÐèÒªÔÚ²ßÂÔ³õʼ»¯½×¶Î½øÐпÉÄÜÔì³É˯Ãß×èÈûµÄ´æ´¢·ÖÅä²Ù×÷£¬¿ÉÒÔ½«ËüÃÇ·ÅÔÚÒ»¸öµ¥¶ÀµÄÄ£¿é SYSINIT() ¹ý³ÌÖм¯ÖнøÐС£


6.7.1.2 mpo_destroy

void mpo_destroy(struct mac_policy_conf *conf);

²ÎÊý ˵Ã÷ Ëø¶¨
conf MAC ²ßÂÔ¶¨Òå  

¡¡¡¡²ßÂÔ¼ÓÔØÊ¼þ¡£±ØÐë³ÖÓвßÂÔÁ´±í»¥³âËø£¬Òò´ËÐèÒªÉ÷ÖØÐÐÊ¡£


6.7.1.3 mpo_syscall

int mpo_syscall(struct thread *td, int call, void *arg);

²ÎÊý ˵Ã÷ Ëø¶¨
td µ÷ÓÃÏß³Ì  
call ²ßÂÔÌØÓеÄϵͳµ÷ÓñàºÅ  
arg ϵͳµ÷ÓòÎÊýµÄÖ¸Õë  

¡¡¡¡¸ÃÈë¿Úº¯ÊýÌṩ²ßÂÔ¸´ÓõÄϵͳµ÷Óã¬ÕâÑù²ßÂÔÄ£¿é²»ÐèҪΪÆäÏòÓû§½ø³ÌÌṩµÄÿһ¸ö¶îÍâ·þÎñ¶ø×¢²áרÓõÄϵͳµ÷ÓᣠÓÉÓ¦ÓóÌÐòÌṩµÄ²ßÂÔ×¢²áÃû×ÖÀ´È·¶¨ÌṩÆäËùÉêÇë·þÎñµÄÌØ¶¨²ßÂÔ£¬ËùÓвÎÊý½«Í¨¹ý¸ÃÈë¿Úº¯Êý´«µÝ¸ø±»µ÷ÓõIJßÂÔ¡£ µ±ÊµÏÖзþÎñʱ£¬°²È«Ä£¿é±ØÐëÔÚ±ØÒªÊ±Í¨¹ý MAC ¿ò¼Üµ÷ÓÃÏàÓ¦µÄ·ÃÎÊ¿ØÖƼì²é»úÖÆ¡£ ±È·½Ëµ£¬¼ÙÈçÒ»¸ö²ßÂÔʵÏÖÁËijÖÖ¶îÍâµÄÐźŹ¦ÄÜ£¬ÄÇôËüÓ¦¸Ãµ÷ÓÃÏà¹ØµÄÐźŷÃÎÊ¿ØÖƼì²é£¬ÒÔ½ÓÊÜ MAC ¿ò¼ÜÖÐ×¢²áµÄÆäËû²ßÂԵļì²é¡£

×¢Òâ: ²»Í¬µÄÄ£¿éÐèÒª²¢·¢µØÊÖ¶¯½øÐÐcopyin()¿½±´ÏµÍ³µ÷ÓÃÊý¾Ý¡£


6.7.1.4 mpo_thread_userret

void mpo_thread_userret(struct thread *td);

²ÎÊý ˵Ã÷ Ëø¶¨
td ·µ»ØÏß³Ì  

¡¡¡¡Ê¹ÓøÃÈë¿Úº¯Êý£¬²ßÂÔÄ£¿éÄܹ»ÔÚÏ̷߳µ»ØÓû§¿Õ¼äʱ£¨ÏµÍ³µ÷Ó÷µ»Ø¡¢Òì³£·µ»ØµÈµÈ£©½øÐÐ MAC Ïà¹ØµÄ´¦Àí¹¤×÷¡£ ʹÓö¯Ì¬½ø³Ì±ê¼ÇµÄ²ßÂÔÐèҪʹÓøÃÈë¿Úº¯Êý£¬ÒòΪÔÚ´¦Àíϵͳµ÷ÓõĹý³ÌÖУ¬²¢²»ÊÇÔÚÈÎÒâʱ¿Ì¶¼ÄÜÉêÇëµ½½ø³ÌËøµÄ£» ½ø³ÌµÄ±ê¼Ç¿ÉÄܱíʾ´«Í³µÄÈÏÖ¤ÐÅÏ¢¡¢½ø³ÌÀúÊ·¼Ç¼»òÕ߯äËûÊý¾Ý¡£ÎªÊ¹ÓøÃÈë¿Úº¯Êý£¬¶Ô½ø³ÌÐÅÈÎ×´Ëù×÷µÄÐÞ¸Ä ¿ÉÄܱ»´æ·ÅÔÚ p_label ,¸ÃÓòÊÜÒ»¸ö½ø³Ì¼¶×ÔÐýËøµÄ±£»¤£»½ÓÏÂÀ´£¬ÉèÖÃÏ̼߳¶µÄTDF_ASTPENDING ±ê־λºÍ½ø³Ì¼¶µÄPS_MACPENDM±ê־룬±íÃ÷½«µ÷¶ÈÒ»¸ö¶Ô userret Èë¿Úº¯ÊýµÄµ÷Óá£Í¨¹ý¸ÃÈë¿Úº¯Êý£¬ ²ßÂÔ¿ÉÒÔÔÚÏà¶Ô¼òµ¥µÄͬ²½ÉÏÏÂÎÄÖд´½¨ÐÅÈÎ×´µÄÌæ´úÆ·¡£²ßÂÔ±à³ÌÈËÔ±±ØÐëÇå³þ£¬ÐèÒª±£Ö¤Óëµ÷¶ÈÒ»¸ö AST Ïà¹ØµÄʼþÖ´ÐдÎÐò£¬ ͬʱËùÖ´ÐÐµÄ AST ¿ÉÄܸܺ´ÔÓ£¬¶øÇÒÔÚ´¦Àí¶àÏß³ÌÓ¦ÓóÌÐòʱ¿ÉÄܱ»ÖØÈë¡£


6.7.2 ²Ù×÷±ê¼Ç

6.7.2.1 mpo_init_bpfdesc_label

void mpo_init_bpfdesc_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ó¦ÓõÄбê¼Ç  

¡¡¡¡ÎªÒ»¸öнüʵÀý»¯µÄ bpfdesc£¨BPF ÃèÊö×Ó£©³õʼ»¯±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.2 mpo_init_cred_label

void mpo_init_cred_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»³õʼ»¯µÄбê¼Ç  

¡¡¡¡ÎªÒ»¸öнüʵÀý»¯µÄÓû§ÐÅÈÎ×´³õʼ»¯±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.3 mpo_init_devfsdirent_label

void mpo_init_devfsdirent_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ó¦ÓõÄбê¼Ç  

¡¡¡¡ÎªÒ»¸öнüʵÀý»¯µÄ devfs¡¡±íÏî³õʼ»¯±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.4 mpo_init_ifnet_label

void mpo_init_ifnet_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ó¦ÓõÄбê¼Ç  

¡¡¡¡ÎªÒ»¸öнüʵÀý»¯µÄÍøÂç½Ó¿Ú³õʼ»¯±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.5 mpo_init_ipq_label

void mpo_init_ipq_label(struct label *label, int flag);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ó¦ÓõÄбê¼Ç  
flag ˯Ãß/²»Ë¯Ãß malloc(9); ²Î¼ûÏÂÎÄ  

¡¡¡¡ÎªÒ»¸öнüʵÀý»¯µÄ IP ·ÖÆ¬ÖØ×é¶ÓÁгõʼ»¯±ê¼Ç¡£ÆäÖеÄflagÓò¿ÉÄÜÈ¡M_WAITOK »òM_NOWAITÖ®Ò»£¬ÓÃÀ´±ÜÃâÔڸóõʼ»¯µ÷ÓÃÖÐÒòΪ malloc(9) ¶ø½øÈë˯Ãß¡£IP ·ÖÆ¬ÖØ×é¶ÓÁеķÖÅä²Ù×÷ͨ³£ÊÇÔÚ ¶ÔÐÔÄÜÓÐÑϸñÒªÇóµÄ»·¾³Ï½øÐеģ¬Òò´ËʵÏÖ´úÂë±ØÐëСÐĵرÜÃâ˯Ãߺͳ¤Ê±¼äµÄ²Ù×÷¡£IP ·ÖÆ¬ÖØ×é¶ÓÁзÖÅä²Ù×÷ʧ°ÜʱÉÏÊöÈë¿Úº¯Êý½«Ê§°Ü·µ»Ø¡£


6.7.2.6 mpo_init_mbuf_label

void mpo_init_mbuf_label(int flag, struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
flag ˯Ãß/²»Ë¯Ãß malloc(9); ²Î¼ûÏÂÎÄ  
label ½«±»³õʼ»¯µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡ÎªÒ»¸öнüʵÀý»¯µÄ mbuf Êý¾Ý°üÍ·²¿£¨mbuf£©³õʼ»¯±ê¼Ç¡£ ÆäÖеÄflagµÄÖµ¿ÉÄÜÈ¡M_WAITOKºÍM_NOWAITÖ®Ò»£¬ ÓÃÀ´±ÜÃâÔڸóõʼ»¯µ÷ÓÃÖÐÒòΪ malloc(9) ¶ø½øÈë˯Ãß¡£Mbuf Í·²¿µÄ·ÖÅä²Ù×÷³£³£ÔÚ¶ÔÐÔÄÜÓÐÑϸñÒªÇóµÄ»·¾³Ï±»Æµ·±Ö´ÐУ¬ Òò´ËʵÏÖ´úÂë±ØÐëСÐĵرÜÃâ˯Ãߺͳ¤Ê±¼äµÄ²Ù×÷¡£ÉÏÊöÈë¿Úº¯ÊýÔÚ Mbuf Í·²¿·ÖÅä²Ù×÷ʧ°Üʱ½«Ê§°Ü·µ»Ø¡£


6.7.2.7 mpo_init_mount_label

void mpo_init_mount_label(struct label *mntlabel, struct label *fslabel);

²ÎÊý ˵Ã÷ Ëø¶¨
mntlabel ½«±»³õʼ»¯µÄmount ½á¹¹²ßÂÔ±ê¼Ç  
fslabel ½«±»³õʼ»¯µÄÎļþϵͳ²ßÂÔ±ê¼Ç  

¡¡¡¡ÎªÒ»¸öнüʵÀý»¯µÄ mount µã³õʼ»¯±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.8 mpo_init_mount_fs_label

void mpo_init_mount_fs_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»³õʼ»¯µÄ±ê¼Ç  

¡¡¡¡ÎªÒ»¸öнü¼ÓÔØµÄÎļþϵͳ³õʼ»¯±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.9 mpo_init_pipe_label

void mpo_init_pipe_label(struct label*label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»ÌîдµÄ±ê¼Ç  

¡¡¡¡ÎªÒ»¸ö¸Õ¸ÕʵÀý»¯µÄ¹ÜµÀ³õʼ»¯°²È«±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.10 mpo_init_socket_label

void mpo_init_socket_label(struct label *label, int flag);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»³õʼ»¯µÄбê¼Ç  
flag malloc(9) flags  

¡¡¡¡ÎªÒ»¸ö¸Õ¸ÕʵÀý»¯µÄÌ×½Ó×Ö³õʼ»¯°²È«±ê¼Ç¡£ÆäÖÐµÄ flag ÓòµÄÖµ±ØÐë±»Ö¸¶¨Îª M_WAITOKºÍM_NOWAITÖ®Ò»£¬ÒÔ±ÜÃâÔڸóõʼ»¯³ÌÖÐʹÓÿÉÄÜ˯ÃßµÄmalloc(9) ¡£


6.7.2.11 mpo_init_socket_peer_label

void mpo_init_socket_peer_label(struct label *label, int flag);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»³õʼ»¯µÄбê¼Ç  
flag malloc(9) flags  

¡¡¡¡Îª¸Õ¸ÕʵÀý»¯µÄÌ×½Ó×Ö¶ÔµÈÌå½øÐбê¼ÇµÄ³õʼ»¯¡£ÆäÖÐµÄ flag ÓòµÄÖµ±ØÐë±»Ö¸¶¨Îª M_WAITOK ºÍ M_NOWAIT Ö®Ò»£¬ÒÔ±ÜÃâÔڸóõʼ»¯³ÌÖÐʹÓÿÉÄÜ˯ÃßµÄ malloc(9)¡£


6.7.2.12 mpo_init_proc_label

void mpo_init_proc_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»³õʼ»¯µÄбê¼Ç  

¡¡¡¡ÎªÒ»¸ö¸Õ¸ÕʵÀý»¯µÄ½ø³Ì³õʼ»¯°²È«±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.13 mpo_init_vnode_label

void mpo_init_vnode_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»³õʼ»¯µÄбê¼Ç  

¡¡¡¡ÎªÒ»¸ö¸Õ¸ÕʵÀý»¯µÄ vnode ³õʼ»¯°²È«±ê¼Ç¡£¿ÉÒÔ˯Ãß¡£


6.7.2.14 mpo_destroy_bpfdesc_label

void mpo_destroy_bpfdesc_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label bpfdesc ±ê¼Ç  

¡¡¡¡Ïú»ÙÒ»¸ö BPF ÃèÊö×ÓÉϵıê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäÓë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.15 mpo_destroy_cred_label

void mpo_destroy_cred_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ïú»ÙµÄ±ê¼Ç  

¡¡¡¡Ïú»ÙÒ»¸öÐÅÈÎ×´Éϵıê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄÓë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.16 mpo_destroy_devfsdirent_label

void mpo_destroy_devfsdirent_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ïú»ÙµÄ±ê¼Ç  

¡¡¡¡Ïú»ÙÒ»¸ö devfs ±íÏîÉϵıê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄÓë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.17 mpo_destroy_ifnet_label

void mpo_destroy_ifnet_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ïú»ÙµÄ±ê¼Ç  

¡¡¡¡Ïú»ÙÓëÒ»¸öÒÑɾ³ý½Ó¿ÚÏà¹ØÁªµÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄÓë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.18 mpo_destroy_ipq_label

void mpo_destroy_ipq_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ïú»ÙµÄ±ê¼Ç  

¡¡¡¡Ïú»ÙÓëÒ»¸ö IP ·ÖƬ¶ÓÁÐÏà¹ØÁªµÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄÓë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.19 mpo_destroy_mbuf_label

void mpo_destroy_mbuf_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ïú»ÙµÄ±ê¼Ç  

¡¡¡¡Ïú»ÙÓëÒ»¸ö Mbuf Ïà¹ØÁªµÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄÓë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.20 mpo_destroy_mount_label

void mpo_destroy_mount_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ïú»ÙµÄ Mount µã±ê¼Ç  

¡¡¡¡Ïú»ÙÓëÒ»¸ö mount µãÏà¹ØÁªµÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄÓë mntlabel Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.21 mpo_destroy_mount_label

void mpo_destroy_mount_label(struct label *mntlabel, struct label *fslabel);

²ÎÊý ˵Ã÷ Ëø¶¨
mntlabel ½«±»Ïú»ÙµÄ Mount µã±ê¼Ç  
fslabel File system label being destroyed>  

¡¡¡¡Ïú»ÙÓëÒ»¸ö mount µãÏà¹ØÁªµÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄ£¬Óë mntlabel ºÍfslabel Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.22 mpo_destroy_socket_label

void mpo_destroy_socket_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ïú»ÙµÄÌ×½Ó×Ö±ê¼Ç  

¡¡¡¡Ïú»ÙÓëÒ»¸öÌ×½Ó×ÖÏà¹ØÁªµÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄ£¬Óë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.23 mpo_destroy_socket_peer_label

void mpo_destroy_socket_peer_label(struct label *peerlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
peerlabel ½«±»Ïú»ÙµÄÌ×½Ó×Ö¶ÔµÈʵÌå±ê¼Ç  

¡¡¡¡Ïú»ÙÓëÒ»¸öÌ×½Ó×ÖÏà¹ØÁªµÄ¶ÔµÈʵÌå±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄ£¬Óë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.24 mpo_destroy_pipe_label

void mpo_destroy_pipe_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ¹ÜµÀ±ê¼Ç  

¡¡¡¡Ïú»ÙÒ»¸ö¹ÜµÀµÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄ£¬Óë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.25 mpo_destroy_proc_label

void mpo_destroy_proc_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½ø³Ì±ê¼Ç  

¡¡¡¡Ïú»ÙÒ»¸ö½ø³ÌµÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄ£¬Óë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.26 mpo_destroy_vnode_label

void mpo_destroy_vnode_label(struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½ø³Ì±ê¼Ç  

¡¡¡¡Ïú»ÙÒ»¸ö vnode µÄ±ê¼Ç¡£ÔÚ¸ÃÈë¿Úº¯ÊýÖУ¬²ßÂÔÓ¦µ±ÊÍ·ÅËùÓÐÔÚÄÚ²¿·ÖÅäµÄ£¬Óë label Ïà¹ØÁªµÄ´æ´¢¿Õ¼ä£¬ÒÔ±ãÏú»Ù¸Ã±ê¼Ç¡£


6.7.2.27 mpo_copy_mbuf_label

void mpo_copy_mbuf_label(struct label *src, struct label *dest);

²ÎÊý ˵Ã÷ Ëø¶¨
src Ô´±ê¼Ç  
dest Ä¿±ê±ê¼Ç  

¡¡¡¡½« src Öеıê¼ÇÐÅÏ¢¿½±´µ½ destÖС£


6.7.2.28 mpo_copy_pipe_label

void mpo_copy_pipe_label(struct label *src, struct label *dest);

²ÎÊý ˵Ã÷ Ëø¶¨
src Ô´±ê¼Ç  
dest Ä¿±ê±ê¼Ç  

¡¡¡¡½« src Öеıê¼ÇÐÅÏ¢¿½±´ÖÁ dest¡£


6.7.2.29 mpo_copy_vnode_label

void mpo_copy_vnode_label(struct label *src, struct label *dest);

²ÎÊý ˵Ã÷ Ëø¶¨
src Ô´±ê¼Ç  
dest Ä¿±ê±ê¼Ç  

¡¡¡¡½« src Öеıê¼ÇÐÅÏ¢¿½±´ÖÁ dest¡£


6.7.2.30 mpo_externalize_cred_label

int mpo_externalize_cred_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«ÓÃÍⲿÐÎʽ±íʾµÄ±ê¼Ç  
element_name ÐèÒªÍⲿ±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
sb ÓÃÀ´´æ·Å±ê¼ÇµÄÎı¾±íʾÐÎʽµÄ×Ö·ûbuffer  
claimed Èç¹û¿ÉÒÔÌî³äelement_data Óò£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾Ý´«ÈëµÄ±ê¼Ç½á¹¹£¬²úÉúÒ»¸öÒÔÍⲿÐÎʽ±íʾµÄ±ê¼Ç¡£ Ò»¸öÍⲿÐÎʽ±ê¼Ç£¬ÊDZê¼ÇÄÚÈݵÄÎı¾±íʾ£¬ËüÓÉÓû§¼¶µÄÓ¦ÓóÌÐòʹÓã¬ÊÇÓû§¿É¶ÁµÄ¡£ ĿǰµÄMACʵÏÖ·½°¸½«ÒÀ´Îµ÷ÓòßÂÔµÄÏàÓ¦Èë¿Úº¯Êý£¬Òò´Ë£¬ ¾ßÌå²ßÂÔµÄʵÏÖ´úÂ룬ÐèÒªÔÚÌîдsb֮ǰ£¬Ïȼì²éelement_nameÖÐÖ¸¶¨µÄÃû×Ö¡£ Èç¹ûelement_nameÖеÄÄÚÈÝÓëÄãµÄ²ßÂÔÃû×Ö²»Ïà·û£¬ÔòÖ±½Ó·µ»Ø0¡£ ½öµ±×ª»»±ê¼ÇÊý¾ÝµÄ¹ý³ÌÖгöÏÖ´íÎóʱ£¬²Å·µ»Ø·Ç0Öµ¡£ Ò»µ©²ßÂÔ¾ö¶¨Ìîдelement_data£¬µÝÔö*claimµÄÊýÖµ¡£


6.7.2.31 mpo_externalize_ifnet_label

int mpo_externalize_ifnet_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«ÓÃÍⲿÐÎʽ±íʾµÄ±ê¼Ç  
element_name ÐèÒªÍⲿ±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
sb ÓÃÀ´´æ·Å±ê¼ÇµÄÎı¾±íʾÐÎʽµÄ×Ö·ûbuffer  
claimed Èç¹û¿ÉÒÔÌî³äelement_data Óò£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾Ý´«ÈëµÄ±ê¼Ç½á¹¹£¬²úÉúÒ»¸öÒÔÍⲿÐÎʽ±íʾµÄ±ê¼Ç¡£ Ò»¸öÍⲿÐÎʽ±ê¼Ç£¬ÊDZê¼ÇÄÚÈݵÄÎı¾±íʾ£¬ËüÓÉÓû§¼¶µÄÓ¦ÓóÌÐòʹÓã¬ÊÇÓû§¿É¶ÁµÄ¡£ ĿǰµÄMACʵÏÖ·½°¸½«ÒÀ´Îµ÷ÓòßÂÔµÄÏàÓ¦Èë¿Úº¯Êý£¬Òò´Ë£¬ ¾ßÌå²ßÂÔµÄʵÏÖ´úÂ룬ÐèÒªÔÚÌîдsb֮ǰ£¬Ïȼì²éelement_nameÖÐÖ¸¶¨µÄÃû×Ö¡£ Èç¹ûelement_nameÖеÄÄÚÈÝÓëÄãµÄ²ßÂÔÃû×Ö²»Ïà·û£¬ÔòÖ±½Ó·µ»Ø0¡£ ½öµ±×ª»»±ê¼ÇÊý¾ÝµÄ¹ý³ÌÖгöÏÖ´íÎóʱ£¬²Å·µ»Ø·Ç0Öµ¡£ Ò»µ©²ßÂÔ¾ö¶¨Ìîдelement_data£¬µÝÔö*claimµÄÊýÖµ¡£


6.7.2.32 mpo_externalize_pipe_label

int mpo_externalize_pipe_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«ÓÃÍⲿÐÎʽ±íʾµÄ±ê¼Ç  
element_name ÐèÒªÍⲿ±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
sb ÓÃÀ´´æ·Å±ê¼ÇµÄÎı¾±íʾÐÎʽµÄ×Ö·ûbuffer  
claimed Èç¹û¿ÉÒÔÌî³äelement_data Óò£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾Ý´«ÈëµÄ±ê¼Ç½á¹¹£¬²úÉúÒ»¸öÒÔÍⲿÐÎʽ±íʾµÄ±ê¼Ç¡£ Ò»¸öÍⲿÐÎʽ±ê¼Ç£¬ÊDZê¼ÇÄÚÈݵÄÎı¾±íʾ£¬ËüÓÉÓû§¼¶µÄÓ¦ÓóÌÐòʹÓã¬ÊÇÓû§¿É¶ÁµÄ¡£ ĿǰµÄMACʵÏÖ·½°¸½«ÒÀ´Îµ÷ÓòßÂÔµÄÏàÓ¦Èë¿Úº¯Êý£¬Òò´Ë£¬ ¾ßÌå²ßÂÔµÄʵÏÖ´úÂ룬ÐèÒªÔÚÌîдsb֮ǰ£¬Ïȼì²éelement_nameÖÐÖ¸¶¨µÄÃû×Ö¡£ Èç¹ûelement_nameÖеÄÄÚÈÝÓëÄãµÄ²ßÂÔÃû×Ö²»Ïà·û£¬ÔòÖ±½Ó·µ»Ø0¡£ ½öµ±×ª»»±ê¼ÇÊý¾ÝµÄ¹ý³ÌÖгöÏÖ´íÎóʱ£¬²Å·µ»Ø·Ç0Öµ¡£ Ò»µ©²ßÂÔ¾ö¶¨Ìîдelement_data£¬µÝÔö*claimµÄÊýÖµ¡£


6.7.2.33 mpo_externalize_socket_label

int mpo_externalize_socket_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«ÓÃÍⲿÐÎʽ±íʾµÄ±ê¼Ç  
element_name ÐèÒªÍⲿ±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
sb ÓÃÀ´´æ·Å±ê¼ÇµÄÎı¾±íʾÐÎʽµÄ×Ö·ûbuffer  
claimed Èç¹û¿ÉÒÔÌî³äelement_data Óò£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾Ý´«ÈëµÄ±ê¼Ç½á¹¹£¬²úÉúÒ»¸öÒÔÍⲿÐÎʽ±íʾµÄ±ê¼Ç¡£ Ò»¸öÍⲿÐÎʽ±ê¼Ç£¬ÊDZê¼ÇÄÚÈݵÄÎı¾±íʾ£¬ËüÓÉÓû§¼¶µÄÓ¦ÓóÌÐòʹÓã¬ÊÇÓû§¿É¶ÁµÄ¡£ ĿǰµÄMACʵÏÖ·½°¸½«ÒÀ´Îµ÷ÓòßÂÔµÄÏàÓ¦Èë¿Úº¯Êý£¬Òò´Ë£¬ ¾ßÌå²ßÂÔµÄʵÏÖ´úÂ룬ÐèÒªÔÚÌîдsb֮ǰ£¬Ïȼì²éelement_nameÖÐÖ¸¶¨µÄÃû×Ö¡£ Èç¹ûelement_nameÖеÄÄÚÈÝÓëÄãµÄ²ßÂÔÃû×Ö²»Ïà·û£¬ÔòÖ±½Ó·µ»Ø0¡£ ½öµ±×ª»»±ê¼ÇÊý¾ÝµÄ¹ý³ÌÖгöÏÖ´íÎóʱ£¬²Å·µ»Ø·Ç0Öµ¡£ Ò»µ©²ßÂÔ¾ö¶¨Ìîдelement_data£¬µÝÔö*claimµÄÊýÖµ¡£


6.7.2.34 mpo_externalize_socket_peer_label

int mpo_externalize_socket_peer_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«ÓÃÍⲿÐÎʽ±íʾµÄ±ê¼Ç  
element_name ÐèÒªÍⲿ±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
sb ÓÃÀ´´æ·Å±ê¼ÇµÄÎı¾±íʾÐÎʽµÄ×Ö·ûbuffer  
claimed Èç¹û¿ÉÒÔÌî³äelement_data Óò£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾Ý´«ÈëµÄ±ê¼Ç½á¹¹£¬²úÉúÒ»¸öÒÔÍⲿÐÎʽ±íʾµÄ±ê¼Ç¡£ Ò»¸öÍⲿÐÎʽ±ê¼Ç£¬ÊDZê¼ÇÄÚÈݵÄÎı¾±íʾ£¬ËüÓÉÓû§¼¶µÄÓ¦ÓóÌÐòʹÓã¬ÊÇÓû§¿É¶ÁµÄ¡£ ĿǰµÄMACʵÏÖ·½°¸½«ÒÀ´Îµ÷ÓòßÂÔµÄÏàÓ¦Èë¿Úº¯Êý£¬Òò´Ë£¬ ¾ßÌå²ßÂÔµÄʵÏÖ´úÂ룬ÐèÒªÔÚÌîдsb֮ǰ£¬Ïȼì²éelement_nameÖÐÖ¸¶¨µÄÃû×Ö¡£ Èç¹ûelement_nameÖеÄÄÚÈÝÓëÄãµÄ²ßÂÔÃû×Ö²»Ïà·û£¬ÔòÖ±½Ó·µ»Ø0¡£ ½öµ±×ª»»±ê¼ÇÊý¾ÝµÄ¹ý³ÌÖгöÏÖ´íÎóʱ£¬²Å·µ»Ø·Ç0Öµ¡£ Ò»µ©²ßÂÔ¾ö¶¨Ìîдelement_data£¬µÝÔö*claimµÄÊýÖµ¡£


6.7.2.35 mpo_externalize_vnode_label

int mpo_externalize_vnode_label(struct label *label, char *element_name, struct sbuf *sb, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«ÓÃÍⲿÐÎʽ±íʾµÄ±ê¼Ç  
element_name ÐèÒªÍⲿ±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
sb ÓÃÀ´´æ·Å±ê¼ÇµÄÎı¾±íʾÐÎʽµÄ×Ö·ûbuffer  
claimed Èç¹û¿ÉÒÔÌî³äelement_data Óò£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾Ý´«ÈëµÄ±ê¼Ç½á¹¹£¬²úÉúÒ»¸öÒÔÍⲿÐÎʽ±íʾµÄ±ê¼Ç¡£ Ò»¸öÍⲿÐÎʽ±ê¼Ç£¬ÊDZê¼ÇÄÚÈݵÄÎı¾±íʾ£¬ËüÓÉÓû§¼¶µÄÓ¦ÓóÌÐòʹÓã¬ÊÇÓû§¿É¶ÁµÄ¡£ ĿǰµÄMACʵÏÖ·½°¸½«ÒÀ´Îµ÷ÓòßÂÔµÄÏàÓ¦Èë¿Úº¯Êý£¬Òò´Ë£¬ ¾ßÌå²ßÂÔµÄʵÏÖ´úÂ룬ÐèÒªÔÚÌîдsb֮ǰ£¬Ïȼì²éelement_nameÖÐÖ¸¶¨µÄÃû×Ö¡£ Èç¹ûelement_nameÖеÄÄÚÈÝÓëÄãµÄ²ßÂÔÃû×Ö²»Ïà·û£¬ÔòÖ±½Ó·µ»Ø0¡£ ½öµ±×ª»»±ê¼ÇÊý¾ÝµÄ¹ý³ÌÖгöÏÖ´íÎóʱ£¬²Å·µ»Ø·Ç0Öµ¡£ Ò»µ©²ßÂÔ¾ö¶¨Ìîдelement_data£¬µÝÔö*claimµÄÊýÖµ¡£


6.7.2.36 mpo_internalize_cred_label

int mpo_internalize_cred_label(struct label *label, char *element_name, char *element_data, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ìî³äµÄ±ê¼Ç  
element_name ÐèÒªÄÚ²¿±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
element_data ÐèÒª±»×ª»»µÄÎı¾Êý¾Ý  
claimed Èç¹ûÊý¾Ý±»Õýȷת»»£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾ÝÒ»¸öÎı¾ÐÎʽµÄÍⲿ±íʾ±ê¼ÇÊý¾Ý£¬´´½¨Ò»¸öÄÚ²¿ÐÎʽµÄ±ê¼Ç½á¹¹¡£ ĿǰµÄMAC·½°¸½«ÒÀ´Îµ÷ÓÃËùÓвßÂÔµÄÏà¹ØÈë¿Úº¯Êý£¬À´ÏìÓ¦±ê¼ÇµÄÄÚ²¿×ª»»ÇëÇó£¬ Òò´Ë£¬ÊµÏÖ´úÂë±ØÐëÊ×ÏÈͨ¹ý±È½Ïelement_nameÖеÄÄÚÈݺÍ×Ô¼ºµÄ²ßÂÔÃû×Ö£¬ À´È·¶¨ÊÇ·ñÐèҪת»»element_dataÖдæ·ÅµÄÊý¾Ý¡£ ÀàËÆµÄ£¬Èç¹ûÃû×Ö²»Æ¥Åä»òÕßÊý¾Ýת»»²Ù×÷³É¹¦£¬¸Ãº¯Êý·µ»Ø0£¬²¢µÝÔö*claimedµÄÖµ¡£


6.7.2.37 mpo_internalize_ifnet_label

int mpo_internalize_ifnet_label(struct label *label, char *element_name, char *element_data, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ìî³äµÄ±ê¼Ç  
element_name ÐèÒªÄÚ²¿±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
element_data ÐèÒª±»×ª»»µÄÎı¾Êý¾Ý  
claimed Èç¹ûÊý¾Ý±»Õýȷת»»£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾ÝÒ»¸öÎı¾ÐÎʽµÄÍⲿ±íʾ±ê¼ÇÊý¾Ý£¬´´½¨Ò»¸öÄÚ²¿ÐÎʽµÄ±ê¼Ç½á¹¹¡£ ĿǰµÄMAC·½°¸½«ÒÀ´Îµ÷ÓÃËùÓвßÂÔµÄÏà¹ØÈë¿Úº¯Êý£¬À´ÏìÓ¦±ê¼ÇµÄÄÚ²¿×ª»»ÇëÇó£¬ Òò´Ë£¬ÊµÏÖ´úÂë±ØÐëÊ×ÏÈͨ¹ý±È½Ïelement_nameÖеÄÄÚÈݺÍ×Ô¼ºµÄ²ßÂÔÃû×Ö£¬ À´È·¶¨ÊÇ·ñÐèҪת»»element_dataÖдæ·ÅµÄÊý¾Ý¡£ ÀàËÆµÄ£¬Èç¹ûÃû×Ö²»Æ¥Åä»òÕßÊý¾Ýת»»²Ù×÷³É¹¦£¬¸Ãº¯Êý·µ»Ø0£¬²¢µÝÔö*claimedµÄÖµ¡£


6.7.2.38 mpo_internalize_pipe_label

int mpo_internalize_pipe_label(struct label *label, char *element_name, char *element_data, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ìî³äµÄ±ê¼Ç  
element_name ÐèÒªÄÚ²¿±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
element_data ÐèÒª±»×ª»»µÄÎı¾Êý¾Ý  
claimed Èç¹ûÊý¾Ý±»Õýȷת»»£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾ÝÒ»¸öÎı¾ÐÎʽµÄÍⲿ±íʾ±ê¼ÇÊý¾Ý£¬´´½¨Ò»¸öÄÚ²¿ÐÎʽµÄ±ê¼Ç½á¹¹¡£ ĿǰµÄMAC·½°¸½«ÒÀ´Îµ÷ÓÃËùÓвßÂÔµÄÏà¹ØÈë¿Úº¯Êý£¬À´ÏìÓ¦±ê¼ÇµÄÄÚ²¿×ª»»ÇëÇó£¬ Òò´Ë£¬ÊµÏÖ´úÂë±ØÐëÊ×ÏÈͨ¹ý±È½Ïelement_nameÖеÄÄÚÈݺÍ×Ô¼ºµÄ²ßÂÔÃû×Ö£¬ À´È·¶¨ÊÇ·ñÐèҪת»»element_dataÖдæ·ÅµÄÊý¾Ý¡£ ÀàËÆµÄ£¬Èç¹ûÃû×Ö²»Æ¥Åä»òÕßÊý¾Ýת»»²Ù×÷³É¹¦£¬¸Ãº¯Êý·µ»Ø0£¬²¢µÝÔö*claimedµÄÖµ¡£


6.7.2.39 mpo_internalize_socket_label

int mpo_internalize_socket_label(struct label *label, char *element_name, char *element_data, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ìî³äµÄ±ê¼Ç  
element_name ÐèÒªÄÚ²¿±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
element_data ÐèÒª±»×ª»»µÄÎı¾Êý¾Ý  
claimed Èç¹ûÊý¾Ý±»Õýȷת»»£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾ÝÒ»¸öÎı¾ÐÎʽµÄÍⲿ±íʾ±ê¼ÇÊý¾Ý£¬´´½¨Ò»¸öÄÚ²¿ÐÎʽµÄ±ê¼Ç½á¹¹¡£ ĿǰµÄMAC·½°¸½«ÒÀ´Îµ÷ÓÃËùÓвßÂÔµÄÏà¹ØÈë¿Úº¯Êý£¬À´ÏìÓ¦±ê¼ÇµÄÄÚ²¿×ª»»ÇëÇó£¬ Òò´Ë£¬ÊµÏÖ´úÂë±ØÐëÊ×ÏÈͨ¹ý±È½Ïelement_nameÖеÄÄÚÈݺÍ×Ô¼ºµÄ²ßÂÔÃû×Ö£¬ À´È·¶¨ÊÇ·ñÐèҪת»»element_dataÖдæ·ÅµÄÊý¾Ý¡£ ÀàËÆµÄ£¬Èç¹ûÃû×Ö²»Æ¥Åä»òÕßÊý¾Ýת»»²Ù×÷³É¹¦£¬¸Ãº¯Êý·µ»Ø0£¬²¢µÝÔö*claimedµÄÖµ¡£


6.7.2.40 mpo_internalize_vnode_label

int mpo_internalize_vnode_label(struct label *label, char *element_name, char *element_data, int *claimed);

²ÎÊý ˵Ã÷ Ëø¶¨
label ½«±»Ìî³äµÄ±ê¼Ç  
element_name ÐèÒªÄÚ²¿±íʾ±ê¼ÇµÄ²ßÂÔµÄÃû×Ö  
element_data ÐèÒª±»×ª»»µÄÎı¾Êý¾Ý  
claimed Èç¹ûÊý¾Ý±»Õýȷת»»£¬ÔòÆäÊýÖµµÝÔö  

¡¡¡¡¸ù¾ÝÒ»¸öÎı¾ÐÎʽµÄÍⲿ±íʾ±ê¼ÇÊý¾Ý£¬´´½¨Ò»¸öÄÚ²¿ÐÎʽµÄ±ê¼Ç½á¹¹¡£ ĿǰµÄMAC·½°¸½«ÒÀ´Îµ÷ÓÃËùÓвßÂÔµÄÏà¹ØÈë¿Úº¯Êý£¬À´ÏìÓ¦±ê¼ÇµÄÄÚ²¿×ª»»ÇëÇó£¬ Òò´Ë£¬ÊµÏÖ´úÂë±ØÐëÊ×ÏÈͨ¹ý±È½Ïelement_nameÖеÄÄÚÈݺÍ×Ô¼ºµÄ²ßÂÔÃû×Ö£¬ À´È·¶¨ÊÇ·ñÐèҪת»»element_dataÖдæ·ÅµÄÊý¾Ý¡£ ÀàËÆµÄ£¬Èç¹ûÃû×Ö²»Æ¥Åä»òÕßÊý¾Ýת»»²Ù×÷³É¹¦£¬¸Ãº¯Êý·µ»Ø0£¬²¢µÝÔö*claimedµÄÖµ¡£


6.7.3 ±ê¼Çʼþ

¡¡¡¡²ßÂÔÄ£¿éʹÓÃMAC ¿ò¼ÜÌṩµÄ¡°±ê¼Çʼþ¡±ÀàÈë¿Úº¯Êý£¬¶ÔÄں˶ÔÏóµÄ±ê¼Ç½øÐвÙ×÷¡£²ßÂÔÄ£¿é½«¸ÐÐËȤµÄ±»±ê¼ÇÄں˶ÔÏóµÄÏà¹ØÉúÃüÖÜÆÚʼþ ×¢²áÔÚÇ¡µ±µÄÈë¿ÚµãÉÏ¡£¶ÔÏóµÄ³õʼ»¯¡¢´´½¨ºÍÏú»Ùʼþ¾ùÌṩÁ˹³×ӵ㡣ÔÚijЩ¶ÔÏóÉÏ»¹¿ÉÒÔʵÏÖÖØÐ±ê¼Ç£¬¼´£¬ÔÊÐíÓû§½ø³Ì¸Ä±ä¶ÔÏóÉϵıê¼ÇÖµ¡£ ¶ÔijЩ¶ÔÏó¿ÉÒÔʵÏÖÆäÌØ¶¨µÄ¶ÔÏóʼþ£¬±ÈÈçÓë IP ÖØ×éÏà¹ØµÄ±ê¼Çʼþ¡£Ò»¸öµäÐ͵ı»±ê¼Ç¶ÔÏóÔÚÆäÉúÃüÖÜÆÚÖн«ÓµÓÐÏÂÁÐÈë¿Úº¯Êý£º

±ê¼Ç³õʼ»¯                     o
£¨¶ÔÏóÏà¹ØµÄµÈ´ý£©              \
±ê¼Ç´´½¨                         o
                                  \
ÖØÐ±ê¼Çʼþ£¬                     o--<--.
¸÷ÖÖ¶ÔÏóÏà¹ØµÄ£¬                   |     |
·ÃÎÊ¿ØÖÆÊ¼þ                       ~-->--o
                                          \
±ê¼ÇÏú»Ù                                   o

¡¡¡¡Ê¹Óñê¼Ç³õʼ»¯Èë¿Úº¯Êý£¬²ßÂÔ¿ÉÒÔÒÔÒ»ÖÖͳһµÄ¡¢Óë¶ÔÏóʹÓû·¾³Î޹صķ½Ê½ÉèÖñê¼ÇµÄ³õʼֵ¡£ ·ÖÅä¸øÒ»¸ö²ßÂÔµÄȱʡ slot ֵΪ0£¬ÕâÑù²»Ê¹Óñê¼ÇµÄ²ßÂÔ¿ÉÄܲ¢²»ÐèÒªÖ´ÐÐרÃŵijõʼ»¯²Ù×÷¡£

¡¡¡¡±ê¼ÇµÄ´´½¨Ê¼þ·¢ÉúÔÚ½«Ò»¸öÄÚºËÊý¾Ý½á¹¹Í¬Ò»¸öÕæÊµµÄÄں˶ÔÏóÏà¹ØÁª£¨Äں˶ÔÏóʵÀý»¯£©µÄʱ¿Ì¡£ ÀýÈ磬ÔÚÕæÕý±»Ê¹ÓÃ֮ǰ£¬ÔÚÒ»¸ö»º³å³ØÄÚÒÑ·ÖÅäµÄ mbuf Êý¾Ý½á¹¹£¬½«±£³ÖΪ¡°Î´Ê¹Óá±×´Ì¬¡£ Òò´Ë£¬mbuf µÄ·ÖÅä²Ù×÷½«µ¼ÖÂÕë¶Ô¸Ã mbuf µÄ±ê¼Ç³õʼ»¯²Ù×÷£¬¶ø mbuf µÄ´´½¨²Ù×÷Ôò±»ÍƳٵ½¸Ã mbuf ÕæÕýÓëÒ»¸öÊý¾Ý±¨Ïà¹ØÁªµÄʱ¿Ì¡£ ͨ³££¬µ÷ÓÃÕß½«»áÌṩ´´½¨Ê¼þµÄÉÏÏÂÎÄ£¬°üÀ¨´´½¨»·¾³¡¢´´½¨¹ý³ÌÖÐÉæ¼°µÄÆäËû¶ÔÏóµÄ±ê¼ÇµÈ¡£ÀýÈ磬µ±Ò»¸öÌ×½Ó×Ö´´½¨Ò»¸ö mbuf ʱ£¬ ³ýÁËд´½¨µÄ mbuf ¼°Æä±ê¼ÇÖ®Í⣬×÷Ϊ´´½¨ÕßµÄÌ×½Ó×ÖÓëÆä±ê¼ÇÒ²±»Ìá½»¸ø²ßÂÔ¼ì²é¡£ ²»ÌᳫÔÚ´´½¨¶ÔÏóʱ¾ÍΪÆä·ÖÅäÄÚ´æµÄÔ­ÒòÓÐÁ½¸ö£º´´½¨²Ù×÷¿ÉÄÜ·¢ÉúÔÚ¶ÔÐÔÄÜÓÐÑϸñÒªÇóµÄÄں˽ӿÚÉÏ£» ¶øÇÒ£¬ÒòΪ´´½¨µ÷Óò»ÔÊÐíʧ°Ü£¬ËùÒÔÎÞ·¨±¨¸æÄÚ´æ·ÖÅäʧ°Ü¡£

¡¡¡¡¶ÔÏóÌØÓеÄʼþÒ»°ã²»»áÒý·¢ÆäËûµÄ±ê¼Çʼþ£¬µ«ÊÇÔÚ¶ÔÏóÉÏÏÂÎÄ·¢Éú¸Ä±äʱ£¬²ßÂÔʹÓÃËüÃÇ¿ÉÒÔ¶ÔÏà¹Ø±ê¼Ç½øÐÐÐ޸Ļò¸üвÙ×÷¡£ ÀýÈ磬ÔÚMAC_UPDATE_IPQ Èë¿Úº¯ÊýÖ®ÄÚ£¬Ä³¸ö IP ·ÖÆ¬ÖØ×é¶ÓÁеıê¼Ç¿ÉÄÜ»áÒòΪ¶ÓÁÐÖнÓÊÕÁËÐ嵀 mbuf ¶ø±»¸üС£

¡¡¡¡·ÃÎÊ¿ØÖÆÊ¼þ½«ÔÚºóÐøÕ½ÚÖÐÏêϸÌÖÂÛ¡£

¡¡¡¡²ßÂÔͨ¹ýÖ´Ðбê¼ÇÏú»Ù²Ù×÷£¬ÊÍ·ÅΪÆä·ÖÅäµÄ´æ´¢¿Õ¼ä»òά»¤µÄ״̬£¬Ö®ºóÄں˲ſÉÒÔÖØÓûòÕßÊͷŶÔÏóµÄÄÚºËÊý¾Ý½á¹¹¡£

¡¡¡¡³ýÁËÓëÌØ¶¨Äں˶ÔÏó°ó¶¨µÄÆÕͨ±ê¼ÇÖ®Í⣬»¹ÓÐÒ»ÖÖ¶îÍâµÄ±ê¼ÇÀàÐÍ£ºÁÙʱ±ê¼Ç¡£ÕâЩ±ê¼ÇÓÃÓÚ´æ·ÅÓÉÓû§½ø³ÌÌá½»µÄ¸üÐÂÐÅÏ¢¡£ ËüÃǵijõʼ»¯ºÍÏú»Ù²Ù×÷ÓëÆäËû±ê¼ÇÒ»Ñù£¬Ö»ÊÇ´´½¨Ê¼þ£¬MAC_INTERNALIZE£¬ÂÔÓв»Í¬£º ¸Ãº¯Êý½ÓÊÜÓû§Ìá½»µÄ±ê¼Ç£¬¸ºÔð½«Æäת»¯ÎªÄں˱íʾÐÎʽ¡£


6.7.3.1 Îļþϵͳ¶ÔÏó±ê¼Çʼþ²Ù×÷

6.7.3.1.1 mpo_associate_vnode_devfs

void mpo_associate_vnode_devfs(struct mount *mp, struct label *fslabel, struct devfs_dirent *de, struct label *delabel, struct vnode *vp, struct label *vlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
mp Devfs ¹ÒÔØµã  
fslabel Devfs Îļþϵͳ±ê¼Ç (mp->mnt_fslabel)  
de Devfs Ŀ¼Ïî  
delabel Óë de Ïà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
vp Óë de Ïà¹ØÁªµÄ vnode  
vlabel Óë vp Ïà¹ØÁªµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ý²ÎÊý de ´«ÈëµÄ devfs Ŀ¼Ïî¼°Æä±ê¼ÇÐÅÏ¢£¬ÎªÒ»¸öнü´´½¨µÄ devfs vnode Ìî³ä±ê¼Ç£¨vlabel£©¡£


6.7.3.1.2 mpo_associate_vnode_extattr

int mpo_associate_vnode_extattr(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
mp Îļþϵͳ¹ÒÔØµã  
fslabel Îļþϵͳ±ê¼Ç  
vp ½«±»±ê¼ÇµÄ vnode  
vlabel Óë vp Ïà¹ØÁªµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡´ÓÎļþϵͳÀ©Õ¹ÊôÐÔÖжÁÈ¡ vp µÄ±ê¼Ç¡£³É¹¦£¬·µ»Ø 0¡£ ²»³É¹¦£¬ÔòÔÚ errno Ö¸¶¨µÄÏàÓ¦µÄ´íÎó±àÂë¡£ Èç¹ûÎļþϵͳ²»Ö§³ÖÀ©Õ¹ÊôÐԵĶÁÈ¡²Ù×÷£¬Ôò¿ÉÒÔ¿¼Âǽ« fslabel ¿½±´ÖÁ vlabel¡£


6.7.3.1.3 mpo_associate_vnode_singlelabel

void mpo_associate_vnode_singlelabel(struct mount *mp, struct label *fslabel, struct vnode *vp, struct label *vlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
mp Îļþϵͳ¹ÒÔØµã  
fslabel Îļþϵͳ±ê¼Ç  
vp ½«±»±ê¼ÇµÄ vnode  
vlabel Óë vp Ïà¹ØÁªµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡ÔڷǶàÖØ±ê¼ÇÎļþϵͳÉÏ£¬Ê¹ÓøÃÈë¿Úº¯Êý£¬¸ù¾ÝÎļþϵͳ±ê¼Ç£¬fslabel£¬ Ϊ vp ÉèÖòßÂÔ±ê¼Ç¡£


6.7.3.1.4 mpo_create_devfs_device

void mpo_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent, struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
dev devfs_dirent ¶ÔÓ¦µÄÉ豸  
devfs_dirent ½«±»±ê¼ÇµÄ Devfs Ŀ¼Ïî  
label ½«±»ÌîдµÄ devfs_dirent ±ê¼Ç  

¡¡¡¡Îª´«ÈëÉ豸н¨µÄ devfs_dirent Ìîд±ê¼Ç¡£¸Ãº¯Êý½«ÔÚÉ豸Îļþϵͳ¼ÓÔØ¡¢Öع¹»òÌí¼ÓÐÂÉ豸ʱ±»µ÷Óá£


6.7.3.1.5 mpo_create_devfs_directory

void mpo_create_devfs_directory(char *dirname, int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
dirname н¨Ä¿Â¼µÄÃû×Ö  
namelen ×Ö·û´® dirname µÄ³¤¶È  
devfs_dirent н¨Ä¿Â¼ÔÚ Devfs ÖжÔÓ¦µÄĿ¼Ïî  

¡¡¡¡Îª´«ÈëĿ¼²ÎÊýµÄн¨ devfs_dirent Ìîд±ê¼Ç¡£¸Ãº¯Êý½«ÔÚ¼ÓÔØ¡¢Öع¹É豸Îļþϵͳ£¬»òÕßÌí¼ÓÒ»¸öÐèÒªÖ¸¶¨Ä¿Â¼½á¹¹µÄÐÂÉ豸ʱ±»µ÷Óá£


6.7.3.1.6 mpo_create_devfs_symlink

void mpo_create_devfs_symlink(struct ucred *cred, struct mount *mp, struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de, struct label *delabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
mp devfs ¹ÒÔØµã  
dd Á´½ÓÄ¿±ê  
ddlabel Óë dd Ïà¹ØÁªµÄ±ê¼Ç  
de ·ûºÅÁ´½ÓÏî  
delabel Óë de Ïà¹ØÁªµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡ÎªÐ½ü´´½¨µÄ devfs(5) ·ûºÅÁ´½ÓÏîÌîд±ê¼Ç£¨delabel£©¡£


6.7.3.1.7 mpo_create_vnode_extattr

int mpo_create_vnode_extattr(struct ucred *cred, struct mount *mp, struct label *fslabel, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *vlabel, struct componentname *cnp);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
mount Îļþϵͳ¹ÒÔØµã  
label Îļþϵͳ±ê¼Ç  
dvp ¸¸Ä¿Â¼ vnode  
dlabel Óë dvp Ïà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
vp д´½¨µÄ vnode  
vlabel Óë vp Ïà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
cnp vpÖеÄ×ÓÓòÃû×Ö  

¡¡¡¡½« vp µÄ±ê¼ÇдÈëÎļþÀ©Õ¹ÊôÐÔ¡£³É¹¦£¬½«±ê¼ÇÌîÈë vlabel£¬ ²¢·µ»Ø 0¡£·ñÔò£¬·µ»Ø¶ÔÓ¦µÄ´íÎó±àÂë¡£


6.7.3.1.8 mpo_create_mount

void mpo_create_mount(struct ucred *cred, struct mount *mp, struct label *mnt, struct label *fslabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
mp ¿ÍÌ壻½«±»¹ÒÔØµÄÎļþϵͳ  
mntlabel ½«±»ÌîдµÄ mp µÄ²ßÂÔ±ê¼Ç  
fslabel ½«±»¹ÒÔØµ½ mp µÄÎļþϵͳµÄ²ßÂÔ±ê¼Ç¡£  

¡¡¡¡Îª´«ÈëµÄÖ÷ÌåÐÅÈÎ×´Ëù´´½¨µÄ¹ÒÔØµãÌîд±ê¼Ç¡£¸Ãº¯Êý½«ÔÚÎļþϵͳ¹ÒÔØÊ±±»µ÷Óá£


6.7.3.1.9 mpo_create_root_mount

void mpo_create_root_mount(struct ucred *cred, struct mount *mp, struct label *mntlabel, struct label *fslabel);

²ÎÊý ˵Ã÷ Ëø¶¨
¼û µÚ 6.7.3.1.8 ½Ú.

¡¡¡¡Îª´«ÈëµÄÖ÷ÌåÐÅÈÎ×´Ëù´´½¨µÄ¹ÒÔØµãÌîд±ê¼Ç¡£¸Ãº¯Êý½«ÔÚ¹ÒÔØ¸ùÎļþϵͳʱ£¬mpo_create_mount; Ö®ºó±»µ÷Óá£


6.7.3.1.10 mpo_relabel_vnode

void mpo_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ½«±»ÖØÐ±ê¼ÇµÄ vnode  
vnodelabel vp ÏÖÓеIJßÂÔ±ê¼Ç  
newlabel ½«È¡´úvnodelabelµÄУ¨¿ÉÄÜÖ»ÊDz¿·Ö£©±ê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄбê¼ÇºÍÖ÷ÌåÐÅÈÎ×´£¬¸üвÎÊý vnode µÄ±ê¼Ç¡£


6.7.3.1.11 mpo_setlabel_vnode_extattr

int mpo_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp, struct label *vlabel, struct label *intlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp д³ö±ê¼ÇËù¶ÔÓ¦µÄ vnode  
vlabel vpµÄ²ßÂÔ±ê¼Ç  
intlabel ½«±»Ð´Èë´ÅÅ̵ıê¼Ç  

¡¡¡¡½«²ÎÊý intlabel ¸ø³öµÄ±ê¼ÇÐÅϢдÈëÖ¸¶¨ vnode µÄÀ©Õ¹ÊôÐÔ¡£ ¸Ãº¯Êý±» vop_stdcreatevnode_ea Ëùµ÷Óá£


6.7.3.1.12 mpo_update_devfsdirent

void mpo_update_devfsdirent(struct devfs_dirent *devfs_dirent, struct label *direntlabel, struct vnode *vp, struct label *vnodelabel);

²ÎÊý ˵Ã÷ Ëø¶¨
devfs_dirent ¿ÍÌ壻devfs Ŀ¼Ïî  
direntlabel ½«±»¸üеÄdevfs_direntµÄ²ßÂÔ±ê¼Ç  
vp ¸¸ vnode ÒÑËø¶¨
vnodelabel vpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾ÝËù´«ÈëµÄ devfs vnode ±ê¼Ç£¬¶Ô devfs_dirent µÄ±ê¼Ç½øÐиüС£ ÖØÐ±ê¼ÇÒ»¸ö devfs vnode µÄ²Ù×÷³É¹¦Ö®ºó£¬½«µ÷Óøú¯ÊýÀ´È·Èϱê¼ÇµÄ¸Ä±ä£¬Èç´Ë£¬¼´Ê¹ÏàÓ¦µÄ vnode Êý¾Ý½á¹¹±»Äں˻ØÊÕÖØÓ㬠Ҳ²»»á¶ªÊ§±ê¼ÇµÄÐÂ״̬¡£ÁíÍ⣬ÔÚ devfs ÖÐн¨Ò»¸ö·ûºÅÁ´½Óʱ£¬½ô½Ó×Åmac_vnode_create_from_vnode£¬ Ò²½«µ÷Óøú¯Êý£¬¶Ô vnode ±ê¼Ç½øÐгõʼ»¯²Ù×÷¡£


6.7.3.2 IPC ¶ÔÏó±ê¼Çʼþ²Ù×÷

6.7.3.2.1 mpo_create_mbuf_from_socket

void mpo_create_mbuf_from_socket(struct socket *so, struct label *socketlabel, struct mbuf *m, struct label *mbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
socket Ì×½Ó×Ö Ì×½Ó×ÖËø¶¨ WIP
socketlabel socket µÄ²ßÂÔ±ê¼Ç  
m ¿ÍÌ壻mbuf  
mbuflabel ½«±»ÌîдµÄ m µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄÌ×½Ó×Ö±ê¼ÇΪд´½¨µÄmbufÍ·²¿ÉèÖñê¼Ç¡£ ÿµ±Ì×½Ó×Ö²úÉúÒ»¸öеÄÊý¾Ý±¨»òÕßÏûÏ¢£¬²¢½«Æä´æ´¢ÔÚ²ÎÊý mbuf ÖÐʱ£¬½«µ÷Óøú¯Êý¡£


6.7.3.2.2 mpo_create_pipe

void mpo_create_pipe(struct ucred *cred, struct pipe *pipe, struct label *pipelabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
pipe ¹ÜµÀ  
pipelabel pipe µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄÖ÷ÌåÐÅÈÎ×´²ÎÊý£¬ÉèÖÃн¨¹ÜµÀµÄ±ê¼Ç¡£Ã¿µ±Ò»¸öйܵÀ±»´´½¨£¬¸Ãº¯Êý½«±»µ÷Óá£


6.7.3.2.3 mpo_create_socket

void mpo_create_socket(struct ucred *cred, struct socket *so, struct label *socketlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
so ¿ÍÌ壻½«±»±ê¼ÇµÄÌ×½Ó×Ö  
socketlabel ½«±»ÌîдµÄ so µÄ±ê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄÖ÷ÌåÐÅÈÎ×´²ÎÊý£¬ÉèÖÃн¨Ì×½Ó×ֵıê¼Ç¡£Ã¿µ±Ð½¨Ò»¸öÌ×½Ó×Ö£¬¸Ãº¯Êý½«±»µ÷Óá£


6.7.3.2.4 mpo_create_socket_from_socket

void mpo_create_socket_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
oldsocket ¼àÌýÌ×½Ó×Ö  
oldsocketlabel oldsocket µÄ²ßÂÔ±ê¼Ç  
newsocket н¨Ì×½Ó×Ö  
newsocketlabel newsocket µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ý listen(2) Ì×½Ó×Ö oldsocket£¬ Ϊн¨ accept(2) µÄÌ×½Ó×Ö newsocket£¬ÉèÖñê¼Ç¡£


6.7.3.2.5 mpo_relabel_pipe

void mpo_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *oldlabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
pipe ¹ÜµÀ  
oldlabel pipe µÄµ±Ç°²ßÂÔ±ê¼Ç  
newlabel ½«Îªpipe ÉèÖõÄеIJßÂÔ±ê¼Ç  

¡¡¡¡ÎªpipeÉèÖÃбê¼Çnewlabel¡£


6.7.3.2.6 mpo_relabel_socket

void mpo_relabel_socket(struct ucred *cred, struct socket *so, struct label *oldlabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
so ¿ÍÌ壻Ì×½Ó×Ö  
oldlabel so µÄµ±Ç°±ê¼Ç  
newlabel ½«Îªsocket ÉèÖõÄбê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄ±ê¼Ç²ÎÊý£¬¶ÔÌ×½Ó×ֵĵ±Ç°±ê¼Ç½øÐиüС£


6.7.3.2.7 mpo_set_socket_peer_from_mbuf

void mpo_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel, struct label *oldlabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
mbuf ´ÓÌ×½Ó×Ö½ÓÊÕµ½µÄµÚÒ»¸öÊý¾Ý±¨  
mbuflabel mbuf µÄ±ê¼Ç  
oldlabel Ì×½Ó×ֵĵ±Ç°±ê¼Ç  
newlabel ½«ÎªÌ×½Ó×ÖÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄ mbuf ±ê¼Ç£¬ÉèÖÃij¸ö stream Ì×½Ó×ֵĶԵȱêÖ¾¡£ ³ýUnixÓòµÄÌ×½Ó×ÖÖ®Í⣬ÿµ±Ò»¸ö stream Ì×½Ó×Ö½ÓÊÕµ½µÚÒ»¸öÊý¾Ý±¨Ê±£¬¸Ãº¯Êý½«±»µ÷Óá£


6.7.3.2.8 mpo_set_socket_peer_from_socket

void mpo_set_socket_peer_from_socket(struct socket *oldsocket, struct label *oldsocketlabel, struct socket *newsocket, struct label *newsocketpeerlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
oldsocket ±¾µØÌ×½Ó×Ö  
oldsocketlabel oldsocket µÄ²ßÂÔ±ê¼Ç  
newsocket ¶ÔµÈÌ×½Ó×Ö  
newsocketpeerlabel ½«ÎªnewsocketÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄÔ¶³ÌÌ×½Ó×ֶ˵㣬Ϊһ¸ö stream UNIX ÓëÌ×½Ó×ÖÉèÖöԵȱê¼Ç¡£ ÿµ±ÏàÓ¦µÄÌ×½Ó×Ö¶ÔÖ®¼ä½øÐÐÁ¬½Óʱ£¬¸Ãº¯Êý½«ÔÚÁ½¶Ë·Ö±ð±»µ÷Óá£


6.7.3.3 Network Object Labeling Event Operations

6.7.3.3.1 mpo_create_bpfdesc

void mpo_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d, struct label *bpflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
bpf_d ¿ÍÌ壻bpf ÃèÊö×Ó  
bpf ½«Îªbpf_dÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄÖ÷ÌåÐÅÈÎ×´²ÎÊý£¬ÎªÐ½¨µÄ BPF ÃèÊö×ÓÉèÖñê¼Ç¡£ µ±½ø³Ì´ò¿ª BPF É豸½Úµãʱ£¬¸Ãº¯Êý½«±»µ÷Óá£


6.7.3.3.2 mpo_create_ifnet

void mpo_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
ifnet ÍøÂç½Ó¿Ú  
ifnetlabel ½«ÎªifnetÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡ÎªÐ½¨µÄÍøÂç½Ó¿ÚÉèÖñê¼Ç¡£¸Ãº¯ÊýÔÚÒÔÏÂÇé¿öϱ»µ÷Ó㺠µ±Ò»¸öеÄÎïÀí½Ó¿Ú±äΪ¿ÉÓÃʱ£¬»òÕßµ±Ò»¸öα½Ó¿ÚÔÚÒýµ¼Ê±»òÓÉÓÚij¸öÓû§²Ù×÷¶øÊµÀý»¯Ê±¡£


6.7.3.3.3 mpo_create_ipq

void mpo_create_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
fragment µÚÒ»¸ö±»½ÓÊÕµÄ IP ·ÖƬ  
fragmentlabel fragment µÄ²ßÂÔ±ê¼Ç  
ipq ½«±»±ê¼ÇµÄ IP ÖØ×é¶ÓÁÐ  
ipqlabel ½«ÎªipqÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾ÝµÚÒ»¸ö½ÓÊÕµ½µÄ·ÖƬµÄ mbuf Í·²¿ÐÅÏ¢£¬ÎªÐ½¨µÄ IP ·ÖÆ¬ÖØ×é¶ÓÁÐÉèÖñê¼Ç¡£


6.7.3.3.4 mpo_create_datagram_from_ipq

void mpo_create_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel, struct mbuf *datagram, struct label *datagramlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
ipq IP ÖØ×é¶ÓÁÐ  
ipqlabel ipq µÄ²ßÂÔ±ê¼Ç  
datagram ½«±»±ê¼ÇµÄÊý¾Ý±¨  
datagramlabel ½«ÎªdatagramlabelÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ý IP ·ÖÆ¬ÖØ×é¶ÓÁУ¬Îª¸Õ¸ÕÖØ×éÍê±ÏµÄ IP Êý¾Ý±¨ÉèÖñê¼Ç¡£


6.7.3.3.5 mpo_create_fragment

void mpo_create_fragment(struct mbuf *datagram, struct label *datagramlabel, struct mbuf *fragment, struct label *fragmentlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
datagram Êý¾Ý±¨  
datagramlabel datagram µÄ²ßÂÔ±ê¼Ç  
fragment ½«±»±ê¼ÇµÄ·ÖƬ  
fragmentlabel ½«ÎªdatagramÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾ÝÊý¾Ý±¨Ëù¶ÔÓ¦µÄ mbuf Í·²¿ÐÅÏ¢£¬ÎªÆäн¨µÄ·ÖƬµÄ mbuf Í·²¿ÉèÖñê¼Ç¡£


6.7.3.3.6 mpo_create_mbuf_from_mbuf

void mpo_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct mbuf *newmbuf, struct label *newmbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
oldmbuf ÒÑÓеģ¨Ô´£©mbuf  
oldmbuflabel oldmbuf µÄ²ßÂÔ±ê¼Ç  
newmbuf ½«±»±ê¼ÇµÄн¨ mbuf  
newmbuflabel ½«ÎªnewmbufÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾Ýij¸öÏÖÓÐÊý¾Ý±¨µÄ mbuf Í·²¿ÐÅÏ¢£¬ÎªÐ½¨Êý¾Ý±¨µÄ mbuf Í·²¿ÉèÖñê¼Ç¡£ÔÚÐí¶àÌõ¼þϽ«»áµ÷Óøú¯Êý£¬ ±ÈÈ磬ÓÉÓÚ¶ÔÆëÒªÇó¶øÖØÐ·ÖÅäij¸ö mbuf ʱ¡£


6.7.3.3.7 mpo_create_mbuf_linklayer

void mpo_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
ifnet ÍøÂç½Ó¿Ú  
ifnetlabel ifnet µÄ²ßÂÔ±ê¼Ç  
mbuf н¨Êý¾Ý±¨µÄ mbuf Í·²¿  
mbuflabel ½«ÎªmbufÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡ÎªÔÚ¸ø¶¨½Ó¿ÚÉÏÓÉÓÚij¸öÁ´Â·²ãÏìÓ¦¶øÐ½¨µÄÊý¾Ý±¨µÄmbufÍ·²¿ÉèÖñê¼Ç¡£ ¸Ãº¯Êý½«ÔÚÈô¸ÉÌõ¼þϱ»µ÷Ó㬱ÈÈçµ±IPv4ºÍIPv6ЭÒéÕ»ÔÚÏìÓ¦ARP»òÕßND6ʱ¡£


6.7.3.3.8 mpo_create_mbuf_from_bpfdesc

void mpo_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel, struct mbuf *mbuf, struct label *mbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
bpf_d BPF ÃèÊö×Ó  
bpflabel bpflabel µÄ²ßÂÔ±ê¼Ç  
mbuf ½«±»±ê¼ÇµÄн¨ mbuf  
mbuflabel ½«ÎªmbufÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡ÎªÊ¹ÓòÎÊý BPF ÃèÊö×Ó´´½¨µÄÐÂÊý¾Ý±¨µÄ mbuf Í·²¿ÉèÖñê¼Ç¡£ µ±¶Ô²ÎÊý BPF ÃèÊö×ÓËù¹ØÁªµÄ BPF É豸½øÐÐд²Ù×÷ʱ£¬¸Ãº¯Êý½«±»µ÷Óá£


6.7.3.3.9 mpo_create_mbuf_from_ifnet

void mpo_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
ifnet ÍøÂç½Ó¿Ú  
ifnetlabel ifnetlabel µÄ²ßÂÔ±ê¼Ç  
mbuf н¨Êý¾Ý±¨µÄ mbuf Í·²¿  
mbuflabel ½«ÎªmbufÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡Îª´ÓÍøÂç½Ó¿Ú²ÎÊý´´½¨µÄÊý¾Ý±¨µÄ mbuf Í·²¿ÉèÖñê¼Ç¡£


6.7.3.3.10 mpo_create_mbuf_multicast_encap

void mpo_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *newmbuf, struct label *newmbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
oldmbuf ÏÖÓÐÊý¾Ý±¨µÄ mbuf Í·²¿  
oldmbuflabel oldmbuf µÄ²ßÂÔ±ê¼Ç  
ifnet ÍøÂç½Ó¿Ú  
ifnetlabel ifnet µÄ²ßÂÔ±ê¼Ç  
newmbuf ½«±»±ê¼ÇµÄн¨Êý¾Ý±¨ mbuf Í·²¿  
newmbuflabel ½«ÎªnewmbufÌîдµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡µ±´«ÈëµÄÒÑÓÐÊý¾Ý±¨±»¸ø¶¨¶à²¥·â×°½Ó¿Ú£¨multicast encapsulation interface£©´¦Àíʱ±»µ÷Ó㬠Ϊд´½¨µÄÊý¾Ý±¨ËùÔÚ mbuf Í·²¿ÉèÖñê¼Ç¡£ ÿµ±Ê¹ÓøÃÐéÄâ½Ó¿Ú´«µÝÒ»¸ömbufʱ£¬½«µ÷Óøú¯Êý¡£


6.7.3.3.11 mpo_create_mbuf_netlayer

void mpo_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel, struct mbuf *newmbuf, struct label *newmbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
oldmbuf ½ÓÊÕµÄÊý¾Ý±¨  
oldmbuflabel oldmbuf µÄ²ßÂÔ±ê¼Ç  
newmbuf н¨Êý¾Ý±¨  
newmbuflabel newmbuf µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡ÎªÓÉ IP ¶ÑÕ»ÒòΪÏìÓ¦½ÓÊÕÊý¾Ý±¨£¨oldmbuf£©¶øÐ½¨µÄÊý¾Ý±¨ÉèÖÃÆä mbuf Í·²¿µÄ±ê¼Ç¡£ Ðí¶àÇé¿öÏÂÐèÒªµ÷Óøú¯Êý£¬±ÈÈ磬ÏìÓ¦ ICMP ÇëÇóÊý¾Ý±¨Ê±¡£


6.7.3.3.12 mpo_fragment_match

int mpo_fragment_match(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
fragment IP Êý¾Ý±¨·ÖƬ  
fragmentlabel fragment µÄ²ßÂÔ±ê¼Ç  
ipq IP ·ÖÆ¬ÖØ×é¶ÓÁÐ  
ipqlabel ipq µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾ÝËù´«ÈëµÄ IP ·ÖÆ¬ÖØ×é¶ÓÁУ¨ipq£©µÄ±ê¼Ç£¬ ¼ì²é°üº¬Ò»¸ö IP Êý¾Ý±¨£¨fragment£©µÄ mbuf µÄÍ·²¿ÊÇ·ñ·ûºÏÆäÒªÇó¡£ ·ûºÏ£¬Ôò·µ»Ø1¡£·ñÔò£¬·µ»Ø0¡£ ÿµ± IP ¶ÑÕ»³¢ÊÔ½«Ò»¸ö¸Õ¸Õ½ÓÊÕµ½µÄ·ÖƬ·ÅÈëij¸öÒÑÓÐµÄ·ÖÆ¬ÖØ×é¶ÓÁÐÖÐʱ£¬½«µ÷Óøú¯Êý½øÐа²È«¼ì²é£» Èç¹ûʧ°Ü£¬½«Îª·ÖÆ¬ÖØÐÂʵÀý»¯Ò»¸öÐ嵀ᅮ¬ÖØ×é¶ÓÁС£ ²ßÂÔ¿ÉÒÔÀûÓøÃÈë¿Úº¯Êý£¬¸ù¾Ý±ê¼Ç»òÕ߯äËûÐÅÏ¢×èÖ¹²»ÆÚÍûµÄ IP ·ÖÆ¬ÖØ×é¡£


6.7.3.3.13 mpo_relabel_ifnet

void mpo_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
ifnet ¿ÍÌå£»ÍøÂç½Ó¿Ú  
ifnetlabel ifnet µÄ²ßÂÔ±ê¼Ç  
newlabel ½«ÎªifnetÉèÖõÄбê¼Ç  

¡¡¡¡¸ù¾ÝËù´«ÈëµÄбê¼Ç£¬newlabel£¬ÒÔ¼°Ö÷ÌåÐÅÈÎ×´£¬ cred£¬¶ÔÍøÂç½Ó¿ÚµÄ±ê¼Ç½øÐиüС£


6.7.3.3.14 mpo_update_ipq

void mpo_update_ipq(struct mbuf *fragment, struct label *fragmentlabel, struct ipq *ipq, struct label *ipqlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
mbuf IP ·ÖƬ  
mbuflabel mbuf µÄ²ßÂÔ±ê¼Ç  
ipq IP ·ÖÆ¬ÖØ×é¶ÓÁÐ  
ipqlabel ½«±»¸üеÄipqµÄµ±Ç°²ßÂÔ±ê¼Ç  

¡¡¡¡¸ù¾ÝËù´«ÈëµÄ IP ·ÖƬ mbuf Í·²¿£¨mbuf£©Îª½ÓÊÕ ËüµÄ IP ·ÖÆ¬ÖØ×é¶ÓÁУ¨ipq£©µÄ±ê¼Ç½øÐиüС£


6.7.3.4 ½ø³Ì±ê¼Çʼþ²Ù×÷

6.7.3.4.1 mpo_create_cred

void mpo_create_cred(struct ucred *parent_cred, struct ucred *child_cred);

²ÎÊý ˵Ã÷ Ëø¶¨
parent_cred ¸¸Ö÷ÌåÐÅÈÎ×´  
child_cred ×ÓÖ÷ÌåÐÅÈÎ×´  

¡¡¡¡¸ù¾ÝËù´«ÈëµÄÖ÷ÌåÐÅÈÎ×´£¬ÎªÐ½¨µÄÖ÷ÌåÐÅÈÎ×´ÉèÖñê¼Ç¡£ ÿµ±ÎªÒ»¸öн¨µÄ struct ucredµ÷Óà crcopy(9) ʱ£¬½«µ÷Óô˺¯Êý¡£ ¸Ãº¯Êý²»Ó¦Óë½ø³Ì¸´ÖÆ£¨forking£©»òÕß´´½¨Ê¼þ»ìΪһ̸¡£


6.7.3.4.2 mpo_execve_transition

void mpo_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp, struct label *vnodelabel);

²ÎÊý ˵Ã÷ Ëø¶¨
old ÒÑÓеÄÖ÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
new ½«±»±ê¼ÇµÄÐÂÖ÷ÌåÐÅÈÎ×´  
vp ½«±»Ö´ÐеÄÎļþ Òѱ»Ëø¶¨
vnodelabel vp µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡Ò»¸öÓµÓÐÐÅÈÎ×´oldµÄÖ÷ÌåÓÉÓÚÖ´ÐÐ(vpÎļþ¶øµ¼Ö±ê¼Çת»»Ê±£¬ ¸Ãº¯Êý¸ù¾Ývnode±ê¼ÇΪ¸ÃÖ÷ÌåÖØÐ±ê¼ÇΪnew¡£ ÿµ±Ò»¸ö½ø³ÌÇëÇóÖ´ÐÐvnodeÎļþ£¬¶øÍ¨¹ý Èë¿Úº¯Êýmpo_execve_will_transition Óгɹ¦·µ»ØµÄ²ßÂÔʱ£¬½«µ÷Óøú¯Êý¡£ ²ßÂÔÄ£¿é¿ÉÒÔͨ¹ý´«ÈëÁ½¸öÖ÷ÌåÐÅÈÎ×´ºÍ¼òµ¥µØµ÷Óà mpo_create_cred À´ÊµÏÖ¸ÃÈë¿Úº¯Êý£¬ so as not to implement a transitioning event. Ò»µ©²ßÂÔʵÏÖÁËmpo_create_credº¯Êý£¬¼´Ê¹Ã»ÓÐʵÏÖ mpo_execve_will_transition£¬Ò²Ó¦¸ÃʵÏָú¯Êý¡£


6.7.3.4.3 mpo_execve_will_transition

int mpo_execve_will_transition(struct ucred *old, struct vnode *vp, struct label *vnodelabel);

²ÎÊý ˵Ã÷ Ëø¶¨
old ÔÚÖ´ÐÐexecve(2)֮ǰµÄÖ÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
vp ½«±»Ö´ÐеÄÎļþ  
vnodelabel vp µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡ÓɲßÂÔ¾ö¶¨£¬µ±²ÎÊýÖ÷ÌåÐÅÈÎ×´Ö´ÐвÎÊý vnode ʱ£¬ÊÇ·ñÐèÒª½øÐÐÒ»¸ö±ê¼Çת»»²Ù×÷¡£Èç¹ûÐèÒª£¬·µ»Ø1£» ·ñÔò£¬·µ»Ø0¡£¼´Ê¹Ò»¸ö²ßÂÔ·µ»Ø0£¬ËüÒ²±ØÐëΪ×Ô¼º²»ÆÚÍûµÄ¶Ô mpo_execve_transitionµÄµ÷ÓÃ×÷ºÃ×¼±¸£¬ÒòΪֻҪÓÐÆäËûÈκÎÒ»¸ö²ßÂÔÒªÇóת»»£¬¾Í½«Ö´Ðд˺¯Êý¡£


6.7.3.4.4 mpo_create_proc0

void mpo_create_proc0(struct ucred *cred);

²ÎÊý ˵Ã÷ Ëø¶¨
cred ½«±»ÌîдµÄÖ÷ÌåÐÅÈÎ×´  

¡¡¡¡Îª½ø³Ì0£¬ËùÓÐÄں˽ø³ÌµÄ׿ÏÈ£¬´´½¨Ö÷ÌåÐÅÈÎ×´¡£


6.7.3.4.5 mpo_create_proc1

void mpo_create_proc1(struct ucred *cred);

²ÎÊý ˵Ã÷ Ëø¶¨
cred ½«±»ÌîдµÄÖ÷ÌåÐÅÈÎ×´  

¡¡¡¡Îª½ø³Ì1£¬ËùÓÐÓû§½ø³ÌµÄ׿ÏÈ£¬´´½¨Ö÷ÌåÐÅÈÎ×´¡£


6.7.3.4.6 mpo_relabel_cred

void mpo_relabel_cred(struct ucred *cred, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
newlabel ½«±»Ó¦Óõ½ cred ÉϵÄбê¼Ç  

¡¡¡¡¸ù¾Ý´«ÈëµÄбê¼Ç£¬¶ÔÖ÷ÌåÐÅÈÎ×´Éϵıê¼Ç½øÐиüС£


6.7.4 ·ÃÎÊ¿ØÖƼì²é

¡¡¡¡Í¨¹ý·ÃÎÊ¿ØÖÆÈë¿Úº¯Êý£¬²ßÂÔÄ£¿éÄÜÓ°ÏìÄں˵ķÃÎÊ¿ØÖƾö²ß¡£ ͨ³£Çé¿öÏ£¬²»ÊǾø¶Ô£¬Ò»¸ö·ÃÎÊ¿ØÖÆÈë¿Úº¯ÊýµÄ²ÎÊýÓУ¬Ò»¸ö»òÕßÈô¸É¸öÊÚȨÐÅÈÎ×´£¬ºÍÏà¹Ø²Ù×÷Éæ¼°µÄÆäËûÈκζÔÏóµÄÐÅÏ¢£¨ÆäÖпÉÄܰüº¬±ê¼Ç£©¡£ ·ÃÎÊ¿ØÖÆÈë¿Úº¯Êý·µ»Ø0£¬±íʾÔÊÐí¸Ã²Ù×÷£»·ñÔò£¬·µ»ØÒ»¸ö errno(2) ´íÎó±àÂë¡£µ÷ÓøÃÈë¿Úº¯Êý£¬½«±éÀúËùÓÐϵͳע²áµÄ²ßÂÔÄ£¿é£¬ÖðÒ»½øÐÐ ²ßÂÔÏà¹ØµÄ¼ì²éºÍ¾ö²ß£¬Ö®ºó°´ÕÕÏÂÊö·½·¨×éºÏ²»Í¬²ßÂԵķµ»Ø½á¹û£ºÖ»Óе±ËùÓеÄÄ£¿é¾ùÔÊÐí¸Ã²Ù×÷ʱ£¬²Å³É¹¦·µ»Ø¡£ ·ñÔò£¬Èç¹ûÓÐÒ»¸ö»òÕßÈô¸ÉÄ£¿éʧ°Ü·µ»Ø£¬ÔòÕû¸ö¼ì²é²»Í¨¹ý¡£Èç¹ûÓжà¸öÄ£¿éµÄ¼ì²é³ö´í·µ»Ø£¬½«Óɶ¨ÒåÔÚkern_mac.c ÖÐµÄ error_select() º¯Êý´ÓËüÃÇ·µ»ØµÄ´íÎó±àÂëÖУ¬Ñ¡ÔñÒ»¸öºÏÊʵ쬷µ»Ø¸øÓû§¡£

×î¸ßÓÅÏȼ¶ EDEADLK
  EINVAL
  ESRCH
  EACCES
×îµÍÓÅÏȼ¶ EPERM

¡¡¡¡Èç¹ûËùÓвßÂÔÄ£¿é·µ»ØµÄ´íÎó±àÂë¾ùûÓгöÏÖÔÚÉÏÊöÓÅÏȼ¶ÐòÁбíÖУ¬ÔòÈÎÒâÑ¡ÔñÒ»¸ö·µ»Ø¡£ Ñ¡Ôñ´íÎó±àÂëµÄÒ»°ã´ÎÐòΪ£ºÄں˴íÎó£¬ÎÞЧµÄ²ÎÊý£¬¶ÔÏó²»´æÔÚ£¬·ÃÎʱ»¾Ü¾ø£¬ºÍÆäËû´íÎó¡£


6.7.4.1 mpo_check_bpfdesc_receive

int mpo_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel, struct ifnet *ifnet, struct label *ifnetlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
bpf_d Ö÷Ì壻BPF ÃèÊö×Ó  
bpflabel bpf_d µÄ²ßÂÔ±ê¼Ç  
ifnet ¿ÍÌå£»ÍøÂç½Ó¿Ú  
ifnetlabel ifnet µÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨ MAC ¿ò¼ÜÊÇ·ñÓ¦¸ÃÔÊÐí½«ÓɲÎÊý½Ó¿Ú½ÓÊÕµ½µÄÊý¾Ý±¨´«µÝ¸øÓÉ BPF ÃèÊö×ÓËù¶ÔÓ¦µÄ»º³åÇø¡£³É¹¦£¬Ôò·µ»Ø0£» ·ñÔò£¬·µ»Ø´íÎó±àÂëÐÅÏ¢errno¡£½¨ÒéʹÓõĴíÎó±àÂëÓУºEACCES£¬ÓÃÓÚ±ê¼Ç²»·ûµÄÇé¿ö£» EPERM£¬ÓÃÓÚȱÉÙÌØÈ¨µÄÇé¿ö¡£


6.7.4.2 mpo_check_kenv_dump

int mpo_check_kenv_dump(struct ucred *cred);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓ¦¸Ã±»ÔÊÐí²éѯÄں˻·¾³×´Ì¬£¨²Î¿¼ kenv(2)£©¡£


6.7.4.3 mpo_check_kenv_get

int mpo_check_kenv_get(struct ucred *cred, char *name);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
name Äں˵Ļ·¾³±äÁ¿Ãû×Ö  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñ¿ÉÒÔ²éѯÄÚºËÖиø¶¨»·¾³±äÁ¿µÄ״̬¡£


6.7.4.4 mpo_check_kenv_set

int mpo_check_kenv_set(struct ucred *cred, char *name);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
name Äں˵Ļ·¾³±äÁ¿Ãû×Ö  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨÉèÖøø¶¨Äں˻·¾³±äÁ¿µÄÖµ¡£


6.7.4.5 mpo_check_kenv_unset

int mpo_check_kenv_unset(struct ucred *cred, char *name);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
name Äں˵Ļ·¾³±äÁ¿Ãû×ÖKernel environment variable name  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨÇå³ý¸ø¶¨µÄÄں˻·¾³±äÁ¿µÄÉèÖá£


6.7.4.6 mpo_check_kld_load

int mpo_check_kld_load(struct ucred *cred, struct vnode *vp, struct label *vlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ÄÚºËÄ£¿éµÄ vnode  
vlabel vpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨ¼ÓÔØ¸ø¶¨µÄÄ£¿éÎļþ¡£


6.7.4.7 mpo_check_kld_stat

int mpo_check_kld_stat(struct ucred *cred);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨ·ÃÎÊÄں˵ļÓÔØÄ£¿éÎļþÁ´±íÒÔ¼°Ïà¹ØµÄͳ¼ÆÊý¾Ý¡£


6.7.4.8 mpo_check_kld_unload

int mpo_check_kld_unload(struct ucred *cred);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐÈ¨Ð¶ÔØÒ»¸öÄÚºËÄ£¿é¡£


6.7.4.9 mpo_check_pipe_ioctl

int mpo_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, struct label *pipelabel, unsigned long cmd, void *data);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
pipe ¹ÜµÀ  
pipelabel pipeµÄ²ßÂÔ±ê¼Ç  
cmd ioctl(2) ÃüÁî  
data ioctl(2) Êý¾Ý  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨµ÷ÓÃÖ¸¶¨µÄ ioctl(2) ϵͳµ÷Óá£


6.7.4.10 mpo_check_pipe_poll

int mpo_check_pipe_poll(struct ucred *cred, struct pipe *pipe, struct label *pipelabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
pipe ¹ÜµÀ  
pipelabel pipeµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨ¶Ô¹ÜµÀpipeÖ´ÐÐpoll²Ù×÷¡£


6.7.4.11 mpo_check_pipe_read

int mpo_check_pipe_read(struct ucred *cred, struct pipe *pipe, struct label *pipelabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
pipe ¹ÜµÀ  
pipelabel pipeµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÊÇ·ñÓÐȨ¶ÁÈ¡pipe¡£


6.7.4.12 mpo_check_pipe_relabel

int mpo_check_pipe_relabel(struct ucred *cred, struct pipe *pipe, struct label *pipelabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
pipe ¹ÜµÀ  
pipelabel pipeµÄµ±Ç°²ßÂÔ±ê¼Ç  
newlabel ½«ÎªpipelabelÉèÖõÄбê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÊÇ·ñÓÐȨΪpipeÖØÐÂÉèÖñê¼Ç¡£


6.7.4.13 mpo_check_pipe_stat

int mpo_check_pipe_stat(struct ucred *cred, struct pipe *pipe, struct label *pipelabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
pipe ¹ÜµÀ  
pipelabel pipeµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÊÇ·ñÓÐȨ²éѯÓëpipeÏà¹ØµÄͳ¼ÆÐÅÏ¢¡£


6.7.4.14 mpo_check_pipe_write

int mpo_check_pipe_write(struct ucred *cred, struct pipe *pipe, struct label *pipelabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
pipe ¹ÜµÀ  
pipelabel pipeµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÊÇ·ñÓÐȨдpipe¡£


6.7.4.15 mpo_check_socket_bind

int mpo_check_socket_bind(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct sockaddr *sockaddr);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
socket ½«±»°ó¶¨µÄÌ×½Ó×Ö  
socketlabel socketµÄ²ßÂÔ±ê¼Ç  
sockaddr socketµÄµØÖ·  

6.7.4.16 mpo_check_socket_connect

int mpo_check_socket_connect(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct sockaddr *sockaddr);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
socket ½«±»Á¬½ÓµÄÌ×½Ó×Ö  
socketlabel socketµÄ²ßÂÔ±ê¼Ç  
sockaddr socketµÄµØÖ·  

¡¡¡¡¾ö¶¨¸ÃÖ÷Ì壨cred£©ÊÇ·ñÓÐȨ½«Ì×½Ó×Ö£¨socket£©°ó¶¨µ½µØÖ· sockaddr¡£³É¹¦£¬·µ»Ø0£¬·ñÔò·µ»ØÒ»¸ö´íÎó±àÂëerrno¡£ ½¨Òé²ÉÓõĴíÎó±àÂëÓУºEACCES£¬ÓÃÓÚ±ê¼Ç²»·ûµÄÇé¿ö£»EPERM£¬ÓÃÓÚÌØÈ¨²»×ãµÄÇé¿ö¡£


6.7.4.17 mpo_check_socket_receive

int mpo_check_socket_receive(struct ucred *cred, struct socket *so, struct label *socketlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
so Ì×½Ó×Ö  
socketlabel soµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÊÇ·ñÓÐȨ²éѯÌ×½Ó×ÖsoµÄÏà¹ØÐÅÏ¢¡£


6.7.4.18 mpo_check_socket_send

int mpo_check_socket_send(struct ucred *cred, struct socket *so, struct label *socketlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
so Ì×½Ó×Ö  
socketlabel soµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÊÇ·ñÓÐȨͨ¹ýÌ×½Ó×Öso·¢ËÍÐÅÏ¢¡£


6.7.4.19 mpo_check_cred_visible

int mpo_check_cred_visible(struct ucred *u1, struct ucred *u2);

²ÎÊý ˵Ã÷ Ëø¶¨
u1 Ö÷ÌåÐÅÈÎ×´  
u2 ¶ÔÏóÐÅÈÎ×´  

¡¡¡¡È·¶¨¸ÃÖ÷ÌåÐÅÈÎ×´u1ÊÇ·ñÓÐȨ ¡°see¡± ¾ßÓÐÐÅÈÎ×´u2 µÄÆäËûÖ÷Ìå¡£ ³É¹¦£¬·µ»Ø0£»·ñÔò£¬·µ»Ø´íÎó±àÂëerrno¡£½¨Òé²ÉÓõĴíÎó±àÂëÓУº EACCES£¬ÓÃÓÚ±ê¼Ç²»·ûµÄÇé¿ö£»EPERM£¬ÓÃÓÚÌØÈ¨²»×ãµÄÇé¿ö£»ESRCH£¬ ÓÃÀ´Ìṩ²»¿É¼ûÐÔ¡£¸Ãº¯Êý¿ÉÔÚÐí¶à»·¾³ÏÂʹÓ㬰üÀ¨ÃüÁîpsËùʹÓõĽø³Ì¼äµÄ״̬ sysctl£¬ÒÔ¼°Í¨¹ýprocfs µÄ״̬²éѯ²Ù×÷¡£


6.7.4.20 mpo_check_socket_visible

int mpo_check_socket_visible(struct ucred *cred, struct socket *socket, struct label *socketlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
socket ¿ÍÌ壻Ì×½Ó×Ö  
socketlabel socketµÄ²ßÂÔ±ê¼Ç  

6.7.4.21 mpo_check_ifnet_relabel

int mpo_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
ifnet ¿ÍÌå£»ÍøÂç½Ó¿Ú  
ifnetlabel ifnetÏÖÓеIJßÂÔ±ê¼Ç  
newlabel ½«±»Ó¦Óõ½ifnetÉϵÄеIJßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨʹÓô«ÈëµÄ±ê¼Ç¸üвÎÊý¶Ô¸ø¶¨µÄÍøÂç½Ó¿ÚµÄ±ê¼Ç½øÐÐÖØÐÂÉèÖá£


6.7.4.22 mpo_check_socket_relabel

int mpo_check_socket_relabel(struct ucred *cred, struct socket *socket, struct label *socketlabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
socket ¿ÍÌ壻Ì×½Ó×Ö  
socketlabel socketÏÖÓеIJßÂÔ±ê¼Ç  
newlabel ½«±»Ó¦Óõ½socketlabelÉϵĸüбê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ²ÉÓô«ÈëµÄ±ê¼Ç¶ÔÌ×½Ó×Ö²ÎÊýµÄ±ê¼Ç½øÐÐÖØÐÂÉèÖá£


6.7.4.23 mpo_check_cred_relabel

int mpo_check_cred_relabel(struct ucred *cred, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
newlabel ½«±»Ó¦Óõ½credÉϵĸüбê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ½«×Ô¼ºµÄ±ê¼ÇÖØÐÂÉèÖÃΪ¸ø¶¨µÄ¸üбê¼Ç¡£


6.7.4.24 mpo_check_vnode_relabel

int mpo_check_vnode_relabel(struct ucred *cred, struct vnode *vp, struct label *vnodelabel, struct label *newlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
vp ¿ÍÌ壻vnode Òѱ»Ëø¶¨
vnodelabel vpÏÖÓеIJßÂÔ±ê¼Ç  
newlabel ½«±»Ó¦Óõ½vpÉϵIJßÂÔ±ê¼Ç  

¡¡¡¡¾ö¶¨¸ÃÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ½«²ÎÊý vnode µÄ±ê¼ÇÖØÐÂÉèÖÃΪָ¶¨±ê¼Ç¡£


6.7.4.25 mpo_check_mount_stat

int mpo_check_mount_stat(struct ucred *cred, struct mount *mp, struct label *mountlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
mp ¿ÍÌ壻Îļþϵͳ¹ÒÔØ  
mountlabel mpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ²é¿´ÔÚ¸ø¶¨ÎļþϵͳÉÏÖ´ÐÐ statfs µÄ½á¹û¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£ ¸Ãº¯Êý¿ÉÄÜÔÚÏÂÁÐÇé¿öϱ»µ÷Ó㺠ÔÚ statfs(2) ºÍÆäËûÏà¹Øµ÷ÓÃÆÚ¼ä£¬»òÕßµ±ÐèÒª´ÓÎļþϵͳÁбíÖÐÑ¡ÔñÅųýÄĸöÎļþϵͳʱ£¬±ÈÈ磬 µ÷Óà getfsstat(2)ʱ¡£


6.7.4.26 mpo_check_proc_debug

int mpo_check_proc_debug(struct ucred *cred, struct proc *proc);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
proc ¿ÍÌ壻½ø³Ì  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ debug ¸ø¶¨½ø³Ì¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻EPERM£¬ÓÃÓÚȨÏÞ²»¹»£» ESRCH£¬ÓÃÓÚÒþÂ÷Ä¿±êµÄ´æÔÚ¡£ ptrace(2) ºÍ ktrace(2) API£¬ÒÔ¼°Ä³Ð© procfs ²Ù×÷½«µ÷Óøú¯Êý¡£


6.7.4.27 mpo_check_vnode_access

int mpo_check_vnode_access(struct ucred *cred, struct vnode *vp, struct label *label, int flags);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
flags access(2) ±êÖ¾  

¡¡¡¡¸ù¾ÝÏà¹ØÖ÷ÌåÐÅÈÎ×´¾ö¶¨Æä¶Ô¸ø¶¨ vnode ÒÔ¸ø¶¨·ÃÎʱêÖ¾Ö´ÐÐµÄ access(2) ºÍÆäËûÏà¹Øµ÷Óõķµ»ØÖµ¡£Ò»°ã£¬Ó¦²ÉÓÃÓëmpo_check_vnode_open ÏàͬµÄÓïÒåÀ´ÊµÏָú¯Êý¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.28 mpo_check_vnode_chdir

int mpo_check_vnode_chdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp ¿ÍÌ壻chdir(2) µÄÄ¿µÄ vnode  
dlabel dvpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ½«½ø³Ì¹¤×÷Ŀ¼Çл»µ½¸ø¶¨ vnode¡£³É¹¦£¬Ôò·µ»Ø 0£» ·ñÔò£¬·µ»ØÒ»¸ö errnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.29 mpo_check_vnode_chroot

int mpo_check_vnode_chroot(struct ucred *cred, struct vnode *dvp, struct label *dlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp Ŀ¼ vnode  
dlabel ÓëdvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨ chroot(2) µ½ÓÉ (dvp)¸ø¶¨µÄĿ¼¡£


6.7.4.30 mpo_check_vnode_create

int mpo_check_vnode_create(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp, struct vattr *vap);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp ¿ÍÌ壻vnode  
dlabel dvpµÄ²ßÂÔ±ê¼Ç  
cnp dvpÖеijÉÔ±Ãû  
vap vapµÄ vnode ÊôÐÔ  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÔÚ¸ø¶¨¸¸Ä¿Â¼£¬ÒÔ¸ø¶¨µÄÃû×ÖºÍÊôÐÔ£¬ ³£¼ûÒ»¸ö vnode¡£³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬ ·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES À´±íʾÓÃÓÚ±ê¼Ç²»Æ¥Å䣬 ¶øÓà EPERM£¬ÓÃÓÚȨÏÞ²»×ã¡£ ÒÔO_CREATΪ²ÎÊýµ÷Óà open(2)£¬»ò¶Ô mknod(2)£¬mkfifo(2) µÈµÄµ÷Óý«µ¼Ö¸ú¯Êý±»µ÷Óá£


6.7.4.31 mpo_check_vnode_delete

int mpo_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, void *label, struct componentname *cnp);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp ¸¸Ä¿Â¼ vnode  
dlabel dvpµÄ²ßÂÔ±ê¼Ç  
vp ¿ÍÌ壻½«±»É¾³ýµÄ vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
cnp vpÖеijÉÔ±Ãû  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ´Ó¸ø¶¨µÄ¸¸Ä¿Â¼ÖУ¬É¾³ý¸ø¶¨Ãû×ÖµÄ vnode¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£ ʹÓà unlink(2) ºÍ rmdir(2)£¬½«µ¼Ö¸ú¯Êý±»µ÷ÓᣠÌṩ¸ÃÈë¿Úº¯ÊýµÄ²ßÂÔ»¹±ØÐëʵÏÖÒ»¸ö mpo_check_rename_to£¬ ÓÃÀ´ÊÚȨÓÉÓÚÖØÃüÃû²Ù×÷µ¼ÖµÄÄ¿±êÎļþµÄɾ³ý¡£


6.7.4.32 mpo_check_vnode_deleteacl

int mpo_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
vp ¿ÍÌ壻vnode ±»Ëø¶¨
label vpµÄ²ßÂÔ±ê¼Ç  
type ACL ÀàÐÍ  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨɾ³ý¸ø¶¨ vnode µÄ¸ø¶¨ÀàÐ굀 ACL¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.33 mpo_check_vnode_exec

int mpo_check_vnode_exec(struct ucred *cred, struct vnode *vp, struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻½«±»Ö´ÐÐµÄ vnode  
label vpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨִÐиø¶¨ vnode¡£ ¶ÔÓÚÖ´ÐÐÌØÈ¨µÄ¾ö²ßÓëÈκÎ˲ʱʼþµÄ¾ö²ßÊÇÑϸñ·Ö¿ªµÄ¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.34 mpo_check_vnode_getacl

int mpo_check_vnode_getacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
type ACL ÀàÐÍ  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ²éѯ¸ø¶¨ vnode Éϵĸø¶¨ÀàÐ굀 ACL¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.35 mpo_check_vnode_getextattr

int mpo_check_vnode_getextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name, struct uio *uio);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
attrnamespace À©Õ¹ÊôÐÔÃû×Ö¿Õ¼ä  
name À©Õ¹ÊôÐÔÃû  
uio I/O ½á¹¹Ö¸Õ룻²Î¼û uio(9)  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ²éѯ¸ø¶¨ vnode Éϸø¶¨Ãû×Ö¿Õ¼äºÍÃû×ÖµÄÀ©Õ¹ÊôÐÔ¡£ ʹÓÃÀ©Õ¹ÊôÐÔʵÏÖ±ê¼Ç´æ´¢µÄ²ßÂÔÄ£¿é¿ÉÄÜ»áÐèÒª¶ÔÕâЩÀ©Õ¹ÊôÐԵIJÙ×÷½øÐÐÌØÊâ´¦Àí¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.36 mpo_check_vnode_link

int mpo_check_vnode_link(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp Ŀ¼ vnode  
dlabel ÓëdvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
vp Á´½ÓÄ¿µÄ vnode  
label ÓëvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
cnp ½«±»´´½¨µÄÁ´½Ó¶ÔÓ¦µÄ³ÉÔ±Ãû  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨΪ²ÎÊývp¸ø¶¨µÄ vnode ´´½¨Ò»¸öÓɲÎÊýcnp¸ø¶¨Ãû×ÖµÄÁ´½Ó¡£


6.7.4.37 mpo_check_vnode_mmap

int mpo_check_vnode_mmap(struct ucred *cred, struct vnode *vp, struct label *label, int prot);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ½«±»Ó³ÉäµÄ vnode  
label ÓëvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
prot mmap ±£»¤ (²Î¼û mmap(2))  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨ½«¸ø¶¨ vnode vp ÒÔ protÖ¸¶¨µÄ±£»¤·½Ê½½øÐÐÓ³Éä.


6.7.4.38 mpo_check_vnode_mmap_downgrade

void mpo_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, struct label *label, int *prot);

²ÎÊý ˵Ã÷ Ëø¶¨
cred See µÚ 6.7.4.37 ½Ú.  
vp  
label  
prot ½«±»½µ¼¶µÄ mmap protections  

¡¡¡¡¸ù¾ÝÖ÷ÌåºÍ¿ÍÌå±ê¼Ç£¬½µµÍ mmap protections¡£


6.7.4.39 mpo_check_vnode_mprotect

int mpo_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, struct label *label, int prot);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp Ó³ÉäµÄ vnode  
prot ´æ´¢±£»¤  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨ½«¸ø¶¨ vnodevp Ó³ÉäÄÚ´æ¿Õ¼äµÄ´æ´¢±£»¤²ÎÊýÉèÖÃΪָ¶¨Öµ¡£


6.7.4.40 mpo_check_vnode_poll

int mpo_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred, struct vnode *vp, struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
active_cred Ö÷ÌåÐÅÈÎ×´  
file_cred Óëstruct fileÏà¹ØÁªµÄÐÅÈÎ×´  
vp ½«±»Ö´ÐÐ poll ²Ù×÷µÄ vnode  
label ÓëvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨ¶Ô¸ø¶¨ vnode vpÖ´ÐÐ poll ²Ù×÷¡£


6.7.4.41 mpo_check_vnode_rename_from

int mpo_vnode_rename_from(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, struct componentname *cnp);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp Ŀ¼ vnode  
dlabel ÓëdvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
vp ½«±»ÖØÃüÃûµÄ vnode  
label ÓëvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
cnp vpÖеijÉÔ±Ãû  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐÈ¨ÖØÃüÃû¸ø¶¨vnode£¬vp¡£


6.7.4.42 mpo_check_vnode_rename_to

int mpo_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct vnode *vp, struct label *label, int samedir, struct componentname *cnp);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp Ŀ¼ vnode  
dlabel ÓëdvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
vp ±»¸²¸ÇµÄ vnode  
label ÓëvpÏà¹ØÁªµÄ²ßÂÔ±ê¼Ç  
samedir ²¼¶ûÐͱäÁ¿£»Èç¹ûÔ´ºÍÄ¿µÄĿ¼ÊÇÏàͬµÄ£¬Ôò±»ÖÃΪ1  
cnp Ä¿±êcomponentÃû  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐÈ¨ÖØÃüÃû¸ø¶¨ vnode vp£¬ÖÁÖ¸¶¨Ä¿Â¼ dvp£¬»ò¸üÃûΪcnp¡£Èç¹ûÎÞÐ踲¸ÇÒÑÓÐÎļþ£¬ Ôòvp ºÍ label µÄÖµ½«Îª NULL.


6.7.4.43 mpo_check_socket_listen

int mpo_check_socket_listen(struct ucred *cred, struct socket *socket, struct label *socketlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
socket ¿ÍÌ壻Ì×½Ó×Ö  
socketlabel socketµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨ¼àÌý¸ø¶¨Ì×½Ó×Ö¡£ ³É¹¦£¬Ôò·µ»Ø0£»·ñÔò£¬·µ»Ø´íÎó±àÂëÖµerrno¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.44 mpo_check_vnode_lookup

int mpo_check_vnode_lookup(struct ucred *cred, struct vnode *dvp, struct label *dlabel, struct componentname *cnp);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp ¿ÍÌ壻vnode  
dlabel dvpµÄ²ßÂÔ±ê¼Ç  
cnp ±»¼ì²éµÄ³ÉÔ±Ãû  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÔÚ¸ø¶¨µÄĿ¼ vnode ÖÐΪ²éÕÒ¸ø¶¨Ãû×ÖÖ´ÐÐlookup²Ù×÷¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸ö errnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.45 mpo_check_vnode_open

int mpo_check_vnode_open(struct ucred *cred, struct vnode *vp, struct label *label, int acc_mode);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
acc_mode open(2) ·ÃÎÊģʽ  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÔÚ¸ø¶¨ vnode ÉÏÒÔ¸ø¶¨µÄ·ÃÎÊģʽִÐÐ open ²Ù×÷¡£ Èç¹û³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸ö´íÎó±àÂë¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.46 mpo_check_vnode_readdir

int mpo_check_vnode_readdir(struct ucred *cred, struct vnode *dvp, struct label *dlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
dvp ¿ÍÌ壻Ŀ¼ vnode  
dlabel dvpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÔÚ¸ø¶¨µÄĿ¼ vnode ÉÏÖ´ÐÐ readdir ²Ù×÷¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸ö´íÎó±àÂë errno¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.47 mpo_check_vnode_readlink

int mpo_check_vnode_readlink(struct ucred *cred, struct vnode *vp, struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÔÚ¸ø¶¨·ûºÅÁ´½Ó vnode ÉÏÖ´ÐÐ readlink ²Ù×÷¡£³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£ ¸Ãº¯Êý¿ÉÄÜÔÚÈô¸É»·¾³Ï±»µ÷Ó㬰üÀ¨ÓÉÓû§½ø³ÌÏÔʽִÐÐµÄ readlink µ÷Ó㬠»òÕßÊÇÔÚ½ø³ÌÖ´ÐÐÃû×Ö²éѯʱÒþʽִÐÐµÄ readlink ¡£


6.7.4.48 mpo_check_vnode_revoke

int mpo_check_vnode_revoke(struct ucred *cred, struct vnode *vp, struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ³·Ïú¶Ô¸ø¶¨ vnode µÄ·ÃÎÊ¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.49 mpo_check_vnode_setacl

int mpo_check_vnode_setacl(struct ucred *cred, struct vnode *vp, struct label *label, acl_type_t type, struct acl *acl);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
type ACL ÀàÐÍ  
acl ACL  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÉèÖøø¶¨ vnode µÄ¸ø¶¨ÀàÐ굀 ACL¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.50 mpo_check_vnode_setextattr

int mpo_check_vnode_setextattr(struct ucred *cred, struct vnode *vp, struct label *label, int attrnamespace, const char *name, struct uio *uio);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
attrnamespace À©Õ¹ÊôÐÔÃû×Ö¿Õ¼ä  
name À©Õ¹ÊôÐÔÃû  
uio I/O ½á¹¹Ö¸Õ룻²Î¼û uio(9)  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÉèÖøø¶¨ vnode Éϸø¶¨Ãû×Ö¿Õ¼äÖиø¶¨Ãû×ÖµÄÀ©Õ¹ÊôÐÔµÄÖµ¡£ ʹÓÃÀ©Õ¹ÊôÐÔ±¸·Ý°²È«±ê¼ÇµÄ²ßÂÔÄ£¿é¿ÉÄÜÐèÒª¶ÔÆäʹÓõÄÊôÐÔʵʩ¶îÍâµÄ±£»¤¡£ÁíÍ⣬ ÓÉÓÚÔÚ¼ì²éºÍʵ¼Ê²Ù×÷ʱ¼ä¿ÉÄÜ´æÔڵľºÕù£¬ ²ßÂÔÄ£¿éÓ¦¸Ã±ÜÃâ¸ù¾ÝÀ´×ÔuioÖеÄÊý¾Ý×ö³ö¾ö²ß¡£ Èç¹ûÕýÔÚÖ´ÐÐÒ»¸öɾ³ý²Ù×÷£¬Ôò²ÎÊý uio µÄÖµÒ²¿ÉÄÜΪ NULL¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.51 mpo_check_vnode_setflags

int mpo_check_vnode_setflags(struct ucred *cred, struct vnode *vp, struct label *label, u_long flags);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
flags Îļþ±êÖ¾£»²Î¼û chflags(2)  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨΪ¸ø¶¨µÄ vnode ÉèÖøø¶¨µÄ±êÖ¾¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.52 mpo_check_vnode_setmode

int mpo_check_vnode_setmode(struct ucred *cred, struct vnode *vp, struct label *label, mode_t mode);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
mode Îļþģʽ£»²Î¼û chmod(2)  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ½«¸ø¶¨ vnode µÄģʽÉèÖÃΪ¸ø¶¨Öµ¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.53 mpo_check_vnode_setowner

int mpo_check_vnode_setowner(struct ucred *cred, struct vnode *vp, struct label *label, uid_t uid, gid_t gid);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  
uid Óû§ID  
gid ×éID  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ½«¸ø¶¨ vnode µÄÎļþ uid ºÍÎļþ gid ÉèÖÃΪ¸ø¶¨Öµ¡£Èç¹ûÎÞÐè¸üУ¬ Ïà¹Ø²ÎÊýÖµ¿ÉÄܱ»ÉèÖÃΪ(-1)¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.54 mpo_check_vnode_setutimes

int mpo_check_vnode_setutimes(struct ucred *cred, struct vnode *vp, struct label *label, struct timespec atime, struct timespec mtime);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vp  
label vpµÄ²ßÂÔ±ê¼Ç  
atime ·ÃÎÊʱ¼ä£»²Î¼û utimes(2)  
mtime ÐÞ¸Äʱ¼ä£»²Î¼û utimes(2)  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ½«¸ø¶¨ vnode µÄ·ÃÎÊʱ¼ä±êÇ©ÉèÖÃΪ¸ø¶¨Öµ¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.55 mpo_check_proc_sched

int mpo_check_proc_sched(struct ucred *ucred, struct proc *proc);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
proc ¿ÍÌ壻½ø³Ì  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨ¸Ä±ä¸ø¶¨½ø³ÌµÄµ÷¶È²ÎÊý¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»£» ESRCH£¬ÓÃÓÚÌṩ²»¿É¼ûÐÔÖÊ¡£

¡¡¡¡See setpriority(2) for more information.


6.7.4.56 mpo_check_proc_signal

int mpo_check_proc_signal(struct ucred *cred, struct proc *proc, int signal);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
proc ¿ÍÌ壻½ø³Ì  
signal Ðźţ»²Î¼û kill(2)  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÏò¸ø¶¨½ø³Ì·¢Ë͸ø¶¨Ðźš£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻EPERM£¬ÓÃÓÚȨÏÞ²»¹»£» ESRCH£¬ÓÃÓÚÌṩ²»¿É¼ûÐÔÖÊ¡£


6.7.4.57 mpo_check_vnode_stat

int mpo_check_vnode_stat(struct ucred *cred, struct vnode *vp, struct label *label);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp ¿ÍÌ壻vnode  
label vpµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´ÊÇ·ñÓÐȨÔÚ¸ø¶¨ vnode ÉÏÖ´ÐÐ stat ²Ù×÷¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£

¡¡¡¡See stat(2) for more information.


6.7.4.58 mpo_check_ifnet_transmit

int mpo_check_ifnet_transmit(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
ifnet ÍøÂç½Ó¿Ú  
ifnetlabel ifnetµÄ²ßÂÔ±ê¼Ç  
mbuf ¿ÍÌ壻½«±»·¢Ë굀 mbuf  
mbuflabel mbufµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÍøÂç½Ó¿ÚÊÇ·ñÓÐȨ´«Ë͸ø¶¨µÄ mbuf¡£³É¹¦£¬Ôò·µ»Ø 0£» ·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.59 mpo_check_socket_deliver

int mpo_check_socket_deliver(struct ucred *cred, struct ifnet *ifnet, struct label *ifnetlabel, struct mbuf *mbuf, struct label *mbuflabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
ifnet ÍøÂç½Ó¿Ú  
ifnetlabel ifnetµÄ²ßÂÔ±ê¼Ç  
mbuf ¿ÍÌ壻½«±»´«Ë굀 mbuf  
mbuflabel mbufµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÌ×½Ó×ÖÊÇ·ñÓÐȨ´Ó¸ø¶¨µÄ mbuf ÖнÓÊÕÊý¾Ý±¨¡£ ³É¹¦£¬Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»¡£


6.7.4.60 mpo_check_socket_visible

int mpo_check_socket_visible(struct ucred *cred, struct socket *so, struct label *socketlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´ ²»¿É¸Ä±ä
so ¿ÍÌ壻Ì×½Ó×Ö  
socketlabel soµÄ²ßÂÔ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÐÅÈÎ×´cred ÊÇ·ñÓÐȨʹÓÃϵͳ¼à¿Øº¯Êý£¬±ÈÈ磬 ÓÉnetstat(8) ºÍ sockstat(1)ʹÓõijÌÐòÀ´¹Û²ì ¸ø¶¨µÄÌ×½Ó×Ö(socket)¡£³É¹¦£¬ Ôò·µ»Ø 0£»·ñÔò£¬·µ»ØÒ»¸öerrnoÖµ¡£ ½¨ÒéʹÓõĴíÎó±àÂ룺EACCES£¬ÓÃÓÚ±ê¼Ç²»Æ¥Å䣻 EPERM£¬ÓÃÓÚȨÏÞ²»¹»£» ESRCH£¬ÓÃÓÚÌṩ²»¿É¼ûÐÔÖÊ¡£


6.7.4.61 mpo_check_system_acct

int mpo_check_system_acct(struct ucred *ucred, struct vnode *vp, struct label *vlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
ucred Ö÷ÌåÐÅÈÎ×´  
vp Éó¼ÆÎļþ£»acct(5)  
vlabel ÓëvpÏà¹ØÁªµÄ±ê¼Ç  

¡¡¡¡¸ù¾ÝÖ÷Ìå±ê¼ÇºÍÉó¼ÆÈÕÖ¾ÎļþµÄ±ê¼Ç£¬È·¶¨¸ÃÖ÷ÌåÊÇ·ñÓÐȨÆô¶¯É󼯡£


6.7.4.62 mpo_check_system_nfsd

int mpo_check_system_nfsd(struct ucred *cred);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨµ÷Óà nfssvc(2)¡£


6.7.4.63 mpo_check_system_reboot

int mpo_check_system_reboot(struct ucred *cred, int howto);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
howto À´×Ô reboot(2)µÄhowto ²ÎÊý  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨÒÔÖ¸¶¨·½Ê½ÖØÆôϵͳ¡£


6.7.4.64 mpo_check_system_settime

int mpo_check_system_settime(struct ucred *cred);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  

¡¡¡¡È·¶¨Ïà¹ØÓû§ÊÇ·ñÓÐȨÉèÖÃϵͳʱÖÓ¡£


6.7.4.65 mpo_check_system_swapon

int mpo_check_system_swapon(struct ucred *cred, struct vnode *vp, struct label *vlabel);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
vp swapÉ豸  
vlabel ÓëvpÏà¹ØÁªµÄ±ê¼Ç  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓÐȨÔö¼ÓÒ»¸ö×÷ΪswapÉ豸µÄ vp ¡£


6.7.4.66 mpo_check_system_sysctl

int mpo_check_system_sysctl(struct ucred *cred, int *name, u_int *namelen, void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen);

²ÎÊý ˵Ã÷ Ëø¶¨
cred Ö÷ÌåÐÅÈÎ×´  
name ²Î¼û sysctl(3)  
namelen  
old  
oldlenp  
inkernel ²¼¶ûÐͱäÁ¿£»Èç¹û´ÓÄں˱»µ÷Óã¬ÆäÖµ±»ÖÃΪ1  
new ²Î¼û sysctl(3)  
newlen  

¡¡¡¡È·¶¨Ïà¹ØÖ÷ÌåÊÇ·ñÓ¦¸Ã±»ÔÊÐíÖ´ÐÐÖ¸¶¨µÄ sysctl(3) ÊÂÎñ¡£


6.7.5 ±ê¼Ç¹ÜÀíµ÷ÓÃ

¡¡¡¡µ±Óû§½ø³ÌÇëÇó¶Ôij¸ö¶ÔÏóµÄ±ê¼Ç½øÐÐÐÞ¸Äʱ£¬½«Òý·¢ÖØÐ±ê¼Çʼþ¡£¶ÔÓ¦µÄ¸üвÙ×÷·ÖÁ½²½½øÐУº Ê×ÏÈ£¬½øÐзÃÎÊ¿ØÖƼì²é£¬È·Èϴ˴θüвÙ×÷ÊÇÓÐЧÇÒ±»ÔÊÐíµÄ£»È»ºó£¬µ÷ÓÃÁíÒ»¸ö¶ÀÁ¢µÄÈë¿Úº¯Êý¶Ô±ê¼Ç½øÐÐÐ޸ġ£ ÖØÐ±ê¼ÇÈë¿Úº¯Êýͨ³£½ÓÊÕÓÉÇëÇó½ø³ÌÌá½»µÄ¶ÔÏó¡¢¶ÔÏó±ê¼ÇÖ¸ÕëºÍÇëÇóбê¼Ç£¬×÷ΪÊäÈë²ÎÊý¡£ ¶ÔÏóÖØÐ±ê¼Ç²Ù×÷µÄʧ°Ü½«ÓÉÏÈÆÚµÄ±ê¼Ç¼ì²é±¨¸æ£¬ËùÒÔ£¬²»ÔÊÐíÔÚ½ÓÏÂÀ´µÄ±ê¼ÇÐ޸Ĺý³ÌÖб¨¸æÊ§°Ü£¬¹Ê¶ø²»ÌᳫÔڴ˹ý³ÌÖÐзÖÅäÄÚ´æ¡£


6.8 Ó¦ÓòãÌåϵ½á¹¹

¡¡¡¡TrustedBSD MAC ¿ò¼Ü°üº¬ÁËÒ»×é²ßÂÔÎ޹صÄ×é³ÉÔªËØ£¬°üÀ¨¹ÜÀí³éÏó±ê¼ÇµÄ MAC ½Ó¿Ú¿â£¬ ¶ÔϵͳÐÅÈÎ×´¹ÜÀíÌåϵµÄÐÞ¸Ä, ΪÓû§·ÖÅä MAC ±ê¼ÇÌṩ֧³ÖµÄ login ¿âº¯Êý£¬ ÒÔ¼°Èô¸É¸ºÔðά»¤ºÍ¸üÐÂÄں˶ÔÏó(½ø³Ì¡¢ÎļþºÍÍøÂç½Ó¿ÚµÈ)°²È«±ê¼ÇµÄ¹¤¾ß¡£ ²»¾Ã£¬½«Óиü¶à¹ØÓÚÓ¦ÓòãÌåϵ½á¹¹µÄÏêϸÐÅÏ¢±»°üº¬½øÀ´¡£


6.8.1 ²ßÂÔÎ޹صıê¼Ç¹ÜÀí API

¡¡¡¡TrustedBSD MAC ÌṩµÄ´óÁ¿¿âº¯ÊýºÍϵͳµ÷Óã¬ÔÊÐíÓ¦ÓóÌÐòʹÓÃÒ»ÖÖͳһµÄ¡¢²ßÂÔÎ޹صĽӿÚÀ´´¦Àí¶ÔÏóµÄ MAC ±ê¼Ç¡£ Èç´Ë£¬Ó¦ÓóÌÐò¿ÉÒÔÇáËɹÜÀí¸÷ÖÖ²ßÂԵıê¼Ç£¬ÎÞÐèΪÔö¼Ó¶Ôij¸öÌØ¶¨²ßÂÔµÄÖ§³Ö¶øÖØÐ±àÂë¡£Ðí¶àͨÓù¤¾ß£¬±ÈÈç ifconfig(8)£¬ls(1) ºÍ ps(1)£¬Ê¹ÓÃÕâЩ²ßÂÔÎ޹صĽӿڲéÑ¯ÍøÂç½á¹¹¡¢ÎļþºÍ½ø³ÌµÄ±ê¼ÇÐÅÏ¢¡£ ÕâЩ API Ò²±»ÓÃÓÚÖ§³Ö MAC ¹ÜÀí¹¤¾ß£¬±ÈÈ磬getfmac(8)£¬getpmac(8)£¬ setfmac(8)£¬ setfsmac(8)£¬ºÍ setpmac(8)¡£ MAC APIµÄÉè¼ÆÏ¸½Ú¿É²Î¿¼ mac(3).

¡¡¡¡Ó¦ÓóÌÐò´¦ÀíµÄ MAC ±ê¼ÇÓÐÁ½ÖÖ´æÔÚÐÎʽ£ºÄÚ²¿ÐÎʽ£¬ÓÃÀ´·µ»ØºÍÉèÖýø³ÌºÍ¶ÔÏóµÄ±ê¼Ç£¨mac_t£©£» »ùÓÚ C ×Ö·û´®µÄÍⲿÐÎʽ£¬×÷Ϊ±ê¼ÇÔÚÅäÖÃÎļþÖеĴæ·ÅÐÎʽ£¬ÓÃÓÚÏòÓû§ÏÔʾ»òÕßÓÉÓû§ÊäÈë¡£ ÿһ¸ö MAC ±ê¼ÇÓÉÒ»×é±ê¼ÇÔªËØ×é³É£¬ÆäÖÐÿ¸öÔªËØÊÇÒ»¸öÐÎÈ磨Ãû×Ö£¬Öµ£©µÄ¶þÔª×é¡£ ÄÚºËÖеÄÿ¸ö²ßÂÔÄ£¿é·Ö±ð±»Ö¸¶¨Ò»¸öÌØ¶¨µÄÃû×Ö£¬ÓÉËüÃǶԱê¼ÇÖÐÓë¸ÃÃû×Ö¶ÔÓ¦µÄÖµ²ÉÓÃÆä²ßÂÔÌØÓеķ½Ê½½øÐнâÎö¡£ ²ÉÓÃÍⲿÐÎʽ±íʾµÄ±ê¼Ç£¬Æä±ê¼ÇÔªËØ±íʾΪÃû×Ö / Öµ£¬ÔªËØÖ®¼äÒÔ¶ººÅ·Ö¸ô¡£ Ó¦ÓóÌÐò¿ÉÒÔʹÓà MAC ¿ò¼ÜÌṩµÄ API ½«Ò»¸ö°²È«±ê¼ÇÔÚÄÚ²¿ÐÎʽºÍÎı¾ÐÎʽ֮¼ä½øÐÐת»»¡£ ÿµ±ÏòÄں˲éѯij¸ö¶ÔÏóµÄ°²È«±ê¼Çʱ£¬ÄÚ²¿ÐÎʽµÄ±ê¼Ç±ØÐëÕë¶ÔËùÐèµÄÔªËØ¼¯ºÏ×÷ºÃÄÚ²¿±ê¼Ç´æ´¢×¼±¸¡£ Ϊ´Ë£¬Í¨³£²ÉÓÃÏÂÃæÁ½ÖÖ·½Ê½Ö®Ò»£ºÊ¹Óà mac_prepare(3) ºÍÒ»¸ö°üº¬ËùÐè±ê¼ÇÔªËØµÄÈÎÒâÁÐ±í£»»òÕߣ¬ ʹÓôÓmac.conf(5) ÅäÖÃÎļþÖмÓÔØÈ±Ê¡ÔªËØ¼¯ºÏµÄij¸öϵͳµ÷Óá£ÔÚ¶ÔÏó¼¶±ðÉèÖÃȱʡ±ê¼Ç£¬½«ÔÊÐíÓ¦ÓóÌÐòÔÚ²»È·¶¨ ϵͳÊÇ·ñ²ÉÓÃÏà¹Ø²ßÂÔµÄÇé¿öÏ£¬Ò²ÄÜÏòÓû§·µ»ØÓë¶ÔÏóÏà¹ØÁªµÄÓÐÒâÒåµÄ°²È«±ê¼Ç¡£

×¢Òâ: ĿǰµÄ MAC ¿â²»Ö§³ÖÖ±½ÓÐÞ¸ÄÄÚ²¿ÐÎʽµÄ±ê¼ÇÔªËØ£¬ËùÓеÄÐ޸ıØÐë°´ÕÕÏÂÁеIJ½Öè½øÐУº ½«ÄÚ²¿ÐÎʽµÄ±ê¼Çת»»³ÉÎı¾×Ö·û´®£¬¶Ô×Ö·û´®½øÐб༭£¬×îºó½«Æäת»»³ÉÄÚ²¿ÐÎʽ±ê¼Ç¡£Èç¹ûÓ¦ÓóÌÐòµÄ×÷ÕßÖ¤Ã÷ȷʵÓÐÐèÒª£¬ ¿ÉÒÔÔÚ½«À´µÄ°æ±¾ÖмÓÈë¶ÔÄÚ²¿ÐÎʽ±ê¼Ç½øÐÐÖ±½ÓÐ޸ĵĽӿڡ£


6.8.2 ΪÓû§Ö¸¶¨±ê¼Ç

¡¡¡¡Óû§ÉÏÏÂÎĹÜÀíµÄ±ê¼Ç½Ó¿Ú£¬ setusercontext(3) £¬µÄÐÐΪÒѾ­±»ÐÞ¸ÄΪ£¬´Ó login.conf(5) ÖвéѯÓëij¸öÓû§µÇ¼Àà±ðÏà¹ØÁªµÄ MAC °²È«±ê¼Ç¡£ µ± LOGIN_SETALL ±»ÉèÖ㬻òÕßµ± LOGIN_SETMAC ±»Ã÷È·Ö¸¶¨Ê±£¬ÕâЩ°²È«±ê¼Ç½«ºÍÆäËûÓû§ÉÏÏÂÎIJÎÊýÒ»Æð±»ÉèÖá£

×¢Òâ: ¿ÉÒÔÔ¤ÆÚ£¬ÔÚ½ñºóµÄij¸ö°æ±¾ÖУ¬FreeBSD ½«°Ñ MAC ±ê¼Ç´Ó login.conf µÄÓû§Àà±ðÊý¾Ý¿âÖгé³ö£¬ÎªÆäά»¤Ò»¸ö¶ÀÁ¢µÄÊý¾Ý¿â¡£ ²»¹ýÔÚ´Ëǰºó£¬setusercontext(3) APIÓ¦¸Ã±£³Ö²»±ä¡£


6.9 С½á

¡¡¡¡TrustedBSD MAC ¿ò¼ÜʹµÃÄÚºËÄ£¿éÄÜÒÔÒ»ÖÖ¼¯Öеķ½Ê½£¬ÍêÉÆÏµÍ³µÄ°²È«²ßÂÔ¡£ ËüÃǼȿÉÀûÓÃÏÖÓеÄÄں˶ÔÏóÊôÐÔ£¬ÓÖÄÜʹÓÃÓÉ MAC ¿ò¼ÜЭÖúά»¤µÄ°²È«±ê¼ÇÊý¾Ý£¬À´ÊµÊ©·ÃÎÊ¿ØÖÆ¡£ ¿ò¼ÜÌṩµÄÁé»îÐÔʹµÃ¿ª·¢ÈËÔ±¿ÉÒÔÔÚÆäÉÏʵÏÖ¸÷ÖÖ²ßÂÔ£¬ÈçÀûÓà BSD ÏÖÓеÄÐÅÈÎ×´£¨credential£© ÓëÎļþ±£»¤»úÖÆµÄ²ßÂÔ£¬ÒÔ¼°ÐÅÏ¢Á÷°²È«²ßÂÔ£¨Èç MLS ºÍ Biba£©¡£ ʵÏÖа²È«·þÎñµÄ²ßÂÔ±à³ÌÈËÔ±£¬¿ÉÒԲο¼±¾Îĵµ£¬ÒÔÁ˽âÏÖÓа²È«Ä£¿éµÄÐÅÏ¢¡£


µÚ7Õ ¡¡ÐéÄâÄÚ´æÏµÍ³

¹©¸å£ºMatthew Dillon. ·­Ò룺intron@intron.ac.

7.1 ÎïÀíÄÚ´æµÄ¹ÜÀí©¤©¤vm_page_t

¡¡¡¡ÎïÀíÄÚ´æÍ¨¹ý½á¹¹Ìåvm_page_tÒÔҳΪ»ù´¡½øÐйÜÀí¡£ ÎïÀíÄÚ´æµÄÒ³ÓÉËüÃǸ÷×Ô¶ÔÓ¦µÄ½á¹¹Ìåvm_page_tËù´ú±í£¬ ÕâЩ½á¹¹Ìå´æ·ÅÔÚÈô¸É¸öÒ³¹ÜÀí¶ÓÁÐÖеÄÒ»¸öÀïÃæ¡£

¡¡¡¡Ò»Ò³¿ÉÒÔ´¦ÓÚÔÚÏß(wired)¡¢»î¶¯(active)£¬È¥»î(inactive)¡¢»º´æ(cache)¡¢ ×ÔÓÉ(free)״̬¡£³ýÁËÔÚÏß״̬£¬Ò³Ò»°ã±»·ÅÖÃÔÚÒ»¸öË«ÏòÁ´±í¶ÓÁÐÀ ´ú±íÁËËüËù´¦µÄ״̬¡£ÔÚÏßÒ³²»·ÅÖÃÔÚÈκζÓÁÐÀï¡£

¡¡¡¡FreeBSDΪ»º´æÒ³ºÍ×ÔÓÉҳʵÏÖÁËÒ»¸ö¸üΪ¸´ÔÓµÄÒ³¶ÓÁлúÖÆ£¬ ÒÔʵÏÖ¶ÔÒ³µÄ·ÖÀà¹ÜÀí¡£Ã¿Ò»ÖÖ״̬¶¼¶ÔÓ¦×Ŷà¸ö¶ÓÁУ¬ ¶ÓÁеݲÅŶÔÓ¦×Å´¦ÀíÆ÷µÄÒ»¼¶¡¢¶þ¼¶»º´æ¡£µ±ÐèÒª·ÖÅäÒ»¸öÐÂҳʱ£¬ FreeBSD»áÊÔͼ°ÑÒ»¸ö°´Ò»¼¶¡¢¶þ¼¶»º´æ¶ÔÆëµÄÒ³Ãæ·ÖÅ䏸ÐéÄâÄÚ´æ¶ÔÏó¡£

¡¡¡¡´ËÍ⣬һ¸öÒ³¿ÉÒÔÓÐÒ»¸öÒýÓüÆÊý£¬¿ÉÒÔ±»Ò»¸öæ¼ÆÊýËø¶¨¡£ ÐéÄâÄÚ´æÏµÍ³Ò²ÊµÏÖÁË¡°ÖÕ¼«Ëø¶¨¡±(ultimate locked)״̬£¬ Ò»¸öÒ³¿ÉÒÔÓÃÒ³±êÖ¾PG_BUSY±íʾÕâһ״̬¡£

¡¡¡¡×ÜÖ®£¬Ã¿¸öÒ³¶ÓÁж¼°´ÕÕLRU(Least-Recently Used)µÄÔ­Ôò¹¤×÷¡£

ÒëÕß×¢: ¶ÌÓïLeast-Recently UsedÓÐÁ½ÖÖÀí½â·½Ê½£º 1.½«¡°least-recently¡±Àí½âΪ·´Ïò±È½Ï¼¶£¬ÒâÒåΪ¡°×îÔ硱£¬Õû¸ö¶ÌÓïÀí½âΪ ¡°×î½üµÄʹÓÃʱ¼ä×îÔ硱£»2.½«¡°least¡±ºÍ¡°recently¡±Àí½âΪ¸±´Ê£¬ ¶¼ÐÞÊΡ°used¡±£¬Õû¸ö¶ÌÓïÀí½âΪ¡°×î½ü×îÉÙʹÓᱡ£ ÕâÁ½ÖÖÀí½â·½Ê½µÄʵ¼ÊÒâÒå»ù±¾Ïàͬ¡£

Ò»¸öÒ³³£³£×î³õ´¦ÓÚÔÚÏß»ò»î¶¯×´Ì¬¡£ÔÚÏßʱ£¬Ò³³£³£¹ØÁªÓÚij´¦µÄÒ³±í¡£ ÐéÄâÄÚ´æÏµÍ³Í¨¹ýɨÃèÔÚÒ»¸ö½Ï»îÔ¾µÄÒ³¶ÓÁÐ(LRU)È·¶¨Ò³µÄÄêÁ䣬 ÒԱ㽫ËûÃÇÒÆµ½Ò»¸ö½Ï²»»îÔ¾µÄÒ³¶ÓÁÐÖС£ ÒÆ¶¯µ½»º´æÖеÄÒ³ÒÀÈ»ÓëÒ»¸öVM¶ÔÏó¹ØÁª£¬µ«±»×÷ΪÁ¢¼´ÔÙÓõĺòÑ¡¡£ ÔÚ×ÔÓɶÔÁÐÖеÄÒ³ÊÇÕæÕýδ±»Ê¹Óõġ£FreeBSD¾¡Á¿²»½«Ò³·ÅÔÚ×ÔÓɶÓÁÐÖУ¬ µ«ÊDZØÐë±£³ÖÒ»¶¨ÊýÁ¿µÄ×ÔÓÉÒ³£¬ÒÔ±ãÏìÓ¦ÖжÏʱ·ÖÅä¡£

¡¡¡¡Èç¹ûÒ»¸ö½ø³ÌÊÔͼ·ÃÎÊÒ»¸ö²»ÔÚÒ³±íÖжøÔÚijһ¶ÓÁÐÖеÄÒ³ (ÀýÈçÈ¥»î¶ÓÁлò»º´æ¶ÓÁÐ)£¬Ò»¸öÏà¶ÔºÄ·Ñ×ÊÔ´ÉÙµÄÒ³´íÎó·¢Éú£¬ µ¼ÖÂÒ³±»Öؼ¤»î¡£Èç¹ûÒ³¸ù±¾²»´æÔÚÓÚϵͳÄÚ´æÖ®ÖУ¬½ø³Ì±ØÐë±»×èÈû£¬ ´Ëʱҳ±»´Ó´ÅÅÌÖÐÔØÈë¡£

ÒëÕß×¢: IntelµÈ³§É̵ÄCPU¹¤×÷ÔÚ±£»¤Ä£Ê½Ê±£¬¿ÉÓÃÀ´ÊµÏÖÐéÄâÄÚ´æ¡£ µ±Ñ°Ö·µÄµØÖ·¿Õ¼ä¶ÔÓ¦×ÅÕæÊµÄÚ´æÊ±£¬ÔòÕý³£¶Áд£» µ±Ñ°Ö·µÄµØÖ·¿Õ¼äûÓжÔÓ¦µÄÕæÊµÄÚ´æÊ±£¬CPU»á²úÉúÒ»¸ö¡°´íÎó¡±£¬ ֪ͨ²Ù×÷ϵͳÓë´ÅÅ̵ÈÉ豸½øÐн»»»£¬¶ÁѰַÔòµ÷Èë´æ´¢ÄÚÈÝ£¬ дѰַÔòд³ö´æ´¢ÄÚÈÝ¡£Õâ¸ö¡°´íÎó¡± ²¢·Ç²Ù×÷ϵͳ»òÓ¦ÓóÌÐò¿ª·¢ÈËÔ±·¸ÏµĴíÎó£¬ ¾¡¹ÜÔÚCPUÓ²¼þʵÏÖÖÐÕâÓëÓ¦ÓóÌÐò»ò²Ù×÷ϵͳÄں˱ÀÀ£µÄ´íÎóµÄ·¢Éú»úÖÆÏàͬ¡£ ²Î¼ûIntelµÄCPU±£»¤Ä£Ê½¿ª·¢Êֲᡣ

¡¡¡¡FreeBSD¶¯Ì¬µÄµ÷ÕûÒ³¶ÓÁУ¬ÊÔͼ½«¸÷¸ö¶ÓÁÐÖеÄÒ³Êýά»¤ÔÚÒ»¸öÊʵ±µÄ±ÈÀýÉÏ£¬ ͬʱ¹ÜÀí³ÌÐò±ÀÀ£µÄÒÑÇåÀíºÍδÇåÀíÒ³¡£ÖØÐÂÆ½ºâµÄ±ÈÀýÊýÖµ¾ö¶¨ÓÚϵͳÄÚ´æµÄ¸ºµ£¡£ ÕâÖÖÖØÐÂÆ½ºâÓÉpageoutÊØ»¤½ø³ÌʵÏÖ£¬°üÀ¨ÇåÀíδÇåÀíÒ³(ÓëËûÃǵĺ󱸴洢ͬ²½)¡¢ ¼àÊÓÒ³±»ÒýÓõĻîÔ¾³Ì¶È (ÖØÖÃËüÃÇÔÚLRU¶ÓÁÐÖеÄλÖûòÔÚ²»Í¬»îÔ¾³Ì¶ÈµÄÒ³¶ÓÁмäÒÆ¶¯)¡¢ µ±±ÈÀý²»Æ½ºâʱÔÚ¶ÓÁмäÇ¨ÒÆÒ³£¬Èç´ËµÈµÈ¡£ FreeBSDµÄVMϵͳ»á½«Öؼ¤»îÒ³¶ø²úÉúµÄ´íÎóƵÂʵ÷µÍµ½Ò»¸öºÏÀíµÄÊýÖµ£¬ ÓÉ´ËÈ·¶¨Ä³Ò»Ò³»îÔ¾/ÏÐÖõÄʵ¼Ê³Ì¶È¡£ Õâ¿ÉÒÔΪ¸üºÃµÄ¾ö¶¨ºÎʱÇåÀí/·ÖÅäÒ»¸öÒ³×ö³ö¾ö²ß¡£


7.2 ͳһµÄ»º´æÐÅÏ¢½á¹¹Ì婤©¤vm_object_t

¡¡¡¡FreeBSDʵÏÖÁËͳһµÄ¡°ÐéÄâÄÚ´æ¶ÔÏó¡±(VM¶ÔÏó)µÄÉè¼ÆË¼Ïë¡£ VM¶ÔÏó¿ÉÒÔÓë¸÷ÖÖÀàÐ͵ÄÄÚ´æÊ¹Ó÷½Ê½Ïà½áºÏ©¤©¤Ö±½ÓʹÓÃ(unbacked)¡¢ ½»»»(swap)¡¢ÎïÀíÉ豸¡¢Îļþ¡£ ÓÉÓÚÎļþϵͳʹÓÃÏàͬµÄVM¶ÔÏó¹ÜÀíºËÄÚÊý¾Ý©¤©¤ÎļþµÄ»º´æ£¬ ËùÒÔÕâЩ»º´æµÄ½á¹¹Ò²ÊÇͳһµÄ¡£

¡¡¡¡VM¶ÔÏó¿ÉÒÔ±»Ó°¸´ÖÆ(shadowed)¡£ ËüÃÇ¿ÉÒÔ±»¶Ñ·Åµ½ÆäËüÀà±ðVM¶ÔÏó¶ÑÕ»µÄ¶¥¶Ë¡£ÀýÈ磬¿ÉÒÔÓÐÒ»¸ö½»»»VM¶ÔÏó£¬ ·ÅÖÃÔÚÎļþVM¶ÔÏó¶ÑÕ»µÄ¶¥¶Ë£¬ÒÔʵÏÖMAP_PRIVATEµÄmmap()²Ù×÷¡£ ÕâÑùµÄÈëÕ»²Ù×÷Ò²¿ÉÒÔÓÃÀ´ÊµÏÖ¸÷ÖÖ¸÷ÑùµÄ¹²ÏíÌØÐÔ£¬ °üÀ¨Ð´Èëʱ¸´ÖÆ(copy-on-write£¬ÓÃÓÚÈÕÖ¾Îļþϵͳ)£¬ÒÔÅÉÉú³öµØÖ·¿Õ¼ä¡£

¡¡¡¡Ó¦µ±×¢Ò⣬һ¸övm_page_t ½á¹¹ÌåÔÚÈÎÒ»¸öʱ¿ÌÖ»ÄÜÓëÒ»¸öVM¶ÔÏóÏà¹ØÁª¡£ VM¶ÔÏóÓ°¸´±¾¿ÉÒÔʵÏÖ¿çʵÀýµÄ¹²ÏíÏàͬµÄÒ³¡£


7.3 ÎļþϵͳÊäÈë/Êä³ö©¤©¤buf½á¹¹Ìå

¡¡¡¡vnode VM¶ÔÏ󣬱ÈÈçÎļþVM¶ÔÏó£¬Ò»°ãÐèҪά»¤ËüÃÇ×Ô¼ºµÄÇåÀí(clean)/ δÇåÀí(dirty)ÐÅÏ¢£¬¶ø²»ÒÀÀµÓÚÎļþϵͳµÄÇåÀí/δÇåÀíά»¤¡£ ÀýÈ磬µ±VMϵͳҪͬ²½Ò»¸öÎïÀíÒ³ºÍÆä¶ÔÓ¦µÄʵ¼Ê´æ´¢Æ÷£¬ VMϵͳ¾ÍÐèÒªÔÚдÈ뵽ʵ¼Ê´æ´¢Æ÷ǰ½«¸ÃÒ³±ê¼ÇΪÒÑÇåÀí¡£ ÁíÍ⣬ÎļþϵͳҪÄܹ»½«Îļþ»òÎļþÔªÊý¾ÝµÄ¸÷²¿·ÖÓ³Éäµ½ÄÚºËÐéÄâÄÚ´æ (KVM)ÖÐÒÔ±ã²Ù×÷¡£

¡¡¡¡ÓÃÀ´½øÐÐÕâЩ¹ÜÀíµÄʵÌå¾ÍÊÇÖÚËùÖÜÖªµÄÎļþϵͳ»º´æ£¬ struct buf»òbp¡£ µ±ÎļþϵͳÐèÒª¶ÔÒ»¸öVM¶ÔÏóµÄÒ»²¿·Ö²Ù×÷ʱ£¬ Ëü³£»á½«Õâ¸ö¶ÔÏóµÄÕⲿ·ÖÓ³Éäµ½struct buf£¬ ²¢ÇÒ½«struct bufÖÐÒ³Ó³Éäµ½ÄÚºËÐéÄâÄÚ´æ(KVM)ÖС£ ͬÑùµÄ£¬´ÅÅÌÊäÈë/Êä³öͨ³£ÒªÏȽ«VM¶ÔÏóµÄ¸÷²¿·ÖÓ³Éäµ½buf½á¹¹ÌåÖУ¬ È»ºó¶Ôbuf½á¹¹Ìå½øÐÐÊäÈë/Êä³ö²Ù×÷¡£ ϲãµÄvm_page_tÔÚÊäÈë/Êä³öÆÚ¼äͨ³£±»±ê¼ÇΪ¡°Ã¦¡±¡£ Îļþϵͳ»º´æÒ²»á¡°Ã¦¡±£¬Õâ¶ÔÓÚÎļþϵͳÇý¶¯³ÌÐò·Ç³£ÓÐÓ㬠¶ÔÎļþϵͳ»º´æ²Ù×÷±È¶ÔVMÕæÊµÒ³(hard)²Ù×÷¸üºÃ¡£

¡¡¡¡FreeBSD±£ÁôÒ»¶¨ÊýÁ¿µÄÄÚºËÐéÄâÄÚ´æÀ´´æ·Åstruct bufµÄÓ³É䣬 µ«ÊÇÕâЩbuf½á¹¹ÌåÓ¦¸ÃÊDZ»ÇåÀí¹ýµÄ¡£ÕâЩÄÚºËÐéÄâÄÚ´æ½öÓÃÀ´´æ·ÅÓ³É䣬 ²¢²»ÏÞÖÆ»º´æÊý¾ÝµÄÄÜÁ¦¡£ÑϸñµÄ˵£¬ÎïÀíÊý¾Ý»º´æÊÇ vm_page_tµÄÒ»¸ö¹¦ÄÜ£¬²»ÊÇÎļþϵͳ»º´æµÄ¹¦ÄÜ¡£ È»¶ø£¬ÓÉÓÚÎļþϵͳ»º´æ±»ÓÃÀ´´¦ÀíÊäÈë/Êä³ö£¬ ËûÃǹÌÓеÄÏÞÖÆÁËͬʱ½øÐÐÊäÈë/Êä³ö¿ÉÄܵÄÊýÁ¿¡£ µ«ÊÇ£¬ÓÉÓÚͨ³£ÓÐÊýǧÎļþϵͳ»º´æ¿É¹©Ê¹Óã¬ËùÒÔÕâ²¢²»»áÔì³ÉÎÊÌâ¡£


7.4 Ó³ÉäÒ³±í©¤©¤vm_map_t, vm_entry_t

¡¡¡¡FreeBSD½«ÎïÀíÒ³±í½á¹¹´ÓVMϵͳÖзÖÀëÁ˳öÀ´¡£¸÷½ø³ÌµÄËùÓÐÒ³±í¿ÉÒÔÍÑÀë½ø³Ì (on the fly)ÖØ½¨£¬²¢ÇÒͨ³£±»ÈÏΪÊÇÒ»´ÎÐԵġ£ÌØÊâµÄÒ³±í£¬ÈçÄÚºËÐéÄâÄÚ´æ(KVM)£¬ ³£³£ÊDZ»ÓÀ¾ÃÐÔÔ¤·ÖÅäµÄ£»ÕâЩҳ±í²»ÊÇÒ»´ÎÐԵġ£

¡¡¡¡FreeBSDͨ¹ývm_map_tºÍvm_entry_t ½á¹¹½«ÐéÄâÄÚ´æÖÐvm_objectsµÄ¸÷µØÖ··¶Î§²¿·Ö¹ØÁªÆðÀ´¡£ Ò³±í±»Ö±½ÓµÄ´Ó vm_map_t/vm_entry_t/vm_object_t ÖÐÓвã´ÎµÄºÏ³É³öÀ´¡£ÕâÀïÐèÒªÖØÉêһϣ¬ÎÒÔøÌáµ½µÄ¡°ÎïÀíÒ³½öÖ±½ÓÓë vm_objectÏà¹ØÁª¡±²¢²»ºÜÕýÈ·¡£vm_page_t Ò²±»»á±»Á´½Óµ½ÕýÔÚÓëÖ®Ïà¹ØÁªµÄÒ³±íÖС£µ±Ò³±í±»µ÷ÓÃʱ£¬ Ò»¸övm_page_t½á¹¹Ìå¿ÉÒÔ±»Á´½Óµ½¼¸¸öpmaps¡£ È»¶ø£¬ÓÉÓÚÓÐÁ˲ã´ÎµÄ¹ØÁª£¬Òò´ËÔÚ¶ÔÏóÖÐËùÓжÔͬһҳµÄÒýÓûáÒýÓÃͬһ vm_page_t½á¹¹Ì壬ÕâÑù¾ÍʵÏÖÁË¿çÇøÓò(board)µÄ»º´æµÄͳһ¡£


7.5 KVM´æ´¢Ó³Éä

¡¡¡¡FreeBSDʹÓÃKVM´æ·Å¸÷ÖÖ¸÷ÑùµÄÄں˽ṹÌå¡£ÔÚKVMÖÐ×î´óµÄµ¥¸öʵÌåÊÇÎļþϵͳ»º´æ¡£ ÄÇÊÇÓëstruct bufʵÌåÓйصÄÓ³Éä¡£

¡¡¡¡²»ÏñLinux£¬FreeBSD²»½«ËùÓеÄÎïÀíÄÚ´æÓ³Éäµ½KVMÖС£ ÕâÒâζ×ÅFreeBSD¿ÉÒÔÔÚ32λƽ̨ÉϹÜÀí³¬¹ý4GBµÄÄÚ´æÅäÖá£ÊÂʵÉÏ£¬ Èç¹ûmmu(ÒëÕß×¢£º¿ÉÄÜÊÇÖ¸¡°ÄÚ´æ¹ÜÀíµ¥Ôª¡±£¬¡°Memory Management Unit¡±) ÓÐ×ã¹»µÄÄÜÁ¦£¬FreeBSDÀíÂÛÉÏ¿ÉÒÔÔÚ32λƽ̨ÉϹÜÀí×î¶à8TBµÄÄÚ´æÅäÖᣠȻ¶ø£¬´ó¶àÊý32ƽֻ̨ÄÜÓ³Éä4GBÄڴ棬ÕâÖ»ÄÜÊÇÒ»¸öÕùÂ۵㡣

¡¡¡¡Óм¸ÖÖ»úÖÆ¿ÉÒÔ¹ÜÀíKVM¡£¹ÜÀíKVMµÄÖ÷Òª»úÖÆÊÇÇøÓò·ÖÅäÆ÷ (zone allocator)¡£ÇøÓò·ÖÅäÆ÷¹ÜÀí×ÅKVMµÄ´ó¿é£¬ÔÙ½«´ó¿éÇзÖΪºã¶¨´óСµÄС¿é£¬ ÒԱ㰴ÕÕijһÖÖÀàÐ͵ĽṹÌå·ÖÅä¡£Äã¿ÉÒÔʹÓÃÃüÁîvmstat -m Ò»ÀÀµ±Ç°KVM·ÖÇøÊ¹ÓÃÇé¿ö¡£


7.6 µ÷ÕûFreeBSDµÄÐéÄâÄÚ´æÏµÍ³

¡¡¡¡¿ª·¢ÕßµÄЭͬŬÁ¦Ê¹µÃFreeBSD¿ÉÒÔ×ÔÐж¯Ì¬µ÷ÕûÄںˡ£Ò»°ãÀ´Ëµ£¬ ³ýÁËÄÚºËÅäÖÃÑ¡ÏîmaxusersºÍNMBCLUSTERS£¬ Äã²»ÐèÒª×öÈκÎÔÓÂÒµÄÊÂÇé¡£ÕâЩÄں˱àÒëÅäÖÃÑ¡Ïî(Ò»°ã)±»Ö¸¶¨ÔÚ /usr/src/sys/i386/conf/CONFIG_FILE Ö®ÖС£ËùÓпÉÓÃÄÚºËÅäÖÃÑ¡ÏîµÄÃèÊö¿ÉÔÚ /usr/src/sys/i386/conf/LINTÖÐÕÒµ½¡£

¡¡¡¡ÔÚÒ»¸ö´óϵͳµÄÅäÖÃÖУ¬Äã¿ÉÄÜÐèÒªÔö¼ÓmaxusersµÄÖµ¡£ ÊýÖµ·¶Î§Í¨³£ÔÚ10µ½128¡£×¢Ò⣬¹ý¶ÈÔö¼Ómaxusers µÄÖµ¿ÉÄܵ¼ÖÂϵͳ´Óʵ¼Ê¿ÉÓõÄKVMÖÐÒç³ö£¬´Ó¶øÒýÆðÎÞ·¨Ô¤ÖªµÄ²Ù×÷¡£ ×îºÃ½«maxusersÉèΪһ¸öºÏÀíµÄÊýÖµ£¬²¢ÇÒÌí¼ÓÆäËüÑ¡Ï ÈçNMBCLUSTERS£¬À´Ôö¼ÓÌØ¶¨µÄ×ÊÔ´¡£

¡¡¡¡Èç¹ûÄãµÄϵͳҪ±»ÖظººÉµÄʹÓÃÍøÂ磬ÄãÐèÒªÔö¼Ó NMBCLUSTERSµÄÖµ¡£ÊýÖµ·¶Î§Í¨³£ÔÚ1024µ½4096¡£

¡¡¡¡NBUFÒ²ÊÇ´«Í³µÄ¹æ»®ÏµÍ³µÄ²ÎÊý¡£ Õâ¸ö²ÎÊý¾ö¶¨ÏµÍ³¿ÉÓÃÀ´Ó³ÉäÎļþϵͳÊäÈë/Êä³ö»º´æµÄKVMµÄÊýÁ¿¡£ ×¢Ò⣺Õâ¸ö²ÎÊýÓëͳһµÄ»º´æÃ»ÓÐÈκιØÏµ¡£Õâ¸ö²ÎÊý¿ÉÔÚ3.0-CURRENT ºÍÒÔºóµÄÄÚºËÖб»¶¯Ì¬µÄµ÷½Ú£¬Í¨³£²»Ó¦µ±±»ÊÖ¶¯µÄµ÷½Ú¡£ ÎÒÃÇÍÆ¼öÄã²»ÒªÖ¸¶¨NBUF¡£ ÈÃϵͳ×ÔÐÐÈ·¶¨Ëü¡£Ì«Ð¡µÄÖµ»áµ¼Ö·dz£µÍЧµÄÎļþϵͳ²Ù×÷£» Ì«´óµÄÖµ»áʹÓÃÒ³¶ÓÁÐÖÐȱÉÙÒ³Ãæ£¬¶ø´óÁ¿µÄÒ³´¦ÓÚÔÚÏß״̬¡£

¡¡¡¡È±Ê¡Çé¿öÏ£¬FreeBSDÄں˱àÒëʱÊDz»±»ÓÅ»¯µÄ¡£ Äã¿ÉÒÔÔÚÄÚºËÅäÖÃÎļþÖÐÓÃmakeoptions Ö¸¶¨ÅÅ´í(debugging)ºÍÓÅ»¯±êÖ¾¡£×¢Ò⣬ÄãÒ»°ã²»Ó¦Ê¹ÓÃ-g£¬ ³ý·ÇÄãÄܹ»Ó¦¸¶Óɴ˲úÉúµÄ´óÄÚºË(µäÐ͵ÄÊÇ7MB»ò¸ü¶à)¡£

makeoptions      DEBUG="-g"
makeoptions      COPTFLAGS="-O -pipe"

¡¡¡¡SysctlÌṩÁËÔÚÔËÐÐʱµ÷ÕûÄں˵ķ½Ê½¡£Äãͨ³£²»ÐèÒªÖ¸¶¨ÈκÎsysctl±äÁ¿£¬ ÓÈÆäÊÇÓëVMÏà¹ØµÄÄÇЩ±äÁ¿¡£

¡¡¡¡ÔËÐÐʱVMºÍϵͳµ÷ÕûµÄÓ°ÏìÏà¶ÔÖ±½ÓһЩ¡£ Ê×ÏÈ£¬Ó¦µ±¾¡¿ÉÄÜÔÚUFS/FFSÎļþϵͳÉÏʹÓÃSoft Updates¡£ ÔÚ/usr/src/sys/ufs/ffs/README.softupdates ÀïÓйØÓÚÈçºÎÅäÖõÄָʾ¡£

¡¡¡¡Æä´Î£¬Ó¦µ±ÅäÖÃ×ã¹»¶àµÄ½»»»¿Õ¼ä¡£ ÄãÓ¦µ±ÔÚÿ¸öÎïÀí´ÅÅÌÉÏÅäÖÃÒ»¸ö½»»»·ÖÇø£¬×î¶à4¸ö£¬ ÉõÖÁÔÚÄãµÄ¡°¹¤×÷¡±´ÅÅÌÉÏ¡£ÄãÓ¦µ±ÓÐÖÁÉÙ2±¶ÓÚÖ÷ÄÚ´æµÄ½»»»¿Õ¼ä£» ¼ÙÈçÄãûÓÐ×ã¹»ÄÚ´æµÄ»°£¬½»»»·ÖÇø»¹Ó¦¸ü¶à¡£ ÄãÒ²Ó¦µ±°´ÕÕÄãÆÚÍûÖеÄ×î´óÄÚ´æÅäÖþö¶¨½»»»·ÖÇøµÄ´óС£¬ ÕâÑùÒÔºó¾Í²»ÔÙÐèÒªÖØÐ¸ø´ÅÅÌ·ÖÇøÁË¡£ Èç¹ûÄã´¦Àíϵͳ±ÀÀ£ºóµÄÄÚ´æÇãµ¹(crash dump)£¬ µÚÒ»¸ö½»»»·ÖÇø±ØÐëÖÁÉÙÓëÖ÷ÄÚ´æÒ»Ñù´ó£¬ /var/crash±ØÐëÓÐ×ã¹»µÄ¿Õ¼äÀ´³Ð×°Çãµ¹¡£

¡¡¡¡NFSÉϵĽ»»»·ÖÇø¿ÉÒԺܺõı»4.X»òºóÀ´µÄϵͳʹÓ㬠µ«ÊÇÄã±ØÐëÃ÷°×NFS·þÎñÆ÷½«Òª¾­ÊÜÒ³×°ÔØ²Ù×÷ºÜÇ¿µÄ³å»÷¡£


µÚ8Õ ¡¡SMPng Éè¼ÆÎĵµ

д×÷£ºJohn Baldwin ºÍ Robert Watson. °æÈ¨ © 2002, 2004, 2005 John Baldwin, Robert Watson·­Ò룺Àî öÎ.

8.1 Ð÷ÂÛ

¡¡¡¡Õâ·ÝÎĵµ¶ÔĿǰ SMPng ¼Ü¹¹µÄÉè¼ÆÓëʵÏÖ½øÐÐÁ˽éÉÜ¡£ ËüÊ×ÏȽéÉÜÁË»ù±¾µÄÔ­ÓïºÍÏà¹Ø¹¤¾ß£¬ ÆäºóÊǹØÓÚ FreeBSD Äں˵Äͬ²½ÓëÖ´ÐÐÄ£ÐÍ£¬ ½ÓÏÂÀ´ÌÖÂÛÁ˾ßÌåϵͳÖеÄËø²ßÂÔ£¬ ²¢ÃèÊöÁËÔÚ¸÷¸ö×ÓϵͳÖÐÒýÈëϸÁ£¶ÈµÄͬ²½ºÍʵÏÖ²¢Ðл¯µÄ²½Ö裬 ×îºóÊÇÏêϸµÄʵÏÖ˵Ã÷£¬ ÓÃÒÔ½âÊÍ×î³õ×ö³öijЩÉè¼Æ¾ö²ßµÄ¶¯»ú£¬ ²¢Ê¹¶ÁÕßÁ˽âʹÓÃÌØ¶¨µÄÔ­ÓïËù¿ÉÄܲúÉúµÄÖØ´óÓ°Ïì¡£

¡¡¡¡Õâ·ÝÎĵµÈÔÔÚ׫дµ±ÖУ¬ ²¢½«²»¶Ï¸üÐÂÒÔ·´Ó³Óë SMPng ÏîÄ¿ÓйصÄ×îÐÂÉè¼ÆÓëʵÏÖµÄÇé¿ö¡£ ÆäÖÐÓÐÐí¶àС½ÚĿǰ»¹Ö»ÊÇÌá¸Ù£¬ µ«ÎÒÃÇ»áÖð½¥ÎªÆä³äʵÄÚÈÝ¡£ ¹ØÓÚÕâ·ÝÎĵµµÄ¸üкͽ¨Ò飬 Çë·¢¸øÎĵµ±à¼­¡£

¡¡¡¡SMPng µÄÄ¿±êÊÇʹÄÚºËÄܹ»²¢·¢Ö´ÐС£ »ù±¾ÉÏ£¬ ÄÚºËÊÇÒ»¸öºÜ´ó¶ø¸´ÔӵijÌÐò¡£ ÒªÈÃÄÚºËÄܹ»¶àÏ̵߳ØÖ´ÐУ¬ ÎÒÃÇÐèҪʹÓÃijЩÆäËü¶àÏ̳߳ÌÐòÔÚʵÏÖʱËùÓõ½µÄ¹¤¾ß£¬ Õâ°üÀ¨»¥³âÌå(mutex)¡¢ ¹²Ïí/ÅÅËûËø(shared/exclusive lock)¡¢ ÐźÅÁ¿(semaphores) ºÍÌõ¼þ±äÁ¿(condition variable)¡£ Èç¹ûÏ£ÍûÁ˽âËüÃÇÒÔ¼°ÆäËü SMP ÊõÓ Çë²ÎÔı¾ÎÄµÄ ÊõÓï±í Ò»½Ú¡£


8.2 »ù±¾¹¤¾ßÓëÉÏËøµÄ»ù´¡ÖªÊ¶

8.2.1 Ô­×Ó²Ù×÷Ö¸ÁîºÍÄÚ´æÕ¤

¡¡¡¡¹ØÓÚÄÚ´æÕ¤ºÍÔ­×Ó²Ù×÷Ö¸ÁîÒѾ­Óкܶà½éÉܲÄÁÏ£¬ Òò´ËÕâÒ»½Ú²¢²»´òËã¶ÔÆä½øÐÐÏ꾡µÄ½éÉÜ¡£ ¼ò¶øÑÔÖ®£¬ Èç¹ûÓжÔijһ±äÁ¿ÉÏÐ´Ëø£¬ ¾Í²»ÄÜÔÚ²»»ñµÃÏàÓ¦µÄËøÊ±¶ÔÆä½øÐжÁÈ¡²Ù×÷¡£ Ò²¾ÍÊÇ˵£¬ ÄÚ´æÕ¤µÄ×÷ÓÃÔÚÓÚ±£Ö¤ÄÚ´æ²Ù×÷µÄÏà¶Ô˳Ðò£¬ µ«²¢²»±£Ö¤ÄÚ´æ²Ù×÷µÄÑϸñʱÐò¡£ »»ÑÔÖ®£¬ ÄÚ´æÕ¤²¢²»±£Ö¤ CPU ½«±¾µØ¿ìÈ¡»º´æ»ò´æ´¢»º³åµÄÄÚÈÝˢд»ØÄڴ棬 ¶øÊÇÔÚËøÊÍ·Åʱȷ±£ÆäËù±£»¤µÄÊý¾Ý£¬ ¶ÔÓÚÄÜ¿´µ½¸ÕÊͷŵÄÄǸöËøµÄ CPU »òÉ豸¿É¼û¡£ ³ÖÓÐÄÚ´æÕ¤µÄ CPU ¿ÉÒÔÔÚÆä¿ìÈ¡»º´æ»ò´æ´¢»º³åÖн«Êý¾Ý±£³ÖÆäËùÏ£ÍûµÄ¡¢ ÈÎÒⳤµÄʱ¼ä£¬ µ«Èç¹ûÆäËü CPU ÔÚͬһÊý¾ÝÔªÉÏÖ´ÐÐÔ­×Ó²Ù×÷£¬ ÔòµÚÒ»¸ö CPU ±ØÐë±£Ö¤£¬ ÆäËù¸üеÄÊý¾ÝÖµ£¬ ÒÔ¼°ÄÚ´æÕ¤ËùÒªÇóµÄÈÎºÎÆäËü²Ù×÷£¬ ¶ÔµÚ¶þ¸ö CPU ¿É¼û¡£

¡¡¡¡ÀýÈ磬 ¼ÙÉèÔÚÒ»¼òµ¥Ä£ÐÍÖУ¬ ÈÏΪÔÚÖ÷´æ (»òijһȫ¾Ö¿ìÈ¡»º´æ) ÖеÄÊý¾ÝÊǿɼûµÄ£¬ µ±Ä³Ò» CPU ÉÏ´¥·¢Ô­×Ó²Ù×÷ʱ£¬ ÆäËü CPU µÄ´æ´¢»º³åºÍ¿ìÈ¡»º´æ¾Í±ØÐë¶Ôͬһ¿ìÈ¡»º´æÏßÉϵÄÈ«²¿Ð´²Ù×÷£¬ ÒÔ¼°ÄÚ´æÕ¤Ö®ºóµÄÈ«²¿Î´Íê³É²Ù×÷½øÐÐˢд¡£

¡¡¡¡ÕâÑùÒ»À´£¬ ÔÚʹÓÃÓÉÔ­×Ó²Ù×÷±£»¤µÄÄڴ浥Ԫʱ¾ÍÐèÒªÌØ±ðСÐÄ¡£ ÀýÈ磬 ÔÚʵÏÖ sleep mutex ʱ£¬ ÎÒÃǾͱØÐëʹÓà atomic_cmpset ¶ø²»ÊÇ atomic_set À´´ò¿ª MTX_CONTESTED λ¡£ ÕâÑù×öµÄÔ­ÒòÊÇ£¬ ÎÒÃÇÐèÒª°Ñ mtx_lock µÄÖµ¶Áµ½Ä³¸ö±äÁ¿£¬ ²¢¾Ý´Ë½øÐоö²ß¡£ È»¶ø£¬ ÎÒÃǶÁµ½µÄÖµ¿ÉÄÜÊǹýʱµÄ£¬ Ò²¿ÉÄÜÔÚÎÒÃǽøÐоö²ßµÄ¹ý³ÌÖз¢Éú±ä»¯¡£ Òò´Ë£¬ µ±Ö´ÐÐ atomic_set ʱ£¬ ×îÖÕ¿ÉÄÜ»á¶ÔÁíÒ»Öµ½øÐÐÖÃ룬 ¶ø²»ÊÇÎÒÃǽøÐоö²ßµÄÄÇÒ»¸ö¡£ Õâ¾Í±ØÐëͨ¹ý atomic_cmpset À´±£Ö¤Ö»ÓÐÔÚÎÒÃǵľö²ßÒÀ¾ÝÊÇ×îеÄʱ£¬ ²Å¶ÔÏàÓ¦µÄ±äÁ¿½øÐÐÖÃλ¡£

¡¡¡¡×îºó£¬ Ô­×Ó²Ù×÷Ö»ÔÊÐíÒ»´Î¸üлò¶ÁÒ»¸öÄÚ´æµ¥Ôª¡£ ÐèÒªÔ­×ӵظüжà¸öµ¥ÔªÊ±£¬ ¾Í±ØÐëʹÓÃËøÀ´´úÌæËüÁË¡£ ÀýÈ磬 Èç¹ûÐèÒª¸üÐÂÁ½¸öÏ໥¹ØÁªµÄ¼ÆÊýÆ÷ʱ£¬ ¾Í±ØÐëʹÓÃËø£¬ ¶ø²»ÊÇÁ½´Îµ¥¶ÀµÄÔ­×Ó²Ù×÷ÁË¡£


8.2.2 ¶ÁËøÓëÐ´Ëø

¡¡¡¡¶ÁËø²¢²»ÐèÒªÏñÐ´ËøÄÇÑùÇ¿¡£ ÕâÁ½ÖÖÀàÐ͵ÄËø£¬ ¶¼ÐèҪȷ±£Í¨¹ýËüÃÇ·ÃÎʵIJ»ÊǹýʱµÄÊý¾Ý¡£ È»¶ø£¬ Ö»ÓÐд²Ù×÷±ØÐëÊÇÅÅËûµÄ£¬ ¶ø¶à¸öÏß³ÌÔò¿ÉÒÔ°²È«µØ¶Áͬһ±äÁ¿µÄÖµ¡£ ʹÓò»Í¬ÀàÐ͵ÄËøÓÃÓÚ¶ÁºÍд²Ù×÷ÓÐÐí¶à¸÷×Ô²»Í¬µÄʵÏÖ·½Ê½¡£

¡¡¡¡µÚÒ»ÖÖ·½·¨ÊÇÓà sx Ëø£¬ Ëü¿ÉÒÔÓÃÓÚʵÏÖдʱʹÓõÄÅÅËûËø£¬ ¶ø¶ÁʱÔò×÷Ϊ¹²ÏíËø¡£ ÕâÖÖ·½·¨Ê®·Ö¼òµ¥Ã÷ÁË¡£

¡¡¡¡µÚ¶þÖÖ·½·¨ÔòÂÔÏÔ»Þɬ¡£ ¿ÉÒÔÓöà¸öËøÀ´±£»¤Í¬Ò»Êý¾ÝÔª¡£ ¶Áʱ£¬ Ö»ÐèËøÆäÖеÄÒ»¸ö¶ÁËø¼´¿É¡£ È»¶ø£¬ Èç¹ûҪдÊý¾ÝµÄ»°£¬ ÔòÐèÒªÊ×ÏÈÉÏËùÓеÄÐ´Ëø¡£ Õâ»á´ó´óÌá¸ßд²Ù×÷µÄ´ú¼Û£¬ µ«µ±¿ÉÄÜÒÔ¶àÖÖ·½Ê½·ÃÎÊÊý¾Ýʱȴ¿ÉÄܷdz£ÓÐÓᣠÀýÈ磬 ¸¸½ø³ÌÖ¸ÕëÊÇͬʱÊÜ proctree_lock sx ËøºÍ½ø³Ì mutex ±£»¤µÄ¡£ ÔÚֻϣÍû¼ì²éÒÑËø½ø³ÌµÄ¸¸½ø³Ìʱ£¬ Óà proc Ëø¸üΪ·½±ã¡£ µ«ÊÇ£¬ ÆäËüһЩµØ·½£¬ ÀýÈç inferior ÕâÀàÐèҪͨ¹ý¸¸Ö¸ÕëÔÚ½ø³ÌÊ÷ÉϽøÐÐËÑË÷£¬ ²¢¶Ôÿ¸ö½ø³ÌÉÏËøµÄµØ·½¾Í²»ÄÜÕâÑù×öÁË£¬ ·ñÔò£¬ ½«ÎÞ·¨±£Ö¤ÔÚ¶ÔÎÒÃÇËù»ñµÃµÄ½á¹ûÖ´ÐвÙ×÷ʱ£¬ ֮ǰ¼ì²éʱµÄ×´¿öÒÀ¾ÉÓÐЧ¡£


8.2.3 ÉÏËø×´Ì¬ºÍ½á¹û

¡¡¡¡Èç¹ûÄúÐèҪʹÓÃËøÀ´±£³ÖËù¼ì²é±äÁ¿µÄ״̬£¬ ²¢¾Ý´ËÖ´ÐÐijЩ²Ù×÷ʱ£¬ ÊDz»Äܽö½öÔÚ¶Á±äÁ¿Ö®Ç°¶ÔÆäÉÏËø£¬ ²¢ÔÚÖ´ÐвÙ×÷֮ǰ½âËøµÄ¡£ ¹ýÔç½âËø½«Ê¹±äÁ¿Ôٴοɱ䣬 Õâ¿ÉÄܻᵼÖÂ֮ǰËù×öµÄ¾ö²ßʧЧ¡£ Òò´Ë£¬ ÔÚËù×ö¼ì²âÒý·¢µÄ¶¯×÷½áÊøÖ®Ç°£¬ ±ØÐë¼ÌÐø±£³ÖÉÏËø×´Ì¬¡£


8.3 ¼Ü¹¹ÓëÉè¼Æ¸ÅÀÀ

8.3.1 ¶ÔÖжϵĴ¦Àí

¡¡¡¡ÓëÐí¶àÆäËü¶àÏß³Ì UNIX ÄÚºËËù²ÉÈ¡µÄģʽÀàËÆ£¬ FreeBSD »á¸³ÓèÖжϴ¦Àí³ÌÐò¶ÀÁ¢µÄÏß³ÌÉÏÏÂÎÄ£¬ ÕâÑù×öÄܹ»ÈÃÖжÏÏß³ÌÔÚÓöµ½ËøÊ±×èÈû¡£ µ«ÎªÁ˱ÜÃâ²»±ØÒªµÄÑÓ³Ù£¬ ÖжÏÏß³ÌÔÚÄÚºËÖУ¬ ÊÇÒÔʵʱÏ̵߳ÄÓÅÏȼ¶ÔËÐеġ£ Òò´Ë£¬ Öжϴ¦Àí³ÌÐò²»Ó¦Ö´Ðйý¾Ã£¬ ÒÔÃâ¶öËÀÆäËüÄÚºËÏ̡߳£ ´ËÍ⣬ ÓÉÓÚ¶à¸ö´¦Àí³ÌÐò¿ÉÒÔ·ÖÏíͬһÖжÏỊ̈߳¬ Öжϴ¦Àí³ÌÐò²»Ó¦ÐÝÃߣ¬ »òʹÓÿÉÄܵ¼ÖÂÐÝÃßµÄËø£¬ ÒÔ±ÜÃ⽫ÆäËüÖжϴ¦Àí³ÌÐò¶öËÀ¡£

¡¡¡¡Ä¿Ç°ÔÚ FreeBSD ÖеÄÖжÏÏß³ÌÊÇÖ¸ÖØÁ¿¼¶ÖжÏÏ̡߳£ ÕâÑù³ÆºôËüÃǵÄÔ­ÒòÔÚÓÚ£¬ תµ½ÖжÏÏß³ÌÐèÒªÖ´ÐÐÒ»´ÎÍêÕûµÄÉÏÏÂÎÄÇл»²Ù×÷¡£ ÔÚ×î³õµÄʵÏÖÖУ¬ Äں˲»ÔÊÐíÇÀÕ¼£¬ Òò´ËÖжÏÔÚ´ò¶ÏÄÚºËÏß³Ì֮ǰ£¬ ±ØÐëµÈ´ýÄÚºËÏß³Ì×èÈû»ò·µ»ØÓû§Ì¬Ö®ºó²ÅÄÜÖ´ÐС£

¡¡¡¡ÎªÁ˽â¾öÏìӦʱ¼äÎÊÌ⣬ FreeBSD ÄÚºËÏÖÔÚ²ÉÓÃÁËÇÀռʽµ÷¶È²ßÂÔ¡£ Ŀǰ£¬ Ö»ÓÐÊÍ·ÅÐÝÃß mutex »ò·¢ÉúÖжÏʱ²ÅÄÜÇÀ¶ÏÄÚºËỊ̈߳¬ µ«×îÖÕÄ¿±êÊÇÔÚ FreeBSD ÉÏʵÏÖÏÂÃæËùÃèÊöµÄÈ«ÇÀռʽµ÷¶È²ßÂÔ¡£

¡¡¡¡²¢·ÇËùÓеÄÖжϴ¦Àí³ÌÐò¶¼ÔÚ¶ÀÁ¢µÄÏß³ÌÉÏÏÂÎÄÖÐÖ´ÐС£ Ïà·´£¬ ijЩ´¦Àí³ÌÐò»áÖ±½ÓÔÚÖ÷ÖжÏÉÏÏÂÎÄÖÐÖ´ÐС£ ÕâЩÖжϴ¦Àí³ÌÐò£¬ ÏÖÔÚ±»´íÎóµØÃüÃûΪ ¡°¿ìËÙ¡± Öжϴ¦Àí³ÌÐò£¬ ÒòΪÔçÆÚ°æ±¾µÄÄÚºËÖÐʹÓÃÁË INTR_FAST ±êÖ¾À´±ê¼ÇÕâЩ´¦Àí³ÌÐò¡£ ĿǰֻÓÐʱÖÓÖжϺʹ®¿Ú I/O É豸ÖжϲÉÓÃÕâÒ»ÀàÐÍ¡£ ÓÉÓÚÕâЩ´¦Àí³ÌÐòûÓжÀÁ¢µÄÉÏÏÂÎÄ£¬ Òò¶øËüÃǶ¼²»ÄÜ»ñµÃ×èÈûÐÔËø£¬ Òò´ËÒ²¾ÍÖ»ÄÜʹÓÃ×ÔÐý mutex¡£

¡¡¡¡×îºó£¬ »¹ÓÐÒ»ÖÖ³ÆÎªÇáÁ¿¼¶ÉÏÏÂÎÄÇл»µÄÓÅ»¯£¬ ¿ÉÒÔÔÚ MD ´úÂëÖÐʹÓᣠÒòΪÖжÏÏ̶߳¼ÊÇÔÚÄÚºËÉÏÏÂÎÄÖÐÖ´Ðеģ¬ ËùÒÔËü¿ÉÒÔ½èÓÃÈÎÒâ½ø³ÌµÄ vmspace (ÐéÄâÄÚ´æµØÖ·¿Õ¼ä)¡£ Òò´Ë£¬ ÔÚÇáÁ¿¼¶ÉÏÏÂÎÄÇл»ÖУ¬ Çл»µ½ÖжÏÏ̲߳¢²»Çл»¶ÔÓ¦µÄ vmspace£¬ ¶øÊǽèÓñ»ÖжÏÏß³ÌµÄ vmspace¡£ Ϊȷ±£±»ÖжÏÏß³ÌµÄ vmspace ²»ÔÚÖжϴ¦Àí¹ý³ÌÖÐÏûʧ£¬ ±»ÖжÏÏß³ÌÔÚÖжÏÏ̲߳»ÔÙ½èÓÃÆä vmspace ֮ǰÊDz»ÔÊÐíÖ´Ðеġ£ ¸Õ²ÅÌáµ½µÄÇé¿ö¿ÉÄÜÔÚÖжÏÏß³Ì×èÈû»òÍê³Éʱ·¢Éú¡£ Èç¹ûÖжÏÏ̷߳¢Éú×èÈû£¬ ÔòËüÔٴνøÈë¿ÉÔËÐÐ״̬ʱ½«Ê¹ÓÃ×Ô¼ºµÄÉÏÏÂÎÄ£¬ ÕâÑùÒ»À´£¬ ¾Í¿ÉÒÔÊͷű»ÖжϵÄÏß³ÌÁË¡£

¡¡¡¡ÕâÖÖÓÅ»¯µÄ»µ´¦ÔÚÓÚËüÃǺÍÓ²¼þ½ôÃÜÏà¹Ø£¬ ¶øÇÒʵÏֱȽϸ´ÔÓ£¬ Òò´ËÖ»ÓÐÔÚÕâÑù×öÄÜ´øÀ´´ó·ùÐÔÄܸÄÉÆÊ±²ÅÓ¦²ÉÓᣠĿǰÕâÑù˵¿ÉÄÜ»¹ÎªÊ±¹ýÔ磬 ¶øÇÒÊÂʵÉÏ¿ÉÄܻᷴ¶øµ¼ÖÂÐÔÄÜϽµ£¬ ÒòΪ¼¸ºõËùÓеÄÖжϴ¦Àí³ÌÐò¶¼»áÁ¢¼´±»È«¾ÖËø (Giant) ×èÈû£¬ ¶øÕâÖÖ×èÈû½«½ø¶øÐèÒªÏß³ÌÐÞÕý¡£ ÁíÍ⣬ Mike Smith ÌáÒé²ÉÓÃÁíÒ»ÖÖ·½Ê½À´´¦ÀíÖжÏỊ̈߳º

  1. ÿ¸öÖжϴ¦Àí³ÌÐò·ÖΪÁ½²¿·Ö£¬ Ò»¸öÔÚÖ÷ÖжÏÉÏÏÂÎÄÖÐÔËÐеÄÖ÷Ìå (predicate) ºÍÒ»¸öÔÚ×Ô¼ºµÄÏß³ÌÉÏÏÂÎÄÖÐÖ´ÐеĴ¦Àí³ÌÐò (handler)¡£

  2. Èç¹ûÖжϴ¦Àí³ÌÐòÓµÓÐÖ÷Ì壬 Ôòµ±´¥·¢ÖжÏʱ£¬ Ö´ÐиÃÖ÷Ìå¡£ Èç¹ûÖ÷Ìå·µ»ØÕ棬 ÔòÈÏΪ¸ÃÖжϱ»´¦ÀíÍê±Ï£¬ Äں˴ÓÖжϷµ»Ø¡£ Èç¹ûÖ÷Ìå·µ»Ø¼Ù£¬ »òÕßÖжÏûÓÐÖ÷Ì壬 Ôòµ÷¶ÈÔËÐÐÏß³Ìʽ´¦Àí³ÌÐò¡£

¡¡¡¡ÔÚÕâһģʽÖÐÊʵ±µØ²ÉÓÃÇáÁ¿¼¶ÉÏÏÂÎÄÇл»¿ÉÄÜÊǷdz£¸´Ôӵġ£ ÒòΪÎÒÃÇ¿ÉÄÜ»áÏ£ÍûÔÚδÀ´¸Ä±äÕâһģʽ£¬ Òò´ËÏÖÔÚ×îºÃµÄ·½°¸£¬ Ó¦¸ÃÊÇÔÝÊ±ÍÆ³ÙÔÚÇáÁ¿¼¶ÉÏÏÂÎÄÇл»Ö®ÉϵŤ×÷£¬ ÒÔ±ã½øÒ»²½ÍêÉÆÖжϴ¦Àí¼Ü¹¹£¬ ËæºóÔÙ¿¼²ìÇáÁ¿¼¶ÉÏÏÂÎÄÇл»ÊÇ·ñÊÊÓá£


8.3.2 ÄÚºËÇÀÕ¼ÓëÁÙ½çÇø

8.3.2.1 ÄÚºËÇÀÕ¼¼ò½é

¡¡¡¡ÄÚºËÇÀÕ¼µÄ¸ÅÄîºÜ¼òµ¥£¬ Æä»ù±¾Ë¼ÏëÊÇ CPU ×ÜÓ¦Ö´ÐÐÓÅÏȼ¶×î¸ßµÄ¹¤×÷¡£ µ±È»£¬ ÖÁÉÙÔÚÀíÏëÇé¿öÏÂÊÇÕâÑù¡£ ÓÐЩʱºò£¬ ´ï³ÉÕâÒ»ÀíÏëµÄ´ú¼Û»áÊ®·Ö¸ß°º£¬ ÒÔÖÁÓÚÔÚÕâЩÇé¿öÏÂÇÀÕ¼»áµÃ²»³¥Ê§¡£

¡¡¡¡ÊµÏÖÍêÈ«µÄÄÚºËÇÀռʮ·Ö¼òµ¥£º ÔÚµ÷¶È½«ÒªÖ´ÐеÄÏ̲߳¢·ÅÈëÔËÐжÓÁÐʱ£¬ ¼ì²éËüµÄÓÅÏȼ¶ÊÇ·ñ¸ßÓÚĿǰÕýÔÚÖ´ÐеÄÏ̡߳£ Èç¹ûÊÇÕâÑùµÄ»°£¬ Ö´ÐÐÒ»´ÎÉÏÏÂÎÄÇл»²¢Á¢¼´¿ªÊ¼Ö´ÐиÃÏ̡߳£

¡¡¡¡¾¡¹ÜËøÄܹ»ÔÚÇÀռʱ±£»¤¶àÊýÊý¾Ý£¬ µ«Äں˲¢²»ÊÇ¿ÉÒÔ°²È«µØ´¦´¦ÇÀÕ¼µÄ¡£ ÀýÈ磬 Èç¹û³ÖÓÐ×ÔÐý mutex µÄÏ̱߳»ÇÀÕ¼£¬ ¶øÐÂÏß³ÌÒ²³¢ÊÔ»ñµÃͬһ×ÔÐý mutex£¬ ÐÂÏ߳̾ͿÉÄÜÒ»Ö±×ÔÐýÏÂÈ¥£¬ ÒòΪ±»ÖжϵÄÏ߳̿ÉÄÜÓÀԶûÓлú»áÔËÐÐÁË¡£ ´ËÍ⣬ ijЩ´úÂ룬 ÀýÈçÔÚ Alpha É쵀 exec ¶Ô½ø³ÌµØÖ·¿Õ¼ä±àºÅ½øÐи³ÖµµÄ´úÂëÒ²²»Äܱ»ÇÀ¶Ï£¬ ÒòΪËü±»ÓÃÀ´Ö§³Öʵ¼ÊµÄÉÏÏÂÎÄÇл»²Ù×÷¡£ ÔÚÕâЩ´úÂë¶ÎÖУ¬ »áͨ¹ýʹÓÃÁÙ½çÇøÀ´ÁÙʱ½ûÓÃÇÀÕ¼¡£


8.3.2.2 ÁÙ½çÇø

¡¡¡¡ÁÙ½çÇø API µÄÔðÈÎÊDZÜÃâÔÚÁÙ½çÇøÄÚ·¢ÉúÉÏÏÂÎÄÇл»¡£ ¶ÔÓÚÍêÈ«ÇÀռʽÄں˶øÑÔ£¬ ³ýÁ˵±Ç°Ïß³ÌÖ®ÍâµÄÆäËüÏ̵߳Äÿ¸ö setrunqueue ¶¼ÊÇÇÀ¶Ïµã¡£ critical_enter µÄÒ»ÖÖʵÏÖ·½Ê½ÊÇÉèÖÃÒ»Ïß³Ì˽Óбê¼Ç£¬ ²¢ÓÉÆä¶ÔÓ¦·½Çå³ý¡£ Èç¹ûµ÷Óà setrunqueue ʱÉèÖÃÁËÕâ¸ö±êÖ¾£¬ ÔòÎÞÂÛÐÂÏ̺߳͵±Ç°Ïß³ÌÏà±ÈÆäÓÅÏȼ¶¸ßµÍ£¬ ¶¼²»»á·¢ÉúÇÀÕ¼¡£ È»¶ø£¬ ÓÉÓÚÁÙ½çÇø»áÔÚ×ÔÐý mutex ÖÐÓÃÓÚ±ÜÃâÉÏÏÂÎÄÇл»£¬ ¶øÇÒÄܹ»Í¬Ê±»ñµÃ¶à¸ö×ÔÐý mutex£¬ Òò´ËÁÙ½çÇø API ±ØÐëÖ§³ÖǶÌס£ ÓÉÓÚÕâ¸öÔ­Òò£¬ ĿǰµÄʵÏÖÖвÉÓÃÁËǶÌ×¼ÆÊý£¬ ¶ø²»½ö½öÊǵ¥¸öµÄÏ̱߳êÖ¾¡£

¡¡¡¡ÎªÁ˾¡¿ÉÄÜËõ¶ÌÏìӦʱ¼ä£¬ ÔÚÁÙ½çÇøÖеÄÇÀÕ¼±»ÍƳ٣¬ ¶ø²»ÊÇÖ±½Ó¶ªÆú¡£ Èç¹ûÏß³ÌÓ¦±»ÇÀ¶Ï£¬ ²¢±»ÖÃΪ¿ÉÔËÐУ¬ ¶øµ±Ç°Ï̴߳¦ÓÚÁÙ½çÇø£¬ Ôò»áÉèÖÃÒ»Ïß³Ì˽ÓбêÖ¾£¬ ±íʾÓÐÒ»¸öÉÐδ½øÐеÄÇÀ¶Ï²Ù×÷¡£ µ±×îÍâ²ãÁÙ½çÇøÍ˳öʱ£¬ »á¼ì²éÕâÒ»±êÖ¾£¬ Èç¹ûËü±»ÖÃ룬 Ôòµ±Ç°Ï̻߳ᱻÇÀ¶Ï£¬ ÒÔÔÊÐí¸ü¸ßÓÅÏȼ¶µÄÏ߳̿ªÊ¼ÔËÐС£

¡¡¡¡ÖжϻáÒý·¢Ò»¸öºÍ×ÔÐý mutex ÓйصÄÎÊÌâ¡£ Èç¹ûµÍ¼¶Öжϴ¦Àí³ÌÐòÐèÒªËø£¬ Ëü¾Í²»ÄÜÖжÏÈκÎÐèÒª¸ÃËøµÄ´úÂ룬 ÒÔ±ÜÃâ¿ÉÄÜ·¢ÉúµÄËð»µÊý¾Ý½á¹¹µÄÇé¿ö¡£ Ŀǰ£¬ÕâÒ»»úÖÆÊÇ͸¹ýÁÙ½çÇø API ÒÔ cpu_critical_enter ºÍ cpu_critical_exit º¯ÊýµÄÐÎʽʵÏֵġ£ ĿǰÕâÒ» API »áÔÚËùÓÐ FreeBSD ËùÖ§³ÖµÄƽ̨ÉϽûÓúÍÖØÐÂÆôÓÃÖжϡ£ ÕâÖÖ·½·¨²¢²»ÊÇ×îÓŵģ¬ µ«Ëü¸üÒ×Àí½â£¬ Ò²¸üÈÝÒ×ÕýÈ·µØÊµÏÖ¡£ ÀíÂÛÉÏ£¬ ÕâÒ»¸¨Öú API Ö»ÐèÒªÅäºÏÔÚÖ÷ÖжÏÉÏÏÂÎÄÖеÄ×ÔÐý mutex ʹÓᣠȻ¶ø£¬ ΪÁËÈôúÂë¸üΪ¼òµ¥£¬ Ëü±»ÓÃÔÚÁËÈ«²¿×ÔÐý mutex£¬ ÉõÖÁ°üÀ¨ËùÓÐÁÙ½çÇøÉÏ¡£ ½«Æä´Ó MI API ÖаþÀë³öÀ´·ÅÈë MD API£¬ ²¢Ö»ÔÚÐèҪʹÓÃËüµÄ MI API µÄ×ÔÐý mutex ʵÏÖÖÐʹÓÿÉÄÜ»áÓиüºÃµÄЧ¹û¡£ Èç¹ûÎÒÃÇ×îÖÕ²ÉÓÃÁËÕâÖÖʵÏÖ·½Ê½£¬ Ôò MD API ¿ÉÄÜÐèÒª¸ÄÃû£¬ ÒÔÕÃÏÔÆäΪһµ¥¶À API ÕâÒ»ÊÂʵ¡£


8.3.2.3 Éè¼ÆÕÛÖÔ

¡¡¡¡ÈçÇ°ÃæÌáµ½µÄ£¬ µ±ÍêÈ«ÇÀÕ¼²¢·Ç×ÜÄÜÌṩ×î¼ÑÐÔÄÜʱ£¬ ²ÉÈ¡ÁËһЩÕÛÖԵĴëÊ©¡£

¡¡¡¡µÚÒ»´¦ÕÛÖÔÊÇ£¬ ÇÀÕ¼´úÂë²¢²»¿¼ÂÇÆäËü CPU µÄ´æÔÚ¡£ ¼ÙÉèÎÒÃÇÓÐÁ½¸ö CPU£¬ A ºÍ B£¬ ÆäÖÐ A ÉÏÏ̵߳ÄÓÅÏȼ¶Îª 4£¬ ¶ø B ÉÏÏ̵߳ÄÓÅÏȼ¶ÊÇ 2¡£ Èç¹û CPU B ÁîÒ»ÓÅÏȼ¶Îª 1 µÄÏ߳̽øÈë¿ÉÔËÐÐ״̬£¬ ÔòÀíÂÛÉÏ£¬ ÎÒÃÇÏ£Íû CPU A Çл»ÖÁÕâÒ»ÐÂỊ̈߳¬ ÕâÑù¾ÍÓÐÁ½¸öÓÅÏȼ¶×î¸ßµÄÏß³ÌÔÚÔËÐÐÁË¡£ È»¶ø£¬ È·¶¨Äĸö CPU ÔÚÇÀռʱ¸üºÏÊÊ£¬ ²¢Í¨¹ý IPI ÏòÄǸö CPU ·¢³öÐźţ¬ ²¢Íê³ÉÏà¹ØµÄͬ²½¹¤×÷µÄ´ú¼ÛÊ®·Ö¸ß°º¡£ Òò´Ë£¬ ĿǰµÄ´úÂë»áÇ¿ÖÆ CPU B Çл»ÖÁ¸ü¸ßÓÅÏȼ¶µÄÏ̡߳£ Çë×¢ÒâÕâÑù×öÈÔ»áÈÃϵͳ½øÈë¸üºÃµÄ״̬£¬ ÒòΪ CPU B »áÈ¥Ö´ÐÐÓÅÏȼ¶Îª 1 ¶ø²»ÊÇ 2 µÄÄǸöÏ̡߳£

¡¡¡¡µÚ¶þ´¦ÕÛÖÔÊÇÏÞÖÆ¶ÔÓÚʵʱÓÅÏȼ¶µÄÄÚºËÏ̵߳ÄÁ¢¼´ÇÀÕ¼¡£ ÔÚÇ°ÃæËù¶¨ÒåµÄÇÀÕ¼²Ù×÷µÄ¼òµ¥ÇéÐÎÖУ¬ µÍÓÅÏȼ¶×ܻᱻÁ¢¼´ÇÀ¶Ï (»òÔÚÆäÍ˳öÁÙ½çÇøºó±»ÇÀ¶Ï)¡£ È»¶ø£¬ Ðí¶àÔÚÄÚºËÖÐÖ´ÐеÄỊ̈߳¬ ÓкܶàÖ»»áÖ´Ðк̵ܶÄʱ¼ä¾Í»á×èÈû»ò·µ»ØÓû§Ì¬¡£ Òò´Ë£¬ Èç¹ûÄÚºËÇÀ¶ÏÕâЩÏ̲߳¢Ö´ÐÐÆäËü·ÇʵʱµÄÄÚºËỊ̈߳¬ ÔòÄں˿ÉÄÜ»áÔÚÕâЩÏß³ÌÂíÉÏÒªÐÝÃß»òÖ´ÐÐÍê±Ï֮ǰÇл»³öÈ¥¡£ ÕâÑùÒ»À´£¬ CPU ¾Í±ØÐëµ÷Õû¿ìÈ¡»º´æÒÔÅäºÏÐÂÏ̵߳ÄÖ´ÐС£ µ±Äں˷µ»Øµ½±»ÇÀ¶ÏµÄÏß³Ìʱ£¬ ËüÓÖÐèÒªÖØÐÂÌî³ä֮ǰ¶ªÊ§µÄ¿ìÈ¡»º´æÐÅÏ¢¡£ ´ËÍ⣬ Èç¹ûÄÚºËÄܹ»½«¶Ô½«×èÈû»ò·µ»ØÓû§Ì¬µÄÄǸöÏ̵߳ÄÇÀ¶ÏÑÓ³Ùµ½ÕâÖ®ºóµÄ»°£¬ »¹Äܹ»ÃâÈ¥Á½´Î¶îÍâµÄÉÏÏÂÎÄÇл»¡£ Òò´Ë£¬ ĬÈÏÇé¿öÏ£¬ Ö»ÓÐÔÚÓÅÏȼ¶½Ï¸ßµÄÏß³ÌÊÇʵʱÏß³Ìʱ£¬ ÇÀÕ¼´úÂë²Å»áÁ¢¼´Ö´ÐÐÇÀ¶Ï²Ù×÷¡£

¡¡¡¡ÆôÓÃÕë¶ÔËùÓÐÄÚºËÏ̵߳ÄÍêÈ«ÇÀÕ¼¶ÔÓÚµ÷ÊԷdz£ÓаïÖú£¬ ÒòΪËü»á±©Â¶³ö¸ü¶àµÄ¾ºÌ¬Ìõ¼þ (race conditions)¡£ ÔÚÄÑÒÔÄ£ÄâÕâЩ¾ºÌ¬Ìõ¼þµÄµ¥´¦ÀíÆ÷ϵͳÖУ¬ ÕâÏÔµÃÓÈÆäÓÐÓᣠÒò´Ë£¬ ÎÒÃÇÌṩÁËÄÚºËÑ¡Ïî FULL_PREEMPTION À´ÆôÓÃÕë¶ÔËùÓÐÄÚºËÏ̵߳ÄÇÀÕ¼£¬ ÕâһѡÏîÖ÷ÒªÓÃÓÚµ÷ÊÔÄ¿µÄ¡£


8.3.3 Ïß³ÌÇ¨ÒÆ

¡¡¡¡¼òµ¥µØËµ£¬ Ï̴߳ÓÒ»¸ö CPU ÒÆ¶¯µ½ÁíÒ»¸öÉϵĹý³Ì³Æ×÷Ç¨ÒÆ¡£ ÔÚ·ÇÇÀռʽÄÚºËÖУ¬ ÕâÖ»»áÔÚÃ÷È·¶¨ÒåµÄµã£¬ ÀýÈçµ÷Óà msleep »ò·µ»ØÖÁÓû§Ì¬Ê±²Å»á·¢Éú¡£ µ«ÊÇ£¬ ÔÚÇÀռʽÄÚºËÖУ¬ ÖжϿÉÄÜ»áÔÚÈκÎʱºòÇ¿ÖÆÇÀ¶Ï£¬ ²¢µ¼ÖÂÇ¨ÒÆ¡£ ¶ÔÓÚ CPU ˽ÓеÄÊý¾Ý¶øÑÔÕâ¿ÉÄÜ»á´øÀ´Ò»Ð©¸ºÃæÓ°Ï죬 ÒòΪ³ý curthread ºÍ curpcb ÒÔÍâµÄÊý¾Ý¶¼¿ÉÄÜÔÚÇ¨ÒÆ¹ý³ÌÖз¢Éú±ä»¯¡£ ÓÉÓÚ´æÔÚDZÔÚµÄÏß³ÌÇ¨ÒÆ£¬ ʹµÃδÊܱ£»¤µÄ CPU ˽ÓÐÊý¾Ý·ÃÎʱäµÃÎÞÓᣠÕâ¾ÍÐèÒªÔÚijЩ´úÂë¶Î½ûÖ¹Ç¨ÒÆ£¬ ÒÔ»ñµÃÎȶ¨µÄ CPU ˽ÓÐÊý¾Ý¡£

¡¡¡¡Ä¿Ç°ÎÒÃDzÉÓÃÁÙ½çÇøÀ´±ÜÃâÇ¨ÒÆ£¬ ÒòΪËüÃÇÄܹ»×èÖ¹ÉÏÏÂÎÄÇл»¡£ µ«ÊÇ£¬ ÕâÓÐʱ¿ÉÄÜÊÇÒ»ÖÖ¹ýÓÚÑÏÀ÷µÄÏÞÖÆ£¬ ÒòΪÁÙ½çÇøÊµ¼ÊÉÏ»á×èÖ¹µ±Ç°´¦ÀíÆ÷ÉϵÄÖжÏÏ̡߳£ Òò¶ø£¬ ÌṩÁËÁíÒ»¸ö API£¬ ÓÃÒÔָʾµ±Ç°½ø³ÌÔÚ±»ÇÀ¶Ïʱ£¬ ²»Ó¦Ç¨ÒƵ½ÁíÒ» CPU¡£

¡¡¡¡Õâ×é API Ò²½ÐÏß³ÌÇ£ÖÆ£¬ ËüÓɵ÷¶ÈÆ÷Ìṩ¡£ Õâ×é API °üÀ¨Á½¸öº¯Êý£º sched_pin ºÍ sched_unpin¡£ ÕâÁ½¸öº¯ÊýÓÃÓÚ¹ÜÀíÏß³Ì˽ÓеļÆÊý td_pinned¡£ Èç¹ûǶÌ×¼ÆÊý´óÓÚÁ㣬 ÔòÏ߳̽«±»Ëø×¡£¬ ¶øÏ߳̿ªÊ¼ÔËÐÐʱÆäǶÌ×¼ÆÊýΪÁ㣬 ±íʾ´¦ÓÚÎ´Ç£ÖÆ×´Ì¬¡£ ËùÓеĵ÷¶ÈÆ÷ʵÏÖÖУ¬ ¶¼ÒªÇó±£Ö¤Ç£ÖÆÏß³ÌÖ»ÔÚËüÃÇÊ״ε÷Óà sched_pin ʱËùÔÚµÄ CPU ÉÏÔËÐС£ ÓÉÓÚÖ»ÓÐÏß³Ì×Ô¼º»áдǶÌ×¼ÆÊý£¬ ¶øÖ»ÓÐÆäËüÏß³ÌÔÚÊÜÇ£ÖÆÏß³ÌûÓÐÖ´ÐУ¬ ÇÒ³ÖÓÐ sched_lock ËøÊ±²Å»á¶ÁǶÌ×¼ÆÊý£¬ Òò´Ë·ÃÎÊ td_pinned ²»±ØÉÏËø¡£ sched_pin º¯Êý»áʹǶÌ×¼ÆÊýµÝÔö£¬ ¶ø sched_unpin ÔòʹÆäµÝ¼õ¡£ ×¢Ò⣬ ÕâЩº¯ÊýÖ»²Ù×÷µ±Ç°Ị̈߳¬ ²¢½«Æä°ó¶¨µ½ÆäÖ´ÐÐËüʱËù´¦µÄ CPU ÉÏ¡£ Òª½«ÈÎÒâḬ̈߳󶨵½Ö¸¶¨µÄ CPU ÉÏ£¬ ÔòӦʹÓà sched_bind ºÍ sched_unbind¡£


8.3.4 µ÷³ö (Callout)

¡¡¡¡Äں˻úÖÆ timeout ÔÊÐíÄں˷þÎñ×¢²áº¯Êý£¬ ÒÔ×÷Ϊ softclock Èí¼þÖжϵÄÒ»²¿·ÖÀ´Ö´ÐС£ ʼþ½«»ùÓÚËùÏ£ÍûµÄʱÖÓàÖવÄÊýÄ¿½øÐУ¬ ²¢ÔÚ´óÔ¼Ö¸¶¨µÄʱ¼ä»Øµ÷Óû§ÌṩµÄº¯Êý¡£

¡¡¡¡Î´¾ö timeout (³¬Ê±) ʼþµÄÈ«¾Ö±íÊÇÓÉһȫ¾Ö mutex£¬ callout_lock ±£»¤µÄ£» ËùÓÐ¶Ô timeout ±íµÄ·ÃÎÊ£¬ ¶¼±ØÐëÊ×ÏÈÄõ½Õâ¸ö mutex¡£ µ± softclock »½ÐÑʱ£¬ Ëü»áɨÃèδ¾ö³¬Ê±±í£¬ ²¢ÕÒ³öÓ¦Æô¶¯µÄÄÇЩ¡£ Ϊ±ÜÃâËøÄæÐò£¬ softclock Ï̻߳áÔÚµ÷ÓÃËùÌṩµÄ timeout »Øµ÷º¯ÊýʱÊ×ÏÈÊÍ·Å callout_lock mutex¡£ Èç¹ûÔÚ×¢²áʱûÓÐÉèÖà CALLOUT_MPSAFE ±êÖ¾£¬ ÔòÔÚµ÷Óõ÷³öº¯Êý֮ǰ£¬ »¹»áץȡȫ¾ÖËø£¬ ²¢ÔÚÖ®ºóÊÍ·Å¡£ Æäºó£¬ callout_lock mutex »áÔÚ¼ÌÐø´¦ÀíǰÔٴλñµÃ¡£ softclock ´úÂëÔÚÊÍ·ÅÕâ¸ö mutex ʱ»á·Ç³£Ð¡Ðĵر£³Ö±íµÄÒ»ÖÂ״̬¡£ Èç¹ûÆôÓÃÁË DIAGNOSTIC£¬ Ôòÿ¸öº¯ÊýµÄÖ´ÐÐʱ¼ä»á±»¼Ç¼£¬ Èç¹û³¬¹ýÁËijһãÐÖµ£¬ Ôò»á²úÉú¾¯¸æ¡£


8.4 ÌØ¶¨Êý¾ÝµÄËø²ßÂÔ

8.4.1 ƾ¾Ý

¡¡¡¡struct ucred ÊÇÄÚºËÄÚ²¿µÄƾ¾Ý½á¹¹Ì壬 Ëüͨ³£×÷ΪÄÚºËÖÐÒÔ½ø³ÌΪµ¼ÏòµÄ·ÃÎÊ¿ØÖƵÄÒÀ¾Ý¡£ BSD-ÅÉÉúµÄϵͳ²ÉÓÃÒ»ÖÖ ¡°Ð´Ê±¸´ÖÆ¡± µÄÄ£ÐÍÀ´´¦ÀíÆ¾¾ÝÊý¾Ý£º ͬһƾ¾Ý½á¹¹Ìå¿ÉÄÜ´æÔÚ¶à¸öÒýÓ㬠Èç¹ûÐèÒª¶ÔÆä½øÐÐÐ޸ģ¬ ÔòÕâ¸ö½á¹¹Ì彫±»¸´ÖÆ¡¢ Ð޸ģ¬ È»ºóÌæ»»¸ÃÒýÓᣠÓÉÓÚÔÚ´ò¿ªÊ±ÓÃÓÚʵÏÖ·ÃÎÊ¿ØÖÆµÄÆ¾¾Ý¿ìÈ¡»º´æ¹ã·º´æÔÚ£¬ ÕâÖÖ×ö·¨»á¼«´óµØ½ÚÊ¡ÄÚ´æ¡£ ÔÚÇ¨ÒÆµ½Ï¸Á£¶ÈµÄ SMP ʱ£¬ ÕâһģÐÍҲʡȥÁË´óÁ¿µÄËø²Ù×÷£¬ ÒòΪֻÓÐδ¹²ÏíµÄƾ¾Ý²ÅÄÜʵʩÐ޸ģ¬ Òò¶ø±ÜÃâÁËÔÚʹÓù²ÏíÆ¾¾Ýʱ¶îÍâµÄͬ²½²Ù×÷¡£

¡¡¡¡Æ¾¾Ý½á¹¹ÌåÖ»ÓÐÒ»¸öÒýÓÃʱ£¬ ±»ÈÏΪÊǿɱäµÄ£» ²»ÔÊÐí¸Ä±ä¹²ÏíµÄƾ¾Ý½á¹¹Ì壬 ·ñÔò½«¿ÉÄܵ¼Ö·¢Éú¾ºÌ¬Ìõ¼þ¡£ cr_mtxp mutex ÓÃÓÚ±£»¤ struct ucred µÄÒýÓüÆÊý£¬ ÒÔά»¤ÆäÒ»ÖÂÐÔ¡£ ʹÓÃÆ¾¾Ý½á¹¹Ìåʱ£¬ ±ØÐëÔÚʹÓùý³ÌÖб£³ÖÓÐЧµÄÒýÓ㬠·ñÔòËü¾Í¿ÉÄÜÔÚÕâ¸ö²»ºÏÀíµÄÏû·ÑÕßʹÓùý³ÌÖб»ÊÍ·Å¡£

¡¡¡¡struct ucred mutex ÊÇÒ»ÖÖÒ¶ mutex£¬ ³öÓÚÐÔÄÜ¿¼ÂÇ£¬ Ëüͨ¹ý mutex ³ØÊµÏÖ¡£

¡¡¡¡ÓÉÓÚ¶àÓÃÓÚ·ÃÎÊ¿ØÖƾö²ß£¬ ƾ¾Ýͨ³£Çé¿öÏÂÊÇÒÔÖ»¶Á·½Ê½·ÃÎʵģ¬ ´Ëʱһ°ãӦʹÓà td_ucred£¬ ÒòΪËü²»ÐèÒªÉÏËø¡£ µ±¸üнø³Ìƾ¾Ýʱ£¬ ¼ì²éºÍ¸üйý³ÌÖбØÐë³ÖÓÐ proc Ëø¡£ ¼ì²éºÍ¸üвÙ×÷±ØÐëʹÓà p_ucred£¬ ÒÔ±ÜÃâ¼ì²éʱºÍʹÓÃʱµÄ¾ºÌ¬Ìõ¼þ¡£

¡¡¡¡Èç¹ûËùµ÷ϵͳµ÷Óý«ÔÚ¸üнø³Ìƾ¾ÝÖ®ºó½øÐзÃÎÊ¿ØÖƼì²é£¬ Ôò td_ucred Ò²±ØÐëË¢ÐÂΪµ±Ç°½ø³ÌµÄÖµ¡£ ÕâÑù×öÄܹ»±ÜÃâÐ޸ĺóʹÓùýʱµÄƾ¾Ý¡£ Äں˻á×Ô¶¯ÔÚ½ø³Ì½øÈëÄÚºËʱ£¬ ½«Ï߳̽ṹÌåµÄ td_ucred Ö¸ÕëË¢ÐÂΪ½ø³ÌµÄ p_ucred£¬ ÒÔ±£Ö¤Äں˷ÃÎÊ¿ØÖÆÄÜÓõ½ÐÂµÄÆ¾¾Ý¡£


8.4.2 ÎļþÃèÊö·ûºÍÎļþÃèÊö·û±í

¡¡¡¡ÏêϸÄÚÈݽ«ÔÚÉÔºóÔö¼Ó¡£


8.4.3 Jail ½á¹¹Ìå

¡¡¡¡struct prison ±£´æÁËÓÃÓÚά»¤ÄÇЩͨ¹ý jail(2) API ´´½¨µÄ jail ËùÓõ½µÄ¹ÜÀíÐÅÏ¢¡£ Õâ°üÀ¨ jail µÄÖ÷»úÃû¡¢ IP µØÖ·£¬ ÒÔ¼°Ò»Ð©Ïà¹ØµÄÉèÖᣠÕâ¸ö½á¹¹Ìå°üº¬ÒýÓüÆÊý£¬ ÒòΪָÏòÕâÒ»½á¹¹ÌåʵÀýµÄÖ¸Õë»áÔÚ¶àÖÖÆ¾¾Ý½á¹¹Ö®¼ä¹²Ïí¡£ ÓÃÁËÒ»¸ö mutex£¬ pr_mtx À´±£»¤¶ÔÒýÓüÆÊýÒÔ¼°ËùÓÐ jail ½á¹¹ÌåÖпɱä±äÁ¿µÄ¶Áд·ÃÎÊ¡£ ÓÐһЩ±äÁ¿Ö»»áÔÚ´´½¨ jail µÄʱ¿Ì·¢Éú±ä»¯£¬ Ö»Ðè³ÖÓÐÓÐЧµÄ struct prison ¾Í¿ÉÒÔ¿ªÊ¼¶ÁÕâЩֵÁË¡£ ¹ØÓÚÿ¸öÏîÄ¿¾ßÌåµÄÉÏËø²Ù×÷µÄÎĵµ£¬ ¿ÉÒÔÔÚ sys/jail.h µÄ×¢ÊÍÖÐÕÒµ½¡£


8.4.4 MAC ¿ò¼Ü

¡¡¡¡TrustedBSD MAC ¿ò¼Ü»áÒÔ struct label µÄÐÎʽά»¤Ò»ÏµÁÐÄں˶ÔÏóµÄÊý¾Ý¡£ Ò»°ãÀ´Ëµ£¬ ÄÚºËÖÐµÄ label (±êÇ©) ÊÇÓÉÓëÆä¶ÔÓ¦µÄÄں˶ÔÏóͬÑùµÄËø±£»¤µÄ¡£ ÀýÈ磬 struct vnode É쵀 v_label ±êÇ©ÊÇÓÉÆäËùÔÚ vnode É쵀 vnode Ëø±£»¤µÄ¡£

¡¡¡¡³ýÁËǶÈëµ½±ê×¼Äں˶ÔÏóÖеıêǩ֮Í⣬ MAC ¿ò¼ÜÒ²ÐèҪά»¤Ò»×é°üº¬ÒÑ×¢²áµÄºÍ¼¤»î²ßÂÔµÄÁÐ±í¡£ ²ßÂÔ±íºÍæ¼ÆÊýÓÉÒ»¸öÈ«¾Ö mutex (mac_policy_list_lock) ±£»¤¡£ ÓÉÓÚÄܹ»Í¬Ê±²¢ÐеؽøÐÐÐí¶à·ÃÎÊ¿ØÖƼì²é£¬ ¶Ô²ßÂÔ±íµÄÖ»¶Á·ÃÎÊ£¬ ÔÚÔö¼õæ¼ÆÊýʱ£¬ ¿ò¼ÜµÄÈë¿Ú´¦ÐèÒªÊ×ÏȳÖÓÐÕâ¸ö mutex¡£ MAC Èë¿Ú²Ù×÷µÄ¹ý³ÌÖв¢²»ÐèÒª³¤Ê±¼ä³ÖÓÐ´Ë mutex -- ÓÐЩ²Ù×÷£¬ ÀýÈçÎļþϵͳ¶ÔÏóÉϵıêÇ©²Ù×÷ -- Êdz־õġ£ ÒªÐ޸IJßÂÔ±í£¬ ÀýÈçÔÚ×¢²áºÍ½â³ý×¢²á²ßÂÔʱ£¬ ÐèÒª³ÖÓÐ´Ë mutex£¬ ¶øÇÒÒªÇóÒýÓüÆÊýΪÁ㣬 ÒÔ±ÜÃâÔÚÓñíʱ¶ÔÆä½øÐÐÐ޸ġ£

¡¡¡¡¶ÔÓÚÐèÒªµÈ´ý±í½øÈëÏÐÖÃ״̬µÄỊ̈߳¬ ÌṩÁËÒ»¸öÌõ¼þ±äÁ¿ mac_policy_list_not_busy£¬ µ«ÕâÒ»Ìõ¼þ±äÁ¿Ö»ÄÜÔÚµ÷ÓÃÕßûÓгÖÓÐÆäËüËøÊ±²ÅÄÜʹÓ㬠·ñÔò¿ÉÄÜ»áÒý·¢ËøÄæÐòÎÊÌâ¡£ æ¼ÆÊýÔÚÕû¸ö¿ò¼ÜÖÐÊÂʵÉÏ»¹°çÑÝÁËijÖÖÐÎʽµÄ ¹²Ïí/ÅÅËû ËøµÄ×÷Ó㺠Óë sx Ëø²»Í¬µÄµØ·½ÔÚÓÚ£¬ µÈ´ýÁÐ±í½øÈëÏÐÖÃ״̬µÄÏ߳̿ÉÒÔ¶öËÀ£¬ ¶ø²»ÊÇÔÊÐíæ¼ÆÊýºÍÆäËüÔÚ MAC ¿ò¼ÜÈë¿Ú (»òÄÚ²¿) µÄËøÖ®¼äµÄÄæÐòÇé¿ö¡£


8.4.5 Ä£¿é

¡¡¡¡¶ÔÓÚÄ£¿é×Óϵͳ£¬ ÓÃÓÚ±£»¤¹²ÏíÊý¾ÝʹÓÃÁËÒ»¸öµ¥¶ÀµÄËø£¬ ËüÊÇÒ»¸ö ¹²Ïí/ÅÅËû (SX) Ëø£¬ Ðí¶àÇé¿öÐèÒª»ñµÃËü (ÒÔ¹²Ïí»òÅÅËûµÄ·½Ê½)£¬ Òò´ËÎÒÃÇÌṩÁ˼¸¸ö·½±ãʹÓõĺêÀ´¼ò»¯¶ÔÕâ¸öËøµÄ·ÃÎÊ£¬ ÕâЩºê¿ÉÒÔÔÚ sys/module.h ÖÐÕÒµ½£¬ ÆäÓ÷¨¶¼·Ç³£¼òµ¥Ã÷ÁË¡£ Õâ¸öËø±£»¤µÄÖ÷ÒªÊÇ module_t (µ±ÒÔ¹²Ïí·½Ê½ÉÏËø) ºÍÈ«¾ÖµÄ modulelist_t ÕâÁ½¸ö½á¹¹Ì壬 ÒÔ¼°Ä£¿é¡£ Òª¸ü½øÒ»²½Àí½âÕâÐ©Ëø²ßÂÔ£¬ ÐèÒª×ÐϸÔĶÁ kern/kern_module.c µÄÔ´´úÂë¡£


8.4.6 Newbus É豸Ê÷

¡¡¡¡newbus ϵͳʹÓÃÁËÒ»¸ö sx Ëø¡£ ¶ÁµÄÒ»·½Ó¦³ÖÓй²Ïí (¶Á) Ëø (sx_slock(9)) ¶øÐ´µÄÒ»·½ÔòÓ¦³ÖÓÐÅÅËû (д) Ëø (sx_xlock(9))¡£ ÄÚ²¿º¯ÊýÒ»°ã²»ÐèÒª½øÐÐÉÏËø£¬ ¶øÍⲿ¿É¼ûµÄÔòÓ¦¸ù¾ÝÐèÒªÉÏËø¡£ ÓÐЩÏîÄ¿²»ÐèÉÏËø£¬ ÒòΪÕâЩÏîÄ¿ÔÚÈ«³ÌÊÇÖ»¶ÁµÄ£¬ (ÀýÈç device_get_softc(9))£¬ Òò¶ø²¢²»»á²úÉú¾ºÌ¬Ìõ¼þ¡£ Õë¶Ô newbus Êý¾Ý½á¹¹µÄÐÞ¸ÄÏà¶Ô¶øÑԷdz£ÉÙ£¬ Òò´Ëµ¥¸öµÄËøÒѾ­×㹻ʹÓ㬠¶ø²»ÖÂÔì³ÉÐÔÄÜÕÛËð¡£


8.4.7 ¹ÜµÀ

¡¡¡¡...


8.4.8 ½ø³ÌºÍÏß³Ì

¡¡¡¡- ½ø³Ì²ã´Î½á¹¹

¡¡¡¡- proc Ëø¼°Æä²Î¿¼

¡¡¡¡- ÔÚϵͳµ÷Óùý³ÌÖÐÏß³Ì˽ÓÐµÄ proc Ï±¾£¬ °üÀ¨ td_ucred

¡¡¡¡- ½ø³Ì¼ä²Ù×÷

¡¡¡¡- ½ø³Ì×éºÍ»á»°


8.4.9 µ÷¶ÈÆ÷

¡¡¡¡±¾ÎÄÔÚÆäËüµØ·½ÒѾ­ÌṩÁËºÜ¶à¹ØÓÚ sched_lock µÄ²Î¿¼ºÍ×¢ÊÍ¡£


8.4.10 Select ºÍ Poll

¡¡¡¡select ºÍ poll ÕâÁ½¸öº¯ÊýÔÊÐíÏß³Ì×èÈû²¢µÈ´ýÎļþÃèÊö·ûÉϵÄʼþ -- ×î³£¼ûµÄÇé¿öÊÇÎļþÃèÊö·ûÊÇ·ñ¿É¶Á»ò¿Éд¡£

¡¡¡¡...


8.4.11 SIGIO

¡¡¡¡SIGIO ·þÎñÔÊÐí½ø³ÌÇëÇóÔÚÌØ¶¨ÎļþÃèÊö·ûµÄ¶Á/д״̬·¢Éú±ä»¯Ê±£¬ ½« SIGIO ÐźÅȺ·¢¸øÆä½ø³Ì×é¡£ ÈÎÒâ¸ø¶¨Äں˶ÔÏóÉÏ£¬ Ö»ÔÊÐíÒ»½ø³Ì»ò½ø³Ì×é×¢²á SIGIO£¬ Õâ¸ö½ø³Ì»ò½ø³Ì×é³ÆÎªÊôÖ÷ (owner)¡£ ÿһ֧³Ö SIGIO ×¢²áµÄ¶ÔÏó£¬ ¶¼°üº¬Ò»Ö¸Õë×ֶΣ¬ Èç¹û¶ÔÏóδע²áÔòΪ NULL£¬ ·ñÔòÊÇÒ»Ö¸ÏòÃèÊöÕâÒ»×¢²áµÄ struct sigio µÄÖ¸Õë¡£ ÕâÒ»×Ö¶ÎÓÉһȫ¾Ö mutex£¬ sigio_lock ±£»¤¡£ µ÷Óà SIGIO ά»¤º¯Êýʱ£¬ ±ØÐëÒÔ ¡°´«ÒýÓá± ·½Ê½´«µÝÕâÒ»×ֶΣ¬ ÒÔÈ·±£±¾µØ×¢²á¸±±¾µÄÖÐÕâ¸ö×ֶβ»ÍÑÀëËøµÄ±£»¤¡£

¡¡¡¡Ã¿¸ö¹ØÁªµ½½ø³Ì»ò½ø³Ì×éµÄ×¢²á¶ÔÏó£¬ ¶¼»á·ÖÅäÒ» struct sigio ½á¹¹£¬ ²¢°üÀ¨Ö¸»Ø¸Ã¶ÔÏóµÄÖ¸Õë¡¢ ÊôÖ÷¡¢ ÐźÅÐÅÏ¢¡¢ ƾ¾Ý£¬ ÒÔ¼°¹ØÓÚÕâÒ»×¢²áµÄÒ»°ãÐÅÏ¢¡£ ÿ¸ö½ø³Ì»ò½ø³Ì×é¶¼°üº¬Ò»¸öÒÑ×¢²á struct sigio ½á¹¹ÌåµÄÁÐ±í£¬ ¶Ô½ø³ÌÀ´ËµÊÇ p_sigiolst£¬ ¶ø¶Ô½ø³Ì×éÔòÊÇ pg_sigiolst¡£ ÕâЩ±íÓÉÏàÓ¦µÄ½ø³Ì»ò½ø³Ì×éËø±£»¤¡£ ³ýÁËÓÃÒÔ½« struct sigio Á¬½Óµ½½ø³Ì×éÉ쵀 sio_pgsigio ×Ö¶ÎÖ®Í⣬ ÔÚ struct sigio ÖеĶàÊý×Ö¶ÎÔÚ×¢²á¹ý³ÌÖж¼ÊDz»±äÁ¿¡£ Ò»°ã¶øÑÔ£¬ ¿ª·¢ÈËÔ±ÔÚʵÏÖеÄÖ§³Ö SIGIO µÄÄں˶ÔÏóʱ£¬ »áÏ£Íû±ÜÃâÔÚµ÷Óà SIGIO Ö§³Öº¯Êý£¬ ÀýÈç fsetown »ò funsetown ³ÖÓнṹÌåËø£¬ ÒÔÃâÈ¥ÐèÒªÔڽṹÌåËøºÍÈ«¾Ö SIGIO ËøÖ®¼ä¶¨ÒåËøÐò¡£ ͨ³£¿ÉÒÔͨ¹ýÌá¸ß½á¹¹ÌåÉϵÄÒýÓüÆÊýÀ´´ïµ½ÕâÑùµÄÄ¿µÄ£¬ ÀýÈ磬 ÔÚ½øÐйܵÀ²Ù×÷ʱ£¬ ʹÓÃÒýÓÃij¸ö¹ÜµÀµÄÎļþÃèÊö·ûÕâÑùµÄ²Ù×÷£¬ ¾Í¿ÉÒÔÕմ˰ìÀí¡£


8.4.12 Sysctl

¡¡¡¡sysctl MIB ·þÎñ»á´ÓÄÚºËÄÚ²¿£¬ ÒÔ¼°Óû§Ì¬µÄÓ¦ÓóÌÐòÒÔϵͳµ÷Óõķ½Ê½´¥·¢¡£ Õâ»áÒý·¢ÖÁÉÙÁ½¸öºÍËøÓйصÄÎÊÌ⣺ ÆäÒ»ÊǶÔά³ÖÃüÃû¿Õ¼äµÄÊý¾Ý½á¹¹µÄ±£»¤£¬ Æä¶þÊÇÓëÄÇЩͨ¹ý sysctl ½Ó¿Ú·ÃÎʵÄÄں˱äÁ¿ºÍº¯ÊýÖ®¼äµÄ½»»¥¡£ ÓÉÓÚ sysctl ÔÊÐíÖ±½Óµ¼³ö (ÉõÖÁÐÞ¸Ä) ÄÚºËͳ¼ÆÊý¾ÝÒÔ¼°ÅäÖòÎÊý£¬ sysctl »úÖÆ±ØÐëÖªµÀÕâЩ±äÁ¿ÏàÓ¦µÄÉÏËøÓïÒå¡£ Ŀǰ£¬ sysctl ʹÓÃÒ»¸öÈ«¾Ö sx ËøÀ´ÊµÏÖ¶Ô sysctl ²Ù×÷µÄ´®Ðл¯£» È»¶ø£¬ ÕâЩÊǼٶ¨ÓÃÈ«¾ÖËø±£»¤µÄ£¬ ²¢ÇÒûÓÐÌṩÆäËü±£»¤»úÖÆ¡£ ÕâÒ»½ÚµÄÆäÓಿ·Ö½«Ïêϸ½éÉÜÉÏËøºÍ sysctl Ïà¹Ø±ä¶¯µÄÓïÒå¡£

¡¡¡¡- ÐèÒª½« sysctl ¸üÐÂÖµËù½øÐеIJÙ×÷µÄ˳Ðò£¬ ´ÓÔ­ÏȵĶÁ¾ÉÖµ¡¢ copyin ºÍ copyout¡¢ дÐÂÖµ£¬ ¸ÄΪ copyin¡¢ ÉÏËø¡¢ ¶Á¾ÉÖµ¡¢ дÐÂÖµ¡¢ ½âËø¡¢ copyout¡£ Ò»°ãµÄ sysctl Ö»ÊÇ copyout ¾ÉÖµ²¢ÉèÖÃËüÃÇ copyin ËùµÃµ½µÄÐÂÖµ£¬ ÈÔÈ»¿ÉÒÔ²ÉÓþÉʽµÄÄ£ÐÍ¡£ È»¶ø£¬ ¶ÔËùÓÐ sysctl ´¦Àí³ÌÐò²ÉÓõڶþÖÖÄ£ÐͲ¢±ÜÃâËø²Ù×÷·½Ã棬 µÚ¶þÖÖ·½Ê½¿ÉÄܸü¹æ¾ØÒ»Ð©¡£

¡¡¡¡- ¶ÔÓÚͨ³£µÄÇé¿ö£¬ sysctl ¿ÉÒÔÄÚǶһ¸ö mutex Ö¸Õëµ½ SYSCTL_FOO ºêºÍ½á¹¹ÌåÖС£ Õâ¶Ô¶àÊý sysctl ¶¼ÊÇÓÐЧµÄ¡£ ¶ÔÓÚʹÓà sx Ëø¡¢ ×ÔÐý mutex£¬ »òÆäËü³ýµ¥Ò»ÐÝÃß mutex Ö®ÍâµÄËø²ßÂÔ£¬ ¿ÉÒÔÓà SYSCTL_PROC ½ÚµãÀ´Íê³ÉÕýÈ·µÄÉÏËø¡£


8.4.13 ÈÎÎñ¶ÓÁÐ (Taskqueue)

¡¡¡¡ÈÎÎñ¶ÓÁÐ (taskqueue) µÄ½Ó¿Ú°üÀ¨Á½¸öÓëÖ®¹ØÁªµÄÓÃÓÚ±£»¤Ïà¹ØÊý¾ÝµÄËø¡£ taskqueue_queues_mutex ÊÇÓÃÓÚ±£»¤ taskqueue_queues TAILQ µÄËø¡£ ÓëÕâ¸öϵͳ¹ØÁªµÄÁíÒ»¸ö mutex ËøÊÇλÓÚ struct taskqueue ½á¹¹ÌåÉÏ¡£ ÔÚ´Ë´¦Ê¹ÓÃͬ²½Ô­ÓïµÄÄ¿µÄÔÚÓÚ±£»¤ struct taskqueue ÖÐÊý¾ÝµÄÍêÕûÐÔ¡£ ӦעÒâµÄÊÇ£¬ ²¢Ã»Óе¥¶ÀµÄ¡¢ °ïÖúÓû§¶ÔÆä×ÔÉíµÄ¹¤×÷½øÐÐËøµÄϸ»¯Óõĺ꣬ ÒòΪÕâÐ©Ëø»ù±¾Éϲ»»áÔÚ kern/subr_taskqueue.c ÒÔÍâµÄµØ·½Óõ½¡£


8.5 ʵÏÖ˵Ã÷

8.5.1 ÐÝÃß¶ÓÁÐ

¡¡¡¡ÐÝÃß¶ÓÁÐÊÇÒ»ÖÖÓÃÓÚ±£´æÍ¬´¦Ò»¸öµÈ´ýͨµÀ (wait channel) ÉÏÐÝÃßÏß³ÌÁбíµÄÊý¾Ý½á¹¹¡£ ÔڵȴýͨµÀÉÏ£¬ ÿ¸ö´¦ÓÚ·Ç˯Ãß״̬µÄÏ̶߳¼»áЯ´øÒ»¸öÐÝÃß¶ÓÁнṹ¡£ µ±Ïß³ÌÔڵȴýͨµÀÉÏ·¢Éú×èÈûʱ£¬ Ëü»á½«ÐÝÃß¶ÓÁнṹÌåË͸øÄǸöµÈ´ýͨµÀ¡£ ÓëµÈ´ýͨµÀ¹ØÁªµÄÐÝÃß¶ÓÁÐÔò±£´æÔÚÒ»¸öÉ¢ÁбíÖС£

¡¡¡¡ÐÝÃß¶ÓÁÐÉ¢ÁбíÖб£´æÁ˰üº¬ÖÁÉÙÒ»¸ö×èÈûÏ̵߳ĵȴýͨµÀÉϵÄÐÝÃß¶ÓÁС£ Õâ¸öÉ¢ÁбíÉϵÄÏî³Æ×÷ sleepqueue (ÐÝÃß¶ÓÁÐ) Á´¡£ Ëü°üº¬ÁËÒ»¸öÐÝÃß¶ÓÁеÄÁ´±í£¬ ÒÔ¼°Ò»¸ö×ÔÐý mutex¡£ ´Ë´¦µÄ×ÔÐý mutex ÓÃÓÚ±£»¤ÐÝÃß¶ÓÁÐ±í£¬ ÒÔ¼°ÆäÉÏÐÝÃß¶ÓÁнṹµÄÄÚÈÝ¡£ Ò»¸öµÈ´ýͨµÀÉÏÖ»»á¹ØÁªÒ»¸öÐÝÃß¶ÓÁС£ Èç¹ûÓжà¸öÏß³ÌÔÚͬһµÈ´ýͨµÀÉÏ×èÈû£¬ ÔòÐÝÃß¶ÓÁÐÖн«¹ØÁª³ýµÚÒ»¸öÏß³ÌÖ®ÍâµÄÈ«²¿Ï̡߳£ µ±´ÓÐÝÃß¶ÓÁÐÖÐɾ³ýÏß³Ìʱ£¬ Èç¹ûËü²»ÊÇΨһµÄ×èÈûµÄÐÝÃßỊ̈߳¬ Ôò»á»ñµÃÖ÷ÐÝÃß¶ÓÁеĿÕÏбíÉϵÄÐÝÃß¶ÓÁнṹ¡£ ×îºóÒ»¸öÏ̻߳áÔÚ»Ö¸´ÔËÐÐʱ»ñµÃÖ÷ÐÝÃß¶ÓÁС£ ÓÉÓÚÏß³ÌÓпÉÄÜÒԺͼÓÈëÐÝÃß¶ÓÁв»Í¬µÄ´ÎÐò´ÓÆäÖÐɾ³ý£¬ Òò´Ë£¬ Ïß³ÌÀ뿪¶ÓÁÐʱ¿ÉÄÜ»áЯ´øÓëÆä½øÈëʱ²»Í¬µÄÐÝÃß¶ÓÁС£

¡¡¡¡sleepq_lock º¯Êý»áËø×¡Ö¸¶¨µÈ´ýͨµÀÉÏÐÝÃß¶ÓÁÐÁ´µÄ×ÔÐý mutex¡£ sleepq_lookup º¯Êý»áÔÚÖ÷ÐÝÃß¶ÓÁÐÉ¢ÁбíÖвéÕÒ¸ø¶¨µÄµÈ´ýͨµÀ¡£ Èç¹ûûÓÐÕÒµ½Ö÷ÐÝÃß¶ÓÁУ¬ Ëü»á·µ»Ø NULL¡£ sleepq_release º¯Êý»á¶Ô¸ø¶¨µÈ´ýͨµÀËù¹ØÁªµÄ×ÔÐý mutex ½øÐнâËø¡£

¡¡¡¡½«Ï̼߳ÓÈëÐÝÃß¶ÓÁÐÊÇͨ¹ý sleepq_add À´Íê³ÉµÄ¡£ Õâ¸öº¯ÊýµÄ²ÎÊý°üÀ¨µÈ´ýͨµÀ¡¢ Ö¸Ïò±£»¤µÈ´ýͨµÀµÄ mutex µÄÖ¸Õë¡¢ µÈ´ýÏûÏ¢ÃèÊö´®£¬ ÒÔ¼°Ò»¸ö±êÖ¾ÑÚÂë¡£ µ÷Óô˺¯Êý֮ǰ£¬ Ӧͨ¹ý sleepq_lock ΪÐÝÃß¶ÓÁÐÁ´ÉÏËø¡£ Èç¹ûµÈ´ýͨµÀ²»ÊÇͨ¹ý mutex ±£»¤µÄ (»òÕßËüÓÉÈ«¾ÖËø±£»¤)£¬ ÔòÓ¦½« mutex Ö¸ÕëÉèÖÃΪ NULL¡£ ¶ø flags (±êÖ¾) ²ÎÊýÔò°üÀ¨ÁËÒ»¸öÀàÐÍ×ֶΣ¬ ÓÃÒÔ±íʾÏ̼߳´½«¼ÓÈëµ½µÄÐÝÃß¶ÓÁеÄÀàÐÍ£¬ ÒÔ¼°ÐÝÃßÊÇ·ñÊÇ¿ÉÖÐ¶ÏµÄ (SLEEPQ_INTERRUPTIBLE)¡£ ĿǰֻÓÐÁ½ÖÖÀàÐ͵ÄÐÝÃß¶ÓÁУº ͨ¹ý msleep ºÍ wakeup º¯Êý¹ÜÀíµÄ´«Í³ÐÝÃß¶ÓÁÐ (SLEEPQ_MSLEEP)£¬ ÒÔ¼°»ùÓÚÌõ¼þ±äÁ¿µÄÐÝÃß¶ÓÁÐ (SLEEPQ_CONDVAR)¡£ ÐÝÃß¶ÓÁÐÀàÐͺÍËøÖ¸ÕëÕâÁ½¸ö²ÎÊýÍêÈ«ÊÇÓÃÓÚÄÚ²¿µÄ¶ÏÑÔ¼ì²é¡£ µ÷Óà sleepq_add µÄ´úÂ룬 Ó¦Ã÷ʾµØÔÚ¹ØÁªµÄ sleepqueue Á´Í¸¹ý sleepq_lock ½øÐÐÉÏËøÖ®ºó£¬ ²¢Ê¹Óõȴýº¯ÊýÔÚÐÝÃß¶ÓÁÐÉÏ×èÈû֮ǰ½âËøËùÓÐÓÃÓÚ±£»¤µÈ´ýͨµÀµÄ interlock¡£

¡¡¡¡Í¨¹ýʹÓà sleepq_set_timeout ¿ÉÒÔΪÐÝÃßÉèÖó¬Ê±¡£ Õâ¸öº¯ÊýµÄ²ÎÊý°üÀ¨µÈ´ýͨµÀ£¬ ÒÔ¼°ÒÔÏà¶ÔʱÖÓàÖàªÊýΪµ¥Î»µÄ³¬Ê±Ê±¼ä¡£ Èç¹ûÐÝÃßÓ¦±»Ä³¸öµ½À´µÄÐźŴò¶Ï£¬ Ôò»¹Ó¦µ÷Óà sleepq_catch_signals º¯Êý£¬ Õâ¸öº¯ÊýΨһµÄ²ÎÊý¾ÍÊǵȴýͨµÀ¡£ Èç¹û´ËÏß³ÌÒѾ­ÓÐδ¾öÐźţ¬ Ôò sleepq_catch_signals ½«·µ»ØÐźűàºÅ£» ÆäËüÇé¿öÏ£¬ Æä·µ»ØÖµÔòÊÇ 0¡£

¡¡¡¡Ò»µ©½«Ï̼߳ÓÈëµ½ÐÝÃß¶ÓÁÐÖУ¬ ¾Í¿ÉÒÔʹÓà sleepq_wait º¯Êý×åÖ®Ò»½«Æä×èÈûÁË¡£ Ŀǰ×ܹ²ÌṩÁËËĸöµÈ´ýº¯Êý£¬ ʹÓÃÄĸöÈ¡¾öÓÚµ÷ÓÃÕâÊÇ·ñÏ£ÍûÔÊÐíʹÓó¬Ê±¡¢ ÊÕµ½Ðźţ¬ »òÓû§Ì¬Ï̵߳÷¶ÈÆ÷´ò¶ÏÐÝÃß״̬¡£ ÆäÖУ¬ sleepq_wait º¯Êý¼òµ¥µØµÈ´ý£¬ Ö±µ½µ±Ç°Ïß³Ìͨ¹ýij¸ö»½ÐÑ (wakeup) º¯ÊýÏÔʽµØ»Ö¸´ÔËÐУ» sleepq_timedwait º¯ÊýÔòµÈ´ý£¬ Ö±µ½µ±Ç°Ï̱߳»ÏÔʽµØ»½ÐÑ£¬ »òÕß´ïµ½ÔçǰʹÓà sleepq_set_timeout ÉèÖõij¬Ê±£» sleepq_wait_sig º¯Êý»áµÈ´ýÏÔʽµØ»½ÐÑ£¬ »òÕ߯äÐÝÃß±»Öжϣ» ¶ø sleepq_timedwait_sig º¯ÊýÔòµÈ´ýÏÔʽµØ»½ÐÑ¡¢ ´ïµ½Óà sleepq_set_timeout ÉèÖõij¬Ê±£¬ »òÏ̵߳ÄÐÝÃß±»ÖжÏÕâÈýÖÖÌõ¼þÖ®Ò»¡£ ËùÓÐÕâЩµÈ´ýº¯ÊýµÄµÚÒ»¸ö²ÎÊý¶¼ÊǵȴýͨµÀ¡£ ³ý´ËÖ®Í⣬ sleepq_timedwait_sig µÄµÚ¶þ¸ö²ÎÊýÊÇÒ»¸ö²¼¶ûÖµ£¬ ±íʾ֮ǰµ÷Óà sleepq_catch_signals ʱÊÇ·ñÓз¢ÏÖδ¾öÐźš£

¡¡¡¡Èç¹ûÏ̱߳»ÏÔʽµØ»Ö¸´ÔËÐУ¬ »òÆäÐÝÃß±»ÐźÅÖÕÖ¹£¬ ÔòµÈ´ýº¯Êý»á·µ»ØÁ㣬 ±íʾÐÝÃ߳ɹ¦¡£ Èç¹ûÏ̵߳ÄÐÝÃß±»³¬Ê±»òÓû§Ì¬Ï̵߳÷¶ÈÆ÷´ò¶Ï£¬ Ôò»á·µ»ØÏàÓ¦µÄ errno ÊýÖµ¡£ ÐèҪעÒâµÄÊÇ£¬ ÒòΪ sleepq_wait Ö»ÄÜ·µ»Ø 0£¬ Òò´Ëµ÷ÓÃÕß²»ÄÜÖ¸ÍûËü·µ»ØÊ²Ã´ÓÐÓÃÐÅÏ¢£¬ ¶øÓ¦¼Ù¶¨ËüÍê³ÉÁËÒ»´Î³É¹¦µÄÐÝÃß¡£ ͬʱ£¬ Èç¹ûÏ̵߳ÄÐÝÃßʱ¼ä³¬Ê±£¬ ²¢Í¬Ê±±»ÖÕÖ¹£¬ Ôò sleepq_timedwait_sig ½«·µ»ØÒ»¸ö±íʾ·¢Éú³¬Ê±µÄ´íÎó´úÂë¡£ Èç¹û·µ»Ø´íÎó´úÂëÊÇ 0 ¶øÇÒʹÓà sleepq_wait_sig »ò sleepq_timedwait_sig À´Ö´ÐÐ×èÈû£¬ ÔòÓ¦µ÷Óà sleepq_calc_signal_retval À´¼ì²éÊÇ·ñÓÐδ¾öÐźţ¬ ²¢¾Ý´ËÑ¡ÔñºÏÊʵķµ»ØÖµ¡£ ½ÏÔçǰµ÷Óà sleepq_catch_signals µÃµ½µÄÐźűàºÅ£¬ Ó¦×÷Ϊ²ÎÊý´«¸ø sleepq_calc_signal_retval¡£

¡¡¡¡ÔÚͬһÐÝÃßͨµÀÉÏÐÝÃßµÄỊ̈߳¬ ¿ÉÒÔÓÉ sleepq_broadcast »ò sleepq_signal º¯ÊýÀ´ÏÔʽµØ»½ÐÑ¡£ ÕâÁ½¸öº¯ÊýµÄ²ÎÊý¾ù°üÀ¨Ï£Íû»½ÐѵĵȴýͨµÀ¡¢ ½«»½ÐÑÏ̵߳ÄÓÅÏȼ¶ (priority) Ìá¸ßµ½¶àÉÙ£¬ ÒÔ¼°Ò»¸ö±êÖ¾ (flags) ²ÎÊý±íʾ½«Òª»Ö¸´ÔËÐеÄÐÝÃß¶ÓÁÐÀàÐÍ¡£ ÓÅÏȼ¶²ÎÊý½«×÷Ϊ×îµÍÓÅÏȼ¶£¬ Èç¹û½«»Ö¸´µÄÏ̵߳ÄÓÅÏȼ¶±È´Ë²ÎÊý¸ü¸ß (ÊýÖµ¸üµÍ) ÔòÆäÓÅÏȼ¶²»»áµ÷Õû¡£ ±êÖ¾²ÎÊýÖ÷ÒªÓÃÓÚº¯ÊýÄÚ²¿µÄ¶ÏÑÔ£¬ ÓÃÒÔÈ·ÈÏÐÝÃß¶ÓÁÐûÓб»µ±×ö´íÎóµÄÀàÐͶԴý¡£ ÀýÈ磬 Ìõ¼þ±äÁ¿º¯Êý²»Ó¦»Ö¸´´«Í³ÐÝÃß¶ÓÁеÄÖ´ÐС£ sleepq_broadcast º¯Êý½«»Ö¸´ËùÓÐÖ¸¶¨ÐÝÃßͨµÀÉϵÄ×èÈûỊ̈߳¬ ¶ø sleepq_signal ÔòÖ»»Ö¸´ÔڵȴýͨµÀÉÏÓÅÏȼ¶×î¸ßµÄ×èÈûÏ̡߳£ ÔÚµ÷ÓÃÕâЩº¯Êý֮ǰ£¬ Ó¦Ê×ÏÈʹÓà sleepq_lock ¶ÔÐÝÃß¶ÓÁÐÉÏËø¡£

¡¡¡¡ÐÝÃßÏß³ÌÒ²¿ÉÒÔͨ¹ýµ÷Óà sleepq_abort º¯ÊýÀ´ÖÐ¶ÏÆäÐÝÃß״̬¡£ Õâ¸öº¯ÊýÖ»ÓÐÔÚ³ÖÓÐ sched_lock ʱ²ÅÄܵ÷Ó㬠¶øÇÒÏ̱߳ØÐë´¦ÓÚÐÝÃß¶ÓÁÐÖ®ÉÏ¡£ Ïß³ÌÒ²¿ÉÒÔͨ¹ýʹÓà sleepq_remove º¯Êý´ÓÖ¸¶¨µÄÐÝÃß¶ÓÁÐÖÐɾ³ý¡£ Õâ¸öº¯Êý°üÀ¨Á½¸ö²ÎÊý£¬ ¼´ÐÝÃßͨµÀºÍỊ̈߳¬ ËüÖ»ÔÚÏ̴߳¦ÓÚÖ¸¶¨ÐÝÃßͨµÀµÄÐÝÃß¶ÓÁÐÖ®ÉÏʱ²Å½«Æä»½ÐÑ¡£ Èç¹ûÏ̲߳»ÔÚÄǸöÐÝÃß¶ÓÁÐÖ®ÉÏ£¬ »òͬʱ´¦ÓÚÁíÒ»µÈ´ýͨµÀµÄÐÝÃß¶ÓÁÐÉÏ£¬ ÔòÕâ¸öº¯Êý½«Ê²Ã´¶¼²»×ö¶øÖ±½Ó·µ»Ø¡£


8.5.2 Ê®×ÖתÃÅ (turnstile)

¡¡¡¡- ÓëÐÝÃß¶ÓÁеıȽϺͲ»Í¬¡£

¡¡¡¡- ²éѯ/µÈ´ý/ÊÍ·Å (lookup/wait/release) - ½éÉÜ TDF_TSNOBLOCK ¾ºÌ¬Ìõ¼þ¡£

¡¡¡¡- ÓÅÏȼ¶´«²¥¡£


8.5.3 ¹ØÓÚ mutex ʵÏÖµÄһЩϸ½Ú

¡¡¡¡- ÎÒÃÇÊÇ·ñÓ¦ÒªÇó mtx_destroy() ³ÖÓÐ mutex£¬ ÒòΪÎÞ·¨°²È«µØ¶ÏÑÔËüÃÇûÓб»ÆäËü¶ÔÏó³ÖÓУ¿


8.5.3.1 ×ÔÐý mutex

¡¡¡¡- ʹÓÃÒ»ÁÙ½çÇø...


8.5.3.2 ÐÝÃß mutex

¡¡¡¡- ÃèÊö mutex ³åͻʱµÄ¾ºÌ¬Ìõ¼þ

¡¡¡¡- ΪºÎÔÚ³ÖÓÐÊ®×ÖתÃÅÁ´ËøÊ±£¬ ¿ÉÒÔ°²È«µØ¶Á³åÍ» mutex µÄ mtx_lock¡£


8.5.4 Witness

¡¡¡¡- ËüÄÜ×öʲô

¡¡¡¡- ËüÈçºÎ¹¤×÷


8.6 ÆäËü»°Ìâ

8.6.1 ÖжÏÔ´ºÍ ICU ³éÏó

¡¡¡¡- struct isrc

¡¡¡¡- pic Çý¶¯


8.6.2 ÆäËüÎÊÌâ/»°Ìâ

¡¡¡¡- ÊÇ·ñÓ¦½« interlock ´«¸ø sema_wait£¿

¡¡¡¡- ÊÇ·ñÓ¦Ìṩ·ÇÐÝÃßʽ sx Ëø£¿

¡¡¡¡- Ôö¼ÓһЩ¹ØÓÚÕýȷʹÓÃÒýÓüÆÊýµÄ½éÉÜ¡£

ÊõÓï±í

Ô­×Ó

µ±×ñÑ­Êʵ±µÄ·ÃÎÊЭÒéʱ£¬ Èç¹ûÒ»²Ù×÷µÄЧ¹û¶ÔÆäËüËùÓÐ CPU ¾ù¿É¼û£¬ Ôò³ÆÆäΪԭ×Ó²Ù×÷¡£ ÏÁÒåµÄÔ­×Ó²Ù×÷ÊÇ»úÆ÷Ö±½ÓÌṩµÄ¡£ ¾Í¸ü¸ßµÄ³éÏó²ã´Î¶øÑÔ£¬ Èç¹û½á¹¹ÌåµÄ¶à¸ö³ÉÔ±ÓÉÒ»¸öËø±£»¤£¬ ÔòÈç¹û¶ÔËüÃǵIJÙ×÷¶¼ÊÇÔÚÉÏËøºó¡¢ ½âËøÇ°½øÐеģ¬ Ò²¿ÉÒÔ³ÆÆäΪԭ×Ó²Ù×÷¡£

²Î¼û: ²Ù×÷.

×èÈû

Ï̵߳ȴýËø¡¢ ×ÊÔ´»òÌõ¼þʱ±»×èÈû¡£ ÕâÒ»ÊõÓïÒ²Òò´Ë±»¸³ÓèÁËÌ«¶àµÄÒ⺭¡£

²Î¼û: ÐÝÃß.

ÁÙ½çÇø

²»ÔÊÐí·¢ÉúÇÀÕ¼µÄ´úÂë¶Î¡£ ʹÓà critical_enter(9) API À´±íʾ½øÈëºÍÍ˳öÁÙ½çÇø¡£

MD

±íʾÓë»úÆ÷/ƽ̨Óйء£

²Î¼û: MI.

ÄÚ´æ²Ù×÷

ÄÚ´æ²Ù×÷°üÀ¨¶Á»òдÄÚ´æÖеÄÖ¸¶¨Î»Öá£

MI

±íʾÓë»úÆ÷/ƽ̨Î޹ء£

²Î¼û: MD.

²Ù×÷
ÄÚ´æ²Ù×÷
Ö÷ÖжÏÉÏÏÂÎÄ

Ö÷ÖжÏÉÏÏÂÎıíʾµ±·¢ÉúÖжÏʱËùÖ´ÐеÄÄǶδúÂë¡£ ÕâЩ´úÂë¿ÉÒÔÖ±½ÓÔËÐÐij¸öÖжϴ¦Àí³ÌÐò£¬ »òµ÷¶ÈÒ»Òì²½ÖÕ¶ËỊ̈߳¬ ÒÔ±ãΪ¸ø¶¨µÄÖжÏÔ´Ö´ÐÐÖжϴ¦Àí³ÌÐò¡£

ʵʱÄÚºËÏß³Ì

Ò»ÖÖ¸ßÓÅÏȼ¶µÄÄÚºËÏ̡߳£ Ŀǰ£¬ Ö»ÓÐÖжÏÏß³ÌÊôÓÚʵʱÓÅÏȼ¶µÄÄÚºËÏ̡߳£

²Î¼û: Ïß³Ì.

ÐÝÃß

µ±½ø³ÌÓÉÌõ¼þ±äÁ¿»òͨ¹ý msleep »ò tsleep ×èÈû²¢½øÈëÐÝÃß¶ÓÁÐʱ£¬ ³ÆÆä½øÈëÐÝÃß״̬¡£

²Î¼û: ×èÈû.

¿ÉÐÝÃßËø

¿ÉÐÝÃßËøÊÇÒ»ÖÖÔÚ½ø³ÌÐÝÃßʱÈԿɳÖÓеÄËø¡£ Ëø¹ÜÀíÆ÷ (lockmgr) ËøºÍ sx ËøÊÇĿǰ FreeBSD ÖнöÓеĿÉÐÝÃßËø¡£ ×îÖÕ£¬ ijЩ sx Ëø£¬ ÀýÈç allproc (È«²¿½ø³Ì) ºÍ proctree (½ø³ÌÊ÷) Ëø½«³ÉΪ²»¿ÉÐÝÃßËø¡£

²Î¼û: ÐÝÃß.

Ïß³Ì

ÓÉ struct thread Ëù±í´ïµÄÄÚºËÏ̡߳£ Ï߳̿ÉÒÔ³ÖÓÐËø£¬ ²¢ÓµÓжÀÁ¢µÄÖ´ÐÐÉÏÏÂÎÄ¡£

µÈ´ýͨµÀ

Ï߳̿ÉÒÔÔÚÆäÉÏÐÝÃßµÄÄÚºËÐéÄâµØÖ·¡£

µÚII²¿·Ö. É豸Çý¶¯³ÌÐò

Ŀ¼
µÚ9Õ¡¡±àд FreeBSD É豸Çý¶¯³ÌÐò
µÚ10Õ¡¡ISAÉ豸Çý¶¯³ÌÐò
µÚ11Õ¡¡PCIÉ豸
µÚ12Õ¡¡Í¨Ó÷ÃÎÊ·½·¨SCSI¿ØÖÆÆ÷
µÚ13Õ¡¡USBÉ豸
µÚ14Õ¡¡Newbus
µÚ15Õ¡¡ÉùÒô×Óϵͳ
µÚ16Õ¡¡PC Card

µÚ9Õ ¡¡±àд FreeBSD É豸Çý¶¯³ÌÐò

д×÷£ºMurray Stokely. »ù´¡ÐÔÊÖ²áintro(4)£ºJörg Wunsch. ·­Ò룺spellar @SMTH.

9.1 ¼ò½é

¡¡¡¡±¾Õ¼òÒª½éÉÜÁËÈçºÎΪFreeBSD±àдÉ豸Çý¶¯³ÌÐò¡£ÊõÓïÉ豸ÔÚ Õâ¶ùµÄÉÏÏÂÎÄÖжàÓÃÓÚÖ¸´úϵͳÖÐÓ²¼þÏà¹ØµÄ¶«Î÷£¬Èç´ÅÅÌ£¬´òÓ¡»ú£¬ ͼÐÎÏÔʽÆ÷¼°Æä¼üÅÌ¡£É豸Çý¶¯³ÌÐòÊDzÙ×÷ϵͳÖÐÓÃÓÚ¿ØÖÆÌض¨É豸µÄ Èí¼þ×é¼þ¡£Ò²ÓÐËùνµÄαÉ豸£¬¼´É豸Çý¶¯³ÌÐòÓÃÈí¼þÄ£ÄâÉ豸µÄÐÐΪ£¬ ¶øÃ»ÓÐÌØ¶¨µÄµ×²ãÓ²¼þ¡£É豸Çý¶¯³ÌÐò¿ÉÒÔ±»¾²Ì¬µØ±àÒë½øÏµÍ³£¬»òÕß Í¨¹ý¶¯Ì¬ÄÚºËÁ´½Ó¹¤¾ß¡®kld¡¯ÔÚÐèҪʱ¼ÓÔØ¡£

¡¡¡¡ÀàUNIX²Ù×÷ϵͳÖеĴó¶àÊýÉ豸¶¼ÊÇͨ¹ýÉ豸½ÚµãÀ´·ÃÎʵģ¬ÓÐʱҲ ±»³ÆÎªÌØÊâÎļþ¡£ÕâЩÎļþÔÚÎļþϵͳµÄ²ã´Î½á¹¹ÖÐͨ³£Î»ÓÚ /devĿ¼Ï¡£ÔÚFreeBSD 5.0-RELEASEÒÔǰµÄ ·¢ÐаæÖÐ, ¶Ôdevfs(5)µÄÖ§³Ö»¹Ã»Óб»¼¯³Éµ½FreeBSDÖУ¬Ã¿¸öÉ豸 ½Úµã±ØÐëÒª¾²Ì¬´´½¨£¬²¢ÇÒ¶ÀÁ¢ÓÚÏà¹ØÉ豸Çý¶¯³ÌÐòµÄ´æÔÚ¡£ÏµÍ³Öдó ¶àÊýÉ豸½ÚµãÊÇͨ¹ýÔËÐÐMAKEDEV´´½¨µÄ¡£

¡¡¡¡É豸Çý¶¯³ÌÐò¿ÉÒÔ´ÖÂԵطÖΪÁ½À࣬×Ö·ûºÍÍøÂçÉ豸Çý¶¯³ÌÐò¡£


9.2 ¶¯Ì¬ÄÚºËÁ´½Ó¹¤¾ß©¤©¤KLD

¡¡¡¡kld½Ó¿ÚÔÊÐíϵͳ¹ÜÀíÔ±´ÓÔËÐеÄϵͳÖж¯Ì¬µØÌí¼ÓºÍɾ³ý¹¦ÄÜ¡£ ÕâÔÊÐíÉ豸Çý¶¯³ÌÐòµÄ±àдÕß½«ËûÃǵÄÐ¸Ķ¯¼ÓÔØµ½ÔËÐеÄÄÚºËÖУ¬ ¶ø²»ÓÃΪÁ˲âÊÔÐ¸Ķ¯¶øÆµ·±µØÖØÆô¡£

¡¡¡¡kld½Ó¿Úͨ¹ýÏÂÃæµÄÌØÈ¨ÃüÁîʹÓãº

  • kldload - ¼ÓÔØÐÂÄÚºËÄ£¿é

  • kldunload - Ð¶ÔØÄÚºËÄ£¿é

  • kldstat - Áоٵ±Ç°¼ÓÔØµÄÄ£¿é

¡¡¡¡ÄÚºËÄ£¿éµÄ³ÌÐò¿ò¼Ü

/*
 * KLD³ÌÐò¿ò¼Ü
 * ÊÜAndrew ReiterÔÚDaemonnewsÉϵÄÎÄÕÂËùÆô·¢
 */

#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>  /* uprintf */ 
#include <sys/errno.h>
#include <sys/param.h>  /* kernel.hÖÐÓõ½µÄ¶¨Òå */
#include <sys/kernel.h> /* Ä£¿é³õʼ»¯ÖÐʹÓõÄÀàÐÍ */

/* 
 * ¼ÓÔØ´¦Àíº¯Êý£¬¸ºÔð´¦ÀíKLDµÄ¼ÓÔØºÍÐ¶ÔØ¡£
 */

static int
skel_loader(struct module *m, int what, void *arg)
{
  int err = 0;
  
  switch (what) {
  case MOD_LOAD:                /* kldload */
    uprintf("Skeleton KLD loaded.\n");
    break;
  case MOD_UNLOAD:
    uprintf("Skeleton KLD unloaded.\n");
    break;
  default:
    err = EOPNOTSUPP;
    break;
  }
  return(err);
}

/* ÏòÄÚºËÆäÓಿ·ÖÉùÃ÷´ËÄ£¿é */

static moduledata_t skel_mod = {
  "skel",
  skel_loader,
  NULL
};  

DECLARE_MODULE(skeleton, skel_mod, SI_SUB_KLD, SI_ORDER_ANY);

9.2.1 Makefile

¡¡¡¡FreeBSDÌṩÁËÒ»¸ömakefile°üº¬Îļþ£¬ÀûÓÃËüÄã¿ÉÒÔ¿ìËٵرàÒë Ä㸽¼Óµ½Äں˵Ķ«Î÷¡£

SRCS=skeleton.c
KMOD=skeleton

.include <bsd.kmod.mk>

¡¡¡¡¼òµ¥µØÓÃÕâ¸ömakefileÔËÐÐmake¾ÍÄܹ»´´½¨Îļþ skeleton.ko£¬¼üÈëÈçÏÂÃüÁî¿ÉÒÔ°ÑËü¼ÓÔØµ½Äںˣº

# kldload -v ./skeleton.ko

9.3 ·ÃÎÊÉ豸Çý¶¯³ÌÐò

¡¡¡¡UNIX ÌṩÁËÒ»Ì×¹«¹²µÄϵͳµ÷Óù©Óû§µÄÓ¦ÓóÌÐòʹÓᣵ±Óû§·ÃÎÊ É豸½Úµãʱ£¬Äں˵ÄÉϲ㽫ÕâЩµ÷Ó÷ַ¢µ½ÏàÓ¦µÄÉ豸Çý¶¯³ÌÐò¡£½Å±¾ /dev/MAKEDEVΪÄãµÄϵͳÉú³ÉÁË´ó¶àÊýµÄÉ豸½Úµã£¬ µ«Èç¹ûÄãÕýÔÚ¿ª·¢Äã×Ô¼ºµÄÇý¶¯³ÌÐò£¬¿ÉÄÜÐèÒªÓà mknod´´½¨Äã×Ô¼ºµÄÉ豸½Úµã¡£


9.3.1 ´´½¨¾²Ì¬É豸½Úµã

¡¡¡¡mknodÃüÁîÐèÒªËĸö²ÎÊýÀ´´´½¨É豸½Úµã¡£ Äã±ØÐëÖ¸¶¨É豸½ÚµãµÄÃû×Ö£¬É豸µÄÀàÐÍ£¬É豸µÄÖ÷ºÅÂëºÍÉ豸µÄ´ÓºÅÂë¡£


9.3.2 ¶¯Ì¬É豸½Úµã

¡¡¡¡É豸Îļþϵͳ£¬»òÕß˵devfs£¬ÔÚÈ«¾ÖÎļþϵͳÃû×Ö¿Õ¼äÖÐÌṩ¶Ô ÄÚºËÉ豸Ãû×Ö¿Õ¼äµÄ·ÃÎÊ¡£ÕâÏû³ýÁËÓÉÓÚÓÐÉ豸Çý¶¯³ÌÐò¶øÃ»Óо²Ì¬ É豸½Úµã£¬»òÕßÓÐÉ豸½Úµã¶øÃ»Óа²×°É豸Çý¶¯³ÌÐò¶ø´øÀ´µÄDZÔÚÎÊÌâ¡£ DevfsÈÔÔÚ½øÕ¹ÖУ¬µ«ÒѾ­Äܹ»¹¤×÷µÃÏ൱ºÃÁË¡£


9.4 ×Ö·ûÉ豸

¡¡¡¡×Ö·ûÉ豸Çý¶¯³ÌÐòÖ±½Ó´ÓÓû§½ø³Ì´«ÊäÊý¾Ý£¬»ò´«ÊäÊý¾Ýµ½Óû§½ø³Ì¡£ ÕâÊÇ×îÆÕͨµÄÒ»ÀàÉ豸Çý¶¯³ÌÐò£¬Ô´ÂëÊ÷ÖÐÓдóÁ¿µÄ¼òµ¥Àý×Ó¡£

¡¡¡¡Õâ¸ö¼òµ¥µÄαÉ豸Àý×Ó»á¼ÇסÄãд¸øËüµÄÈκÎÖµ£¬²¢ÇÒµ±Äã¶ÁÈ¡ËüµÄʱºò »á½«ÕâЩֵ·µ»Ø¸øÄã¡£ÏÂÃæÏÔʾÁËÁ½¸ö°æ±¾£¬Ò»¸öÊÊÓÃÓÚFreeBSD 4.X£¬ Ò»¸öÊÊÓÃÓÚFreeBSD 5.X¡£

Àý 9-1. ÊÊÓÃÓÚFreeBSD 4.XµÄ»ØÏÔαÉ豸Çý¶¯³ÌÐòʵÀý

/*
 * ¼òµ¥¡®echo¡¯Î±É豸KLD
 *
 * Murray Stokely
 */

#define MIN(a,b) (((a) < (b)) ? (a) : (b))

#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>  /* uprintf */
#include <sys/errno.h>
#include <sys/param.h>  /* kernel.hÖÐÓõ½µÄ¶¨Òå */
#include <sys/kernel.h> /* Ä£¿é³õʼ»¯ÖÐʹÓõÄÀàÐÍ */
#include <sys/conf.h>   /* cdevsw½á¹¹ */
#include <sys/uio.h>    /* uio½á¹¹ */
#include <sys/malloc.h>

#define BUFFERSIZE 256

/* º¯ÊýÔ­ÐÍ */
d_open_t	echo_open;
d_close_t	echo_close;
d_read_t	echo_read;
d_write_t	echo_write;

/* ×Ö·ûÉ豸Èë¿Úµã */
static struct cdevsw echo_cdevsw = {
	echo_open,
	echo_close,
	echo_read,
	echo_write,
	noioctl,
	nopoll,
	nommap,
	nostrategy,
	"echo",
	33,              /* Ϊlkms±£Áô - /usr/src/sys/conf/majors */
	nodump,
	nopsize,
	D_TTY,
	-1
};

typedef struct s_echo {
	char msg[BUFFERSIZE];
	int len;
} t_echo;

/* ±äÁ¿ */
static dev_t sdev;
static int count;
static t_echo *echomsg;

MALLOC_DECLARE(M_ECHOBUF);
MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");

/*
 * Õâ¸öº¯Êý±»kld[un]load(2)ϵͳµ÷ÓÃÀ´µ÷Óã¬
 * ÒÔ¾ö¶¨¼ÓÔØºÍÐ¶ÔØÄ£¿éʱÐèÒª²ÉÈ¡µÄ¶¯×÷¡£
 */

static int
echo_loader(struct module *m, int what, void *arg)
{
	int err = 0;

	switch (what) {
	case MOD_LOAD:                /* kldload */
		sdev = make_dev(&echo_cdevsw,
		    0,
		    UID_ROOT,
		    GID_WHEEL,
		    0600,
		    "echo");
		/* kmalloc·ÖÅ乩Çý¶¯³ÌÐòʹÓõÄÄÚ´æ */
		MALLOC(echomsg, t_echo *, sizeof(t_echo), M_ECHOBUF, M_WAITOK);
		printf("Echo device loaded.\n");
		break;
	case MOD_UNLOAD:
		destroy_dev(sdev);
		FREE(echomsg,M_ECHOBUF);
		printf("Echo device unloaded.\n");
		break;
	default:
		err = EOPNOTSUPP;
		break;
	}
	return(err);
}

int
echo_open(dev_t dev, int oflags, int devtype, struct proc *p)
{
	int err = 0;

	uprintf("Opened device \"echo\" successfully.\n");
	return(err);
}

int
echo_close(dev_t dev, int fflag, int devtype, struct proc *p)
{
	uprintf("Closing device \"echo.\"\n");
	return(0);
}

/*
 * readº¯Êý½ÓÊÜÓÉecho_write()´æ´¢µÄbuf£¬²¢½«Æä·µ»Øµ½Óû§¿Õ¼ä£¬
 * ÒÔ¹©ÆäËûº¯Êý·ÃÎÊ¡£
 * uio(9)
 */

int
echo_read(dev_t dev, struct uio *uio, int ioflag)
{
	int err = 0;
	int amt;

	/*
	 * Õâ¸ö¶Á²Ù×÷Óжà´ó£¿
	 * ÓëÓû§ÇëÇóµÄ´óСһÑù£¬»òÕßµÈÓÚÊ£ÓàÊý¾ÝµÄ´óС¡£
	 */
	amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ?
	    echomsg->len - uio->uio_offset : 0);
	if ((err = uiomove(echomsg->msg + uio->uio_offset,amt,uio)) != 0) {
		uprintf("uiomove failed!\n");
	}
	return(err);
}

/*
 * echo_write½ÓÊÜÒ»¸ö×Ö·û´®²¢½«Ëü±£´æµ½»º³åÇø£¬ÓÃÓÚÒÔºóµÄ·ÃÎÊ¡£
 */

int
echo_write(dev_t dev, struct uio *uio, int ioflag)
{
	int err = 0;

	/* ½«×Ö·û´®´ÓÓû§¿Õ¼äµÄÄÚ´æ¸´ÖÆµ½Äں˿ռä */
	err = copyin(uio->uio_iov->iov_base, echomsg->msg,
	    MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1));

	/* ÏÖÔÚÐèÒªÒÔnull½áÊø×Ö·û´®£¬²¢¼Ç¼³¤¶È */
	*(echomsg->msg + MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1)) = 0;
	echomsg->len = MIN(uio->uio_iov->iov_len, BUFFERSIZE);

	if (err != 0) {
		uprintf("Write failed: bad address!\n");
	}
	count++;
	return(err);
}

DEV_MODULE(echo,echo_loader,NULL);

Àý 9-2. ÊÊÓÃÓÚFreeBSD 5.X»ØÏÔαÉ豸Çý¶¯³ÌÐòʵÀý

/*
 * ¼òµ¥¡®echo¡¯Î±É豸 KLD
 *
 * Murray Stokely
 *
 * ´Ë´úÂëÓÉSøren (Xride) Straarupת»»µ½5.X
 */

#include <sys/types.h>
#include <sys/module.h>
#include <sys/systm.h>  /* uprintf */
#include <sys/errno.h>
#include <sys/param.h>  /* kernel.hÖÐÓõ½µÄ¶¨Òå */
#include <sys/kernel.h> /* Ä£¿é³õʼ»¯ÖÐʹÓõÄÀàÐÍ */
#include <sys/conf.h>   /* cdevsw½á¹¹ */
#include <sys/uio.h>    /* uio½á¹¹ */
#include <sys/malloc.h>

#define BUFFERSIZE 256


/* º¯ÊýÔ­ÐÍ */
static d_open_t      echo_open;
static d_close_t     echo_close;
static d_read_t      echo_read;
static d_write_t     echo_write;

/* ×Ö·ûÉ豸Èë¿Úµã */
static struct cdevsw echo_cdevsw = {
	.d_version = D_VERSION,
	.d_open = echo_open,
	.d_close = echo_close,
	.d_read = echo_read,
	.d_write = echo_write,
	.d_name = "echo",
};

typedef struct s_echo {
	char msg[BUFFERSIZE];
	int len;
} t_echo;

/* ±äÁ¿ */
static struct cdev *echo_dev;
static int count;
static t_echo *echomsg;

MALLOC_DECLARE(M_ECHOBUF);
MALLOC_DEFINE(M_ECHOBUF, "echobuffer", "buffer for echo module");

/*
 * Õâ¸öº¯Êý±»kld[un]load(2)ϵͳµ÷ÓÃÀ´µ÷ÓÃ, 
 * ÒÔ¾ö¶¨¼ÓÔØºÍÐ¶ÔØÄ£¿éʱÐèÒª²ÉÈ¡µÄ¶¯×÷. 
 */

static int
echo_loader(struct module *m, int what, void *arg)
{
	int err = 0;

	switch (what) {
	case MOD_LOAD:                /* kldload */
		echo_dev = make_dev(&echo_cdevsw,
		    0,
		    UID_ROOT,
		    GID_WHEEL,
		    0600,
		    "echo");
		/* kmalloc·ÖÅ乩Çý¶¯³ÌÐòʹÓõÄÄÚ´æ */
		echomsg = malloc(sizeof(t_echo), M_ECHOBUF, M_WAITOK);
		printf("Echo device loaded.\n");
		break;
	case MOD_UNLOAD:
		destroy_dev(echo_dev);
		free(echomsg, M_ECHOBUF);
		printf("Echo device unloaded.\n");
		break;
	default:
		err = EOPNOTSUPP;
		break;
	}
	return(err);
}

static int
echo_open(struct cdev *dev, int oflags, int devtype, struct thread *p)
{
	int err = 0;

	uprintf("Opened device \"echo\" successfully.\n");
	return(err);
}

static int
echo_close(struct cdev *dev, int fflag, int devtype, struct thread *p)
{
	uprintf("Closing device \"echo.\"\n");
	return(0);
}

/*
 * readº¯Êý½ÓÊÜÓÉecho_write()´æ´¢µÄbuf£¬²¢½«Æä·µ»Øµ½Óû§¿Õ¼ä£¬
 * ÒÔ¹©ÆäËûº¯Êý·ÃÎÊ¡£
 * uio(9)
 */

static int
echo_read(struct cdev *dev, struct uio *uio, int ioflag)
{
	int err = 0;
	int amt;

	/*
	 * Õâ¸ö¶Á²Ù×÷Óжà´ó£¿
	 * µÈÓÚÓû§ÇëÇóµÄ´óС£¬»òÕßµÈÓÚÊ£ÓàÊý¾ÝµÄ´óС¡£
	 */
	amt = MIN(uio->uio_resid, (echomsg->len - uio->uio_offset > 0) ?
	     echomsg->len - uio->uio_offset : 0);
	if ((err = uiomove(echomsg->msg + uio->uio_offset, amt, uio)) != 0) {
		uprintf("uiomove failed!\n");
	}
	return(err);
}

/*
 * echo_write½ÓÊÜÒ»¸ö×Ö·û´®²¢½«Ëü±£´æµ½»º³åÇø, ÓÃÓÚÒÔºóµÄ·ÃÎÊ. 
 */

static int
echo_write(struct cdev *dev, struct uio *uio, int ioflag)
{
	int err = 0;

	/* ½«×Ö·û´®´ÓÓû§¿Õ¼äµÄÄÚ´æ¸´ÖÆµ½Äں˿ռä */
	err = copyin(uio->uio_iov->iov_base, echomsg->msg,
	    MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1));

	/* ÏÖÔÚÐèÒªÒÔnull½áÊø×Ö·û´®£¬²¢¼Ç¼³¤¶È */
	*(echomsg->msg + MIN(uio->uio_iov->iov_len, BUFFERSIZE - 1)) = 0;
	echomsg->len = MIN(uio->uio_iov->iov_len, BUFFERSIZE);

	if (err != 0) {
		uprintf("Write failed: bad address!\n");
	}
	count++;
	return(err);
}

DEV_MODULE(echo,echo_loader,NULL);

¡¡¡¡ÔÚFreeBSD 4.XÉϰ²×°´ËÇý¶¯³ÌÐò£¬Ä㽫Ê×ÏÈÐèÒªÓÃÈçÏÂÃüÁîÔÚ ÄãµÄÎļþϵͳÉÏ´´½¨Ò»¸ö½Úµã£º

# mknod /dev/echo c 33 0

¡¡¡¡Çý¶¯³ÌÐò±»¼ÓÔØºó£¬ÄãÓ¦¸ÃÄܹ»¼üÈëһЩ¶«Î÷£¬È磺

# echo -n "Test Data" > /dev/echo
# cat /dev/echo
Test Data

¡¡¡¡ÕæÕýµÄÓ²¼þÉ豸ÔÚÏÂÒ»ÕÂÃèÊö¡£

¡¡¡¡²¹³ä×ÊÔ´


9.5 ¿éÉ豸(ÏûÍöÖÐ)

¡¡¡¡ÆäËûUNIXϵͳ֧³ÖÁíÒ»ÀàÐ͵ĴÅÅÌÉ豸£¬³ÆÎª¿éÉ豸¡£¿éÉ豸ÊÇÄÚºË ÎªËüÃÇÌṩ»º³åµÄ´ÅÅÌÉ豸¡£ÕâÖÖ»º³åʹµÃ¿éÉ豸¼¸ºõûÓÐÓ㬻òÕß˵·Ç³£ ²»¿É¿¿¡£»º³å»áÖØÐ°²ÅÅд²Ù×÷µÄ´ÎÐò£¬Ê¹µÃÓ¦ÓóÌÐòɥʧÁËÔÚÈκÎʱ¿Ì¼°Ê± ÖªµÀ׼ȷµÄ´ÅÅÌÄÚÈݵÄÄÜÁ¦¡£Õâµ¼Ö¶ԴÅÅÌÊý¾Ý½á¹¹£¨Îļþϵͳ£¬Êý¾Ý¿âµÈ£©µÄ ¿ÉÔ¤²âµÄºÍ¿É¿¿µÄ±ÀÀ£»Ö¸´³ÉΪ²»¿ÉÄÜ¡£ÓÉÓÚд²Ù×÷±»ÑÓ³Ù£¬ÄÚºËÎÞ·¨ÏòÓ¦Óà ³ÌÐò±¨¸æÄĸöÌØ¶¨µÄд²Ù×÷Óöµ½ÁËд´íÎó£¬ÕâÓÖ½øÒ»²½Ôö¼ÓÁËÒ»ÖÂÐÔÎÊÌâ¡£ ÓÉÓÚÕâ¸öÔ­Òò£¬ÕæÕýµÄÓ¦ÓóÌÐò´Ó²»ÒÀÀµÓÚ¿éÉ豸£¬ÊÂʵÉÏ£¬¼¸ºõËùÓзÃÎÊ ´ÅÅ̵ÄÓ¦ÓóÌÐò¶¼¾¡Á¦Ö¸¶¨×ÜÊÇʹÓÃ×Ö·û£¨»ò¡°raw¡±£©É豸¡£ ÓÉÓÚʵÏÖ½«Ã¿¸ö´ÅÅÌ£¨·ÖÇø£©Í¬¾ßÓв»Í¬ÓïÒåµÄÁ½¸öÉ豸»ìΪһ̸£¬´Ó¶øÖÂʹ Ïà¹ØÄں˴úÂ뼫´óµØ¸´ÔÓ»¯£¬×÷ÎªÍÆ½ø´ÅÅÌI/O»ù´¡½á¹¹ÏÖ´ú»¯µÄÒ»²¿·Ö£¬FreeBSD ÅׯúÁ˶Դø»º³åµÄ´ÅÅÌÉ豸µÄÖ§³Ö¡£


9.6 ÍøÂçÉ豸Çý¶¯³ÌÐò

¡¡¡¡·ÃÎÊÍøÂçÉ豸µÄÇý¶¯³ÌÐò²»ÐèҪʹÓÃÉ豸½Úµã¡£Ñ¡ÔñÄĸöÇý¶¯³ÌÐòÊÇ »ùÓÚÄÚºËÄÚ²¿µÄÆäËû¾ö¶¨¶ø²»Êǵ÷ÓÃopen()£¬¶ÔÍøÂçÉ豸µÄʹÓÃͨ³£ÓÉ ÏµÍ³µ÷ÓÃsocket(2)ÒýÈë¡£

¡¡¡¡¸ü¶àϸ½Ú£¬ Çë²Î¼û ifnet(9) Áª»úÊֲᡢ »Ø»·É豸µÄÔ´´úÂ룬 ÒÔ¼° Bill Paul ׫дµÄÍøÂçÇý¶¯³ÌÐò¡£


µÚ10Õ ¡¡ISAÉ豸Çý¶¯³ÌÐò

д×÷£ºSergey Babkin. ¸Ä±àΪÊֲ᣺Murray Stokely¡¢ Valentino Vaschetto ºÍ Wylie Stilwell. ·­Ò룺spellar @SMTH.

10.1 ¸ÅÊö

¡¡¡¡±¾Õ½éÉÜÁ˱àдISAÉ豸Çý¶¯³ÌÐòÏà¹ØµÄһЩÎÊÌâ¡£Õâ¶ùչʾµÄα´úÂë Ï൱Ïêϸ£¬ºÜÈÝÒ×ÈÃÈËÁªÏëµ½ÕæÕýµÄ´úÂ룬²»¹ýÕâÒÀÈ»½ö½öÊÇα´úÂë¡£ Ëü±ÜÃâÁËÓëËùÌÖÂÛµÄÖ÷ÌâÎ޹صÄϸ½Ú¡£ÕæÊµµÄÀý×Ó¿ÉÒÔÔÚʵ¼ÊÇý¶¯³ÌÐòµÄ Ô´´úÂëÖÐÕÒµ½¡£epºÍaha ¸üÊÇÐÅÏ¢µÄºÃÀ´Ô´¡£


10.2 »ù±¾ÐÅÏ¢

¡¡¡¡µäÐ͵ÄISAÇý¶¯³ÌÐòÐèÒªÒÔϰüº¬Îļþ£º

#include <sys/module.h>
#include <sys/bus.h>
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>

#include <isa/isavar.h>
#include <isa/pnpvar.h>

¡¡¡¡ËüÃÇÃèÊöÁËÕë¶ÔISAºÍͨÓÃ×ÜÏß×ÓϵͳµÄ¶«Î÷¡£

¡¡¡¡×ÜÏß×ÓϵͳÊÇÒÔÃæÏò¶ÔÏóµÄ·½Ê½ÊµÏֵ쬯äÖ÷Òª½á¹¹Í¨¹ýÏà¹ØÁªµÄ ·½·¨º¯ÊýÀ´·ÃÎÊ¡£

¡¡¡¡ISAÇý¶¯³ÌÐòʵÏÖµÄ×ÜÏß·½·¨µÄÁбíÓëÈÎºÎÆäËû×ÜÏߵĺÜÏàËÆ¡£ ¶ÔÓÚÃû×ÖΪ¡°xxx¡±µÄ¼ÙÏëÇý¶¯³ÌÐò£¬ËüÃǽ«ÊÇ£º

  • static void xxx_isa_identify (driver_t *, device_t); ͨ³£ÓÃÓÚ×ÜÏßÇý¶¯³ÌÐò¶ø²»ÊÇÉ豸Çý¶¯³ÌÐò¡£ µ«¶ÔÓÚISAÉ豸£¬Õâ¸ö·½·¨ÓÐÌØÊâÓÃ;£ºÈç¹ûÉ豸ÌṩijЩÉè±¸ÌØ¶¨µÄ £¨·ÇPnP£©·½·¨×Ô¶¯Õì²âÉ豸£¬Õâ¸öÀý³Ì¿ÉÒÔʵÏÖËü¡£

  • static int xxx_isa_probe (device_t dev); ÔÚÒÑÖª£¨»òPnP£©Î»ÖÃ̽²âÉ豸¡£¶ÔÓÚÒѾ­²¿·ÖÅäÖÃµÄ É豸£¬Õâ¸öÀý³ÌÒ²Äܹ»ÌṩÉè±¸ÌØ¶¨µÄ¶ÔijЩ²ÎÊýµÄ×Ô¶¯Õì²â¡£

  • static int xxx_isa_attach (device_t dev); ¹Ò½ÓºÍ³õʼ»¯É豸¡£

  • static int xxx_isa_detach (device_t dev); Ð¶ÔØÉ豸Çý¶¯Ä£¿éǰ½â¹ÒÉ豸¡£

  • static int xxx_isa_shutdown (device_t dev); ϵͳ¹Ø±ÕǰִÐÐÉ豸µÄ¹Ø±Õ¡£

  • static int xxx_isa_suspend (device_t dev); ϵͳ½øÈë½ÚÄÜ״̬ǰ¹ÒÆðÉ豸¡£Ò²¿ÉÒÔÖÐÖ¹ Çл»µ½½ÚÄÜ״̬¡£

  • static int xxx_isa_resume (device_t dev); ´Ó½ÚÄÜ״̬·µ»Øºó»Ö¸´É豸µÄ»î¶¯×´Ì¬¡£

¡¡¡¡xxx_isa_probe()ºÍ xxx_isa_attach()ÊDZØÐëÌṩµÄ£¬ÆäÓàÀý³Ì¸ù¾ÝÉ豸µÄ ÐèÒª¿ÉÒÔÓÐÑ¡ÔñµØÊµÏÖ¡£

¡¡¡¡Ê¹ÓÃÏÂÃæÒ»×éÃèÊö·û½«É豸Çý¶¯Á´½Óµ½ÏµÍ³¡£

    /* Ö§³ÖµÄ×ÜÏß·½·¨±í */
    static device_method_t xxx_isa_methods[] = {
        /* ÁгöÇý¶¯³ÌÐòÖ§³ÖµÄËùÓÐ×ÜÏß·½·¨º¯Êý */
        /* ÂÔÈ¥²»Ö§³ÖµÄº¯Êý */
        DEVMETHOD(device_identify,  xxx_isa_identify),
        DEVMETHOD(device_probe,     xxx_isa_probe),
        DEVMETHOD(device_attach,    xxx_isa_attach),
        DEVMETHOD(device_detach,    xxx_isa_detach),
        DEVMETHOD(device_shutdown,  xxx_isa_shutdown),
        DEVMETHOD(device_suspend,   xxx_isa_suspend),
        DEVMETHOD(device_resume,    xxx_isa_resume),

	{ 0, 0 }
    };

    static driver_t xxx_isa_driver = {
        "xxx",
        xxx_isa_methods,
        sizeof(struct xxx_softc),
    };


    static devclass_t xxx_devclass;

    DRIVER_MODULE(xxx, isa, xxx_isa_driver, xxx_devclass,
        load_function, load_argument);

¡¡¡¡´Ë´¦µÄ½á¹¹xxx_softcÊÇÒ»¸öÉ豸 ÌØ¶¨µÄ½á¹¹£¬Ëü°üº¬Ë½ÓеÄÇý¶¯³ÌÐòÊý¾ÝºÍÇý¶¯³ÌÐò×ÊÔ´µÄÃèÊö·û¡£ ×ÜÏß´úÂë»á×Ô¶¯°´ÐèҪΪÿ¸öÉ豸·ÖÅäÒ»¸ösoftcÃèÊö·û¡£

¡¡¡¡Èç¹ûÇý¶¯³ÌÐò×÷Ϊ¿É¼ÓÔØÄ£¿éʵÏÖ£¬µ±Çý¶¯³ÌÐò±»¼ÓÔØ»òÐ¶ÔØÊ±£¬ »áµ÷ÓÃload_function()º¯Êý½øÐÐÇý¶¯³ÌÐòÌØ¶¨µÄ ³õʼ»¯»òÇåÀí¹¤×÷£¬²¢½«load_argument×÷Ϊº¯ÊýµÄÒ»¸ö²ÎÁ¿´«µÝ½øÈ¥¡£ Èç¹ûÇý¶¯³ÌÐò²»Ö§³Ö¶¯Ì¬¼ÓÔØ£¨»»¾ä»°Ëµ£¬Ëü±ØÐë±»Á´½Óµ½ÄÚºËÖУ©£¬Ôò ÕâЩֵӦµ±±»ÉèÖÃΪ0£¬×îºóµÄ¶¨Ò彫¿´ÆðÀ´ÈçÏÂËùʾ£º

 DRIVER_MODULE(xxx, isa, xxx_isa_driver,
       xxx_devclass, 0, 0);

¡¡¡¡Èç¹ûÇý¶¯³ÌÐòÊÇΪ֧³ÖPnPµÄÉ豸¶øÐ´µÄ£¬ÄÇô¾Í±ØÐ붨ÒåÒ»¸ö°üº¬ ËùÓÐÖ§³ÖµÄPnP IDµÄ±í¡£Õâ¸ö±íÓÉ´ËÇý¶¯³ÌÐòËùÖ§³ÖµÄPnP IDµÄÁÐ±í ºÍÒÔÈ˿ɶÁµÄÐÎʽ¸ø³öµÄ¡¢ÓëÕâЩID¶ÔÓ¦µÄÓ²¼þÀàÐͺÍÐͺŵÄÃèÊö ×é³É¡£¿´ÆðÀ´ÈçÏ£º

    static struct isa_pnp_id xxx_pnp_ids[] = {
        /* ÿ¸öËùÖ§³ÖµÄPnP IDÕ¼Ò»ÐÐ */
        { 0x12345678,   "Our device model 1234A" },
        { 0x12345679,   "Our device model 1234B" },
        { 0,        NULL }, /* ±í½áÊø */
    };

¡¡¡¡Èç¹ûÇý¶¯³ÌÐò²»Ö§³ÖPnPÉ豸£¬ËüÈÔÈ»ÐèÒªÒ»¸ö¿ÕµÄPnP ID±í£¬ ÈçÏÂËùʾ£º

    static struct isa_pnp_id xxx_pnp_ids[] = {
        { 0,        NULL }, /* ±í½áÊø */
    };

10.3 Device_tÖ¸Õë

¡¡¡¡Device_tÊÇΪÉ豸½á¹¹¶ø¶¨ÒåµÄÖ¸ÕëÀàÐÍ£¬ ÕâÀïÎÒÃÇÖ»¹ØÐÄ´ÓÉ豸Çý¶¯³ÌÐò±àдÕߵĽǶȿ´¸ÐÐËȤµÄ·½·¨¡£ÏÂÃæµÄ·½·¨ ÓÃÀ´²Ù×ÝÉ豸½á¹¹ÖеÄÖµ£º

¡¡¡¡

  • device_t device_get_parent(dev) »ñÈ¡É豸µÄ¸¸×ÜÏß¡£

  • driver_t device_get_driver(dev) »ñȡָÏòÆäÇý¶¯³ÌÐò½á¹¹µÄÖ¸Õë¡£

  • char *device_get_name(dev) »ñÈ¡Çý¶¯³ÌÐòµÄÃû×Ö£¬ÔÚÎÒÃÇµÄ Àý×ÓÖÐΪ"xxx"¡£

  • int device_get_unit(dev) »ñÈ¡µ¥ÔªºÅ£¨Óëÿ¸öÇý¶¯³ÌÐò¹ØÁªµÄÉ豸´Ó0¿ªÊ¼±àºÅ£©¡£

  • char *device_get_nameunit(dev) »ñÈ¡É豸Ãû£¬°üÀ¨µ¥ÔªºÅ¡£ ÀýÈç¡°xxx0¡±£¬¡°xxx1¡± µÈ¡£

  • char *device_get_desc(dev) »ñÈ¡É豸ÃèÊö¡£Í¨³£ËüÒÔÈ˿ɶÁµÄ ÐÎʽÃèÊöÉ豸µÄÈ·ÇÐÐͺš£

  • device_set_desc(dev, desc)ÉèÖÃÃèÊöÐÅÏ¢¡£ÕâʹµÃÉ豸ÃèÊöÖ¸Ïòdesc×Ö·û´®£¬ ´ËºóÕâ¸ö×Ö·û´®¾Í²»Äܱ»½â³ý·ÖÅä¡£

  • device_set_desc_copy(dev, desc) ÉèÖÃÃèÊöÐÅÏ¢¡£ÃèÊö±»¿½±´µ½ÄÚ²¿¶¯Ì¬·ÖÅäµÄ »º³åÇø£¬ÕâÑùdesc×Ö·û´®ÔÚÒÔºó¿ÉÒÔ±»¸Ä±ä¶ø²»»á²úÉúÓк¦µÄ½á¹û¡£

  • void *device_get_softc(dev) »ñȡָÏòÓëÉ豸¹ØÁªµÄÉ豸ÃèÊö·û £¨xxx_softc½á¹¹£©µÄÖ¸Õë¡£

  • u_int32_t device_get_flags(dev) »ñÈ¡ÅäÖÃÎļþÖÐÌØ¶¨ÓÚÉ豸µÄ ±êÖ¾¡£

¡¡¡¡¿ÉÒÔʹÓÃÒ»¸öºÜ·½±ãµÄº¯Êýdevice_printf(dev, fmt, ...)´ÓÉ豸Çý¶¯³ÌÐòÖдòӡѶϢ¡£Ëü×Ô¶¯ÔÚѶϢǰÌí¼Ó µ¥ÔªÃûºÍðºÅ¡£

¡¡¡¡device_tµÄÕâЩ·½·¨ÔÚÎļþkern/bus_subr.c ÖÐʵÏÖ¡£


10.4 ÅäÖÃÎļþÓë×Ô¶¯ÅäÖÃÆÚ¼äʶ±ðºÍ̽²âµÄ˳Ðò

¡¡¡¡ISAÉ豸ÔÚÄÚºËÅäÖÃÎļþÖеÄÃèÊöÈçÏ£º

device xxx0 at isa? port 0x300 irq 10 drq 5
       iomem 0xd0000 flags 0x1 sensitive

¡¡¡¡¶Ë¿ÚÖµ¡¢IRQÖµºÍÆäËûÖµ±»×ª»»³ÉÓëÉ豸¹ØÁªµÄ×ÊÔ´Öµ¡£¸ù¾ÝÉ豸 ¶Ô×Ô¶¯ÅäÖÃÐèÒªºÍÖ§³Ö³Ì¶ÈµÄ²»Í¬£¬ÕâЩֵÊÇ¿ÉÑ¡µÄ¡£ÀýÈ磬 ijЩÉ豸¸ù±¾²»ÐèÒª¶ÁDRQ£¬¶øÓÐЩÔòÔÊÐíÉ豸´ÓÉ豸ÅäÖö˿ڶÁÈ¡ IRQÉèÖá£Èç¹û»úÆ÷Óжà¸öISA×ÜÏߣ¬¿ÉÒÔÔÚÅäÖÃÎļþÖÐÃ÷È·Ö¸¶¨ÄÄÌõ ×ÜÏߣ¬Èçisa0»òisa1£¬ ·ñÔò½«ÔÚËùÓÐISA×ÜÏßÉÏËÑË÷É豸¡£

¡¡¡¡Ãô¸Ð(sensitive)ÊÇÒ»ÖÖ×ÊÔ´ÇëÇó£¬Ëüָʾ ±ØÐëÔÚËùÓзÇÃô¸ÐÉ豸֮ǰ̽²âÉ豸¡£´ËÌØÐÔËä±»Ö§³Ö£¬µ«Ëƺõ´Óδ ÔÚĿǰµÄÈκÎÇý¶¯³ÌÐòÖÐʹÓùý¡£

¡¡¡¡¶ÔÓÚÀϵÄISAÉ豸£¬ºÜ¶àÇé¿öÏÂÇý¶¯³ÌÐòÈÔÈ»Äܹ»Õì²âÅäÖòÎÊý¡£ µ«ÊÇϵͳÖÐÅäÖõÄÿ¸öÉ豸±ØÐë¾ßÓÐÒ»¸öÅäÖÃÐС£Èç¹ûϵͳÖÐ×°ÓÐͬһ ÀàÐ͵ÄÁ½¸öÉ豸£¬µ«¶ÔÓ¦µÄÇý¶¯³ÌÐòÈ´Ö»ÓÐÒ»¸öÅäÖÃÐУ¬ÀýÈç:

device xxx0 at isa?
ÄÇôֻÓÐÒ»¸öÉ豸»á±»ÅäÖá£

¡¡¡¡µ«¶ÔÓÚÖ§³Öͨ¹ýPnP»òרÓÐЭÒé½øÐÐ×Ô¶¯Ê¶±ðµÄÉ豸£¬Ò»¸öÅäÖÃÐÐ ¾Í×ã¹»ÅäÖÃϵͳÖеÄËùÓÐÉ豸£¬ÈçÉÏÃæµÄÅäÖÃÐУ¬»òÕß¼òµ¥µØ£º

device xxx at isa?

¡¡¡¡Èç¹ûÉ豸Çý¶¯³ÌÐò¼ÈÖ§³ÖÄÜ×Ô¶¯Ê¶±ðµÄÉ豸ÓÖÖ§³ÖÀÏÉ豸£¬²¢ÇÒ Á½ÀàÉ豸ͬʱ°²×°ÔÚһ̨»úÆ÷ÉÏ£¬ÄÇôֻҪÔÚÅäÖÃÎļþÖÐÃèÊöÀÏÉ豸 ¾Í×ã¹»ÁË¡£×Ô¶¯Ê¶±ðµÄÉ豸½«±»×Ô¶¯Ìí¼Ó¡£

¡¡¡¡Èç¹ûISAÉ豸ÊÇ×Ô¶¯ÅäÖõ쬷¢ÉúµÄʼþÈçÏ£º

¡¡¡¡ËùÓÐÉ豸Çý¶¯³ÌÐòµÄʶ±ðÀý³Ì£¨°üÀ¨Ê¶±ðËùÓÐPnPÉ豸µÄPnPʶ±ð Àý³Ì£©ÒÔËæ»ú˳Ðò±»µ÷Óá£ËûÃÇʶ±ð³öÉ豸ºó¾Í°ÑÉ豸Ìí¼Óµ½ISA×ÜÏß ÉϵÄÁбíÖС£Í¨³£Çý¶¯³ÌÐòµÄʶ±ðÀý³Ì½«ÐÂÉ豸ÓëËüÃǵÄÇý¶¯ ³ÌÐò¹ØÁªÆðÀ´¡£¶øPnPʶ±ðÀý³Ì²¢²»ÖªµÀÆäËûÇý¶¯³ÌÐò£¬Òò´Ë²»Äܽ« Çý¶¯³ÌÐòÓëËüËùÌí¼ÓµÄÐÂÉ豸¹ØÁªÆðÀ´¡£

¡¡¡¡Ê¹ÓÃPnPЭÒéÈÃPnPÉ豸½øÈë˯Ãߣ¬ÒÔ·ÀÖ¹ËüÃDZ»Ì½²âΪÀÏÉ豸¡£

¡¡¡¡±»±ê¼ÇΪÃô¸Ð(sensitive)µÄ·ÇPnPÉ豸µÄ ̽²âÀý³Ì±»µ÷Óá£Èç¹û̽²âÉ豸³É¹¦£¬ÄÇô¾ÍΪÆäµ÷ÓùҽÓ(attach) Àý³Ì¡£

¡¡¡¡ËùÓзÇPnPÉ豸µÄ̽²âºÍÁ¬½ÓÀý³ÌÒÔͬÑùµÄ·½Ê½±»µ÷Óá£

¡¡¡¡PnPÉ豸´Ó˯ÃßÖлָ´¹ýÀ´£¬²¢¸øËüÃÇ·ÖÅäËùÇëÇóµÄ×ÊÔ´£ºI/O¡¢ ÄÚ´æµØÖ··¶Î§¡¢IRQºÍDRQ£¬ËùÓÐÕâЩÓëÒÑÁ¬½ÓµÄÀÏÉ豸²»»á³åÍ»¡£

¡¡¡¡¶ÔÓÚÿ¸öPnPÉ豸£¬ËùÓÐISAÉ豸Çý¶¯³ÌÐòµÄ̽²âÀý³Ì¶¼»á±»µ÷ÓᣠµÚÒ»¸öÒªÇó´ËÉ豸µÄÇý¶¯³ÌÐò½«±»Á¬½Ó¡£¶à¸öÇý¶¯³ÌÐòÒÔ²»Í¬µÄÓÅÏÈȨ ÒªÇóÒ»¸öÉ豸µÄÇé¿öÊÇ¿ÉÄܵģ¬ÕâÖÖÇé¿öÏ£¬¾ßÓÐ×î¸ßÓÅÏÈȨµÄÇý¶¯³ÌÐò ½«»ñʤ¡£Ì½²âÀý³Ì±ØÐëµ÷ÓÃISA_PNP_PROBE()½« ÕæÊµµÄPnP IDºÍÇý¶¯³ÌÐòÖ§³ÖµÄIDÁбí×÷±È½Ï£¬Èç¹ûID²»ÔÚ±íÖÐÔò·µ»Ø ʧ°Ü¡£ÕâÒâζ×Åÿ¸öÇý¶¯³ÌÐò£¬°üÀ¨²»Ö§³ÖÈκÎPnPÉ豸µÄÇý¶¯³ÌÐò£¬ ¶¼±ØÐë¶Ôδ֪µÄPnPÉ豸ÎÞÌõ¼þµ÷Óà ISA_PNP_PROBE()£¬¶ÔÓÚδ֪É豸£¬ ÖÁÉÙÒªÓÃÒ»¸ö ¿ÕµÄPnP ID±íµ÷Óò¢·µ»ØÊ§°Ü¡£

¡¡¡¡Ì½²âÀý³ÌÓöµ½´íÎóʱ»á·µ»ØÒ»¸öÕýÖµ£¨´íÎóÂ룩£¬³É¹¦Ê±·µ»Ø Áã»ò¸ºÖµ¡£

¡¡¡¡¸ºµÄ·µ»ØÖµÓÃÓÚPnPÉ豸֧³Ö¶à¸ö½Ó¿ÚµÄÇé¿ö¡£ÀýÈ磬ÀϵļæÈÝ½Ó¿Ú ºÍеĸ߼¶½Ó¿Úͨ¹ý²»Í¬µÄÇý¶¯³ÌÐòÀ´Ìṩ֧³Ö¡£Á½¸öÇý¶¯³ÌÐò ¶¼Õì²âÉ豸¡£ÔÚ̽²âÀý³ÌÖзµ»Ø½Ï¸ßÖµµÄÇý¶¯³ÌÐòÓÅÏÈ£¨»»¾ä»°Ëµ£¬ ·µ»Ø0µÄÇý¶¯³ÌÐò¾ßÓÐ×î¸ßµÄÓÅÏȼ¶£¬·µ»Ø-1µÄÆä´Î£¬·µ»Ø-2µÄ¸üÔÚ Æäºó£¬Èç´ËÏÂÈ¥£©¡£Èç¹û¶à¸öÇý¶¯³ÌÐò·µ»ØÏàͬµÄÖµ£¬ÄÇô×îÏȵ÷ÓÃµÄ »ñʤ¡£Òò´Ë£¬Èç¹ûÇý¶¯³ÌÐò·µ»Ø0£¬¾Í»ù±¾Äܹ»È·ÐÅËü»ñµÃÓÅÏÈȨÖٲá£

¡¡¡¡Éè±¸ÌØ¶¨µÄʶ±ðÀý³ÌÒ²Äܹ»½«Ò»Àà¶ø²»Êǵ¥¸öÇý¶¯³ÌÐòÖ¸ÅɸøÉ豸¡£ ¾ÍÏóʹÓÃPnPµÄÇé¿öÒ»Ñù£¬¶ÔÓÚijһÉ豸£¬»á̽²âÕâÒ»ÀàÖÐËùÓеÄÇý¶¯³ÌÐò¡£ ÓÉÓÚÕâ¸öÌØÐÔÔÚÈκÎÏÖ´æµÄÇý¶¯³ÌÐòÖÐ×ܾùδʵÏÖ£¬¹Ê±¾ÎĵµÖв»ÔÙÓèÒÔ ¿¼ÂÇ¡£

¡¡¡¡ÓÉÓÚ̽²âÀÏÉ豸µÄʱºòPnPÉ豸±»½ûÓã¬ËüÃDz»»á±»Á¬½ÓÁ½´Î £¨Ò»´Î×÷ΪÀÏÉ豸£¬Ò»´Î×÷ΪPnP£©¡£µ«Èç¹ûʶ±ðÀý³ÌÉ豸Ïà¹ØµÄ£¬ ÕâÖÖÇé¿öÏÂÉ豸Çý¶¯³ÌÐòÓÐÔðÈÎÈ·±£Í¬Ò»É豸²»»á±»É豸Çý¶¯³ÌÐò Á¬½ÓÁ½´Î£ºÒ»´Î×÷ΪÀϵÄÓÉÓû§ÅäÖõģ¬Ò»´Î×÷Ϊ×Ô¶¯Ê¶±ðµÄ¡£

¡¡¡¡¶ÔÓÚ×Ô¶¯Ê¶±ðµÄÉ豸£¨°üÀ¨PnPºÍÉè±¸ÌØ¶¨µÄ£©µÄÁíÒ»¸öʵ¼ù½áÂÛÊÇ£¬ ²»ÄÜ´ÓÄÚºËÅäÖÃÎļþÖÐÏòËüÃÇ´«µÝÆì±ê¡£Òò´ËËüÃDZØÐëҪô¸ù±¾²»Ê¹Óà Æì±ê£¬ÒªÃ´ÎªËùÓÐ×Ô¶¯Ê¶±ðµÄÉ豸ʹÓõ¥ÔªºÅΪ0µÄÉ豸µÄÆì±ê£¬»òÕß Ê¹ÓÃsysctl½Ó¿Ú¶ø²»ÊÇÆì±ê¡£

¡¡¡¡Í¨¹ýʹÓú¯Êý×åresource_query_*()ºÍ resource_*_value()Ö±½Ó·ÃÎÊÅäÖÃ×ÊÔ´£¬ ´Ó¶ø¿ÉÒÔÌṩÆäËû²»³£ÓõÄÅäÖá£ËüÃǵÄʵÏÖλÓÚ kern/subr_bus.c¡£ÀϵÄIDE´ÅÅÌÇý¶¯Æ÷ i386/isa/wd.c°üº¬ÕâÑùʹÓõÄÀý×Ó¡£ µ«±ØÐëÓÅÏÈʹÓÃÅäÖõıê×¼·½·¨¡£½«½âÎöÅäÖÃ×ÊÔ´ÕâÀàÊÂÇéÁô¸ø ×ÜÏßÅäÖôúÂë¡£


10.5 ×ÊÔ´

¡¡¡¡Óû§Ð´Èëµ½ÄÚºËÅäÖÃÎļþÖеÄÐÅÏ¢±»×÷ΪÅäÖÃ×ÊÔ´´¦Àí£¬²¢´«µÝµ½Äںˡ£ ×ÜÏßÅäÖôúÂë½âÎöÕⲿ·ÖÐÅÏ¢²¢½«Æäת»»Îª½á¹¹device_tµÄÖµºÍÓëÖ® ¹ØÁªµÄ×ÜÏß×ÊÔ´¡£¶ÔÓÚ¸´ÔÓÇé¿öϵÄÅäÖã¬Çý¶¯³ÌÐò¿ÉÒÔÖ±½ÓʹÓà resource_* º¯Êý·ÃÎÊÅäÖÃ×ÊÔ´¡£ È»¶ø£¬ ͨ³£¼È²»ÐèÒªÒ²²»ÍƼöÕâÑù×ö£¬ Òò´ËÕâ¶ù²»ÔÙ½øÒ»²½ÌÖÂÛÕâ¸öÎÊÌâ¡£

¡¡¡¡×ÜÏß×ÊÔ´Óëÿ¸öÉ豸Ïà¹ØÁª¡£Í¨¹ýÀàÐͺÍÀàÐÍÖеÄÊý×Ö±êʶËüÃÇ¡£ ¶ÔÓÚISA×ÜÏߣ¬¶¨ÒåÁËÏÂÃæµÄÀàÐÍ£º

  • SYS_RES_IRQ - ÖжϺÅ

  • SYS_RES_DRQ - ISA DMAͨµÀºÅ

  • SYS_RES_MEMORY - Ó³É䵽ϵͳÄÚ´æ¿Õ¼ä µÄÉ豸ÄÚ´æµÄ·¶Î§

  • SYS_RES_IOPORT - É豸I/O¼Ä´æÆ÷µÄ·¶Î§

¡¡¡¡ÀàÐÍÄÚµÄö¾Ù´Ó0¿ªÊ¼£¬Òò´ËÈç¹ûÉ豸ÓÐÁ½¸öÄÚ´æÇøÓò£¬ËüµÄ SYS_RES_MEMORY ÀàÐ͵Ä×ÊÔ´±àºÅΪ0ºÍ1¡£ ×ÊÔ´ÀàÐÍÓëCÓïÑÔµÄÀàÐÍÎ޹أ¬ ËùÓÐ×ÊÔ´Öµ¾ßÓÐCÓïÑÔ unsigned long ÀàÐÍ£¬²¢ÇÒ±ØÒªÊ±±ØÐë½øÐÐÀàÐÍÇ¿ÖÆ×ª»» (cast)¡£×ÊÔ´ºÅ²»±ØÁ¬Ðø£¬ ¾¡¹Ü¶ÔÓÚISAËüÃÇÒ»°ãÊÇÁ¬ÐøµÄ¡£ISAÉ豸ÔÊÐíµÄ×ÊÔ´±àºÅΪ£º

          IRQ: 0-1
          DRQ: 0-1
          MEMORY: 0-3
          IOPORT: 0-7

¡¡¡¡ËùÓÐ×ÊÔ´±»±íʾΪ´øÓÐÆðʼֵºÍ¼ÆÊýµÄ·¶Î§¡£¶ÔÓÚIRQºÍDRQ×ÊÔ´£¬ ¼ÆÊýÒ»°ãµÈÓÚ1¡£ÄÚ´æµÄÖµÒýÓÃÎïÀíµØÖ·¡£

¡¡¡¡¶Ô×ÊÔ´Äܹ»Ö´ÐÐÈýÖÖÀàÐ͵͝×÷£º

  • set/get

  • allocate/release

  • activate/deactivate

¡¡¡¡SetÉèÖÃ×ÊԴʹÓõķ¶Î§¡£Allocation±£Áô³öÇëÇóµÄ·¶Î§£¬Ê¹µÃ ÆäËüÉ豸²»ÄÜÔÙÕ¼Ó㨲¢¼ì²é´Ë·¶Î§Ã»Óб»ÆäËüÉ豸ռÓã©¡£ ActivationÖ´ÐбØÒªµÄ¶¯×÷ʹµÃÇý¶¯³ÌÐò¿ÉÒÔ·ÃÎÊ×ÊÔ´£¨ÀýÈ磬¶ÔÓÚ Äڴ棬Ëü½«±»Ó³Éäµ½Äں˵ÄÐéÄâµØÖ·¿Õ¼ä£©¡£

¡¡¡¡²Ù×÷×ÊÔ´µÄº¯ÊýÓУº

  • int bus_set_resource(device_t dev, int type, int rid, u_long start, u_long count)

    Ϊ×ÊÔ´ÉèÖ÷¶Î§¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£ Ò»°ã´Ëº¯ÊýÖ»ÓÐÔÚtype£¬ rid£¬start»ò countÖ®Ò»µÄÖµ³¬³öÁËÔÊÐíµÄ·¶Î§²Å»á ·µ»Ø´íÎó¡£

    • dev - Çý¶¯³ÌÐòµÄÉ豸

    • type - ×ÊÔ´ÀàÐÍ£¬SYS_RES_*

    • rid - ÀàÐÍÄÚ²¿µÄ×ÊÔ´ºÅ£¨ID£©

    • start, count - ×ÊÔ´·¶Î§

  • int bus_get_resource(device_t dev, int type, int rid, u_long *startp, u_long *countp)

    È¡µÃ×ÊÔ´·¶Î§¡£³É¹¦Ôò·µ»Ø0£¬Èç¹û×ÊÔ´ÉÐ䶨ÒåÔò·µ»Ø´íÎóÂë¡£

  • u_long bus_get_resource_start(device_t dev, int type, int rid) u_long bus_get_resource_count (device_t dev, int type, int rid)

    ±ã½Ýº¯Êý£¬Ö»ÓÃÀ´»ñÈ¡start»òcount¡£³ö´íµÄÇé¿öÏ·µ»Ø0£¬ Òò´ËÈç¹û0ÊÇ×ÊÔ´µÄstartºÏ·¨ÖµÖ®Ò»£¬½«ÎÞ·¨Çø·Ö·µ»Ø µÄ0ÊÇ·ñָʾ´íÎó¡£ÐÒÔ˵ÄÊÇ£¬¶ÔÓÚ¸½¼ÓÇý¶¯³ÌÐò£¬Ã»ÓÐISA×ÊÔ´µÄ startÖµ´Ó0¿ªÊ¼¡£

  • void bus_delete_resource(device_t dev, int type, int rid)

    ɾ³ý×ÊÔ´£¬ÁîÆä䶨Òå¡£

  • struct resource * bus_alloc_resource(device_t dev, int type, int *rid, u_long start, u_long end, u_long count, u_int flags)

    ÔÚstartºÍendÖ®¼äûÓб»ÆäËüÉ豸ռÓõĵط½°´countÖµ µÄ·¶Î§·ÖÅäÒ»¸ö×ÊÔ´¡£²»¹ý£¬²»Ö§³Ö¶ÔÆë¡£Èç¹û×ÊÔ´ÉÐδ±»ÉèÖ㬠Ôò×Ô¶¯´´½¨Ëü¡£startΪ0£¬endΪ~0£¨È«1£©µÄÕâ¶ÔÌØÊâÖµ Òâζ×űØÐëʹÓÃÒÔǰͨ¹ý bus_set_resource()ÉèÖõĹ̶¨Öµ£º startºÍcount¾ÍÊÇËüÃÇ×Ô¼º£¬end=(start+count)£¬ÕâÖÖÇé¿öÏ£¬ Èç¹ûÒÔǰ×ÊԴûÓж¨Ò壬Ôò·µ»Ø´íÎó¡£¾¡¹Üridͨ¹ýÒýÓô«µÝ£¬ µ«Ëü²¢²»±»ISA×ÜÏßµÄ×ÊÔ´·ÖÅä´úÂëÉèÖã¨ÆäËü×ÜÏß¿ÉÄÜʹÓò»Í¬µÄ ·½·¨²¢¿ÉÄÜÐÞ¸ÄËü£©¡£

¡¡¡¡Æì±êÊÇÒ»¸öλӳÉ䣬µ÷ÓÃÕ߸ÐÐËȤµÄÓУº

  • RF_ACTIVE - ʹµÃ×ÊÔ´·ÖÅäºó ±»×Ô¶¯¼¤»î¡£

  • RF_SHAREABLE - ×ÊÔ´¿ÉÒÔͬʱ ±»¶à¸öÇý¶¯³ÌÐò¹²Ïí¡£

  • RF_TIMESHARE - ×ÊÔ´¿ÉÒÔ±»¶à¸öÇý¶¯ ³ÌÐò·Öʱ¹²Ïí£¬Ò²¾ÍÊÇ˵£¬±»¶à¸öÇý¶¯³ÌÐòͬʱ·ÖÅ䣬µ«ÈκΠ¸ø¶¨Ê±¼äÖ»Äܱ»ÆäÖÐÒ»¸ö¼¤»î¡£

  • ³ö´í·µ»Ø0¡£±»·ÖÅäµÄÖµ¿ÉÒÔʹÓà rhand_*()´Ó·µ»ØµÄ¾ä±ú»ñµÃ¡£

  • int bus_release_resource(device_t dev, int type, int rid, struct resource *r)

  • ÊÍ·Å×ÊÔ´£¬rΪbus_alloc_resource() ·µ»ØµÄ¾ä±ú¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£

  • int bus_activate_resource(device_t dev, int type, int rid, struct resource *r) int bus_deactivate_resource(device_t dev, int type, int rid, struct resource *r)

  • ¼¤»î»ò½ûÓÃ×ÊÔ´¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£Èç¹û ×ÊÔ´±»·Öʱ¹²ÏíÇÒµ±Ç°±»ÁíÒ»Çý¶¯³ÌÐò¼¤»î£¬Ôò·µ»Ø EBUSY¡£

  • int bus_setup_intr(device_t dev, struct resource *r, int flags, driver_intr_t *handler, void *arg, void **cookiep) int bus_teardown_intr(device_t dev, struct resource *r, void *cookie)

  • ¹ØÁª/·ÖÀëÖжϴ¦Àí³ÌÐòÓëÉ豸¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò ·µ»Ø´íÎóÂë¡£

  • r - ±»¼¤»îµÄÃèÊöIRQµÄ×ÊÔ´¾ä±ú¡£

    flags - ÖжÏÓÅÏȼ¶£¬ÈçÏÂÖ®Ò»£º

    • INTR_TYPE_TTY - ÖÕ¶ËºÍÆäËü ÀàËÆµÄ×Ö·ûÀàÐÍÉ豸¡£Ê¹Óà spltty()ÆÁ±ÎËüÃÇ¡£

    • (INTR_TYPE_TTY | INTR_TYPE_FAST) - ÊäÈ뻺³å½ÏСµÄÖÕ¶ËÀàÐÍ É豸£¬¶øÇÒÊäÈëÉϵÄÊý¾Ý¶ªÊ§ºÜ¹Ø¼ü£¨ÀýÈçÀÏʽ´®¿Ú£©¡£ ʹÓÃspltty()ÆÁ±ÎËüÃÇ¡£

    • INTR_TYPE_BIO - ¿éÀàÐÍÉ豸£¬ ²»°üÀ¨CAM¿ØÖÆÆ÷Éϵġ£Ê¹Óà splbio()ÆÁ±ÎËüÃÇ¡£

    • INTR_TYPE_CAM - CAM £¨Í¨Ó÷ÃÎÊ ·½·¨Common Access Method£©×ÜÏß¿ØÖÆÆ÷¡£Ê¹Óà splcam()ÆÁ±ÎËüÃÇ¡£

    • INTR_TYPE_NET - ÍøÂç½Ó¿Ú ¿ØÖÆÆ÷¡£Ê¹Óà splimp()ÆÁ±ÎËüÃÇ¡£

    • INTR_TYPE_MISC - ¸÷ÖÖÆäËüÉ豸¡£³ýÁËͨ¹ý splhigh()ûÓÐÆäËü·½·¨ÆÁ±ÎËüÃÇ¡£ splhigh()ÆÁ±ÎËùÓÐÖжϡ£

¡¡¡¡µ±Öжϴ¦Àí³ÌÐòÖ´ÐÐʱ£¬Æ¥ÅäÆäÓÅÏȼ¶µÄËùÓÐÆäËüÖж϶¼±»ÆÁ±Î£¬ ΨһµÄÀýÍâÊÇMISC¼¶±ð£¬Ëü²»»áÆÁ±ÎÆäËüÖжϣ¬Ò²²»»á±»ÆäËüÖÐ¶Ï ÆÁ±Î¡£

  • handler - Ö¸Ïò´¦Àí³ÌÐòµÄÖ¸Õ룬 ÀàÐÍdriver_intr_t±»¶¨ÒåΪvoid driver_intr_t(void *)

  • arg - ´«µÝ¸ø´¦Àí³ÌÐòµÄ²ÎÁ¿£¬±êʶ ÌØ¶¨É豸¡£ÓÉ´¦Àí³ÌÐò½«Ëü´Óvoid*ת»»ÎªÈκÎʵ¼ÊÀàÐÍ¡£ISA Öжϴ¦Àí³ÌÐòµÄ¾ÉÔ¼¶¨ÊÇʹÓõ¥ÔªºÅ×÷Ϊ²ÎÁ¿£¬ÐÂÔ¼¶¨£¨ÍƼö£© ʹÓÃÖ¸ÏòÉ豸softc½á¹¹µÄÖ¸Õë¡£

  • cookie[p] - ´Ó setup()½ÓÊÕµÄÖµ£¬µ±´«µÝ¸ø teardown() ʱÓÃÓÚ±êʶ´¦Àí³ÌÐò¡£

¡¡¡¡¶¨ÒåÁËÈô¸É·½·¨À´²Ù×÷×ÊÔ´¾ä±ú(struct resource *)¡£É豸Çý¶¯ ³ÌÐò±àдÕ߸ÐÐËȤµÄÓУº

  • u_long rman_get_start(r) u_long rman_get_end(r) È¡µÃ±»·ÖÅäµÄ×ÊÔ´·¶Î§µÄÆðʼºÍ½áÊø¡£

  • void *rman_get_virtual(r) È¡µÃ ±»¼¤»îµÄÄÚ´æ×ÊÔ´µÄÐ鵨ַ¡£


10.6 ×ÜÏßÄÚ´æÓ³Éä

¡¡¡¡ºÜ¶àÇé¿öÏÂÉ豸Çý¶¯³ÌÐòºÍÉ豸֮¼äµÄÊý¾Ý½»»»ÊÇͨ¹ýÄÚ´æ ½øÐеġ£ÓÐÁ½ÖÖ¿ÉÄܵıäÌ壺

¡¡¡¡(a) ÄÚ´æÎ»ÓÚÉ豸¿¨ÉÏ

¡¡¡¡(b) ÄÚ´æÎª¼ÆËã»úµÄÖ÷ÄÚ´æ

¡¡¡¡Çé¿ö(a)ÖУ¬Çý¶¯³ÌÐò¿ÉÄÜÐèÒªÔÚ¿¨ÉϵÄÄÚ´æÓëÖ÷´æÖ®¼äÀ´»Ø ¿½±´Êý¾Ý¡£ÎªÁ˽«¿¨ÉϵÄÄÚ´æÓ³Éäµ½Äں˵ÄÐ鵨ַ¿Õ¼ä£¬¿¨ÉÏÄÚ´æµÄ ÎïÀíµØÖ·ºÍ³¤¶È±ØÐë±»¶¨ÒåΪSYS_RES_MEMORY×ÊÔ´¡£ È»ºó×ÊÔ´¾Í¿ÉÒÔ±»·ÖÅä²¢¼¤»î£¬ËüµÄÐéµØÖ·Í¨¹ýʹÓà rman_get_virtual()»ñÈ¡¡£½ÏÀϵÄÇý¶¯³ÌÐò ½«º¯Êýpmap_mapdev()ÓÃÓÚ´ËÄ¿µÄ£¬ÏÖÔÚ ²»Ó¦µ±ÔÙÖ±½ÓʹÓô˺¯Êý¡£ËüÒѳÉΪ×ÊÔ´¼¤»îµÄÒ»¸öÄÚ²¿²½Öè¡£

¡¡¡¡´ó¶àÊýISA¿¨µÄÄÚ´æÅäÖÃΪÎïÀíµØÎ»ÓÚ640KB-1MB·¶Î§Ö®¼äµÄ ij¸öλÖá£Ä³Ð©ISA¿¨ÐèÒª¸ü´óµÄÄڴ淶Χ£¬Î»ÓÚ16MÒÔϵÄij¸ö λÖã¨ÓÉÓÚISA×ÜÏßÉÏ24λµØÖ·ÏÞÖÆ£©¡£ÕâÖÖÇé¿öÏ£¬Èç¹û»úÆ÷ÓÐ ±ÈÉ豸ÄÚ´æµÄÆðʼµØÖ·¸ü¶àµÄÄڴ棨»»¾ä»°Ëµ£¬ËüÃÇÖØµþ£©£¬Ôò ±ØÐëÔÚ±»É豸ʹÓõÄÄÚ´æÆðʼµØÖ·´¦ÅäÖÃÒ»¸öÄÚ´æ¿Õ¶´¡£Ðí¶à BIOSÔÊÐíÔÚÆðʼÓÚ14MB»ò15MB´¦ÅäÖÃ1MµÄÄÚ´æ¿Õ¶´¡£Èç¹ûBIOS ÕýÈ·µØ±¨¸æÄÚ´æ¿Õ¶´£¬FreeBSD¾ÍÄܹ»ÕýÈ·´¦ÀíËüÃÇ£¨´ËÌØÐÔ ÔÚÀÏBIOSÉÏ¿ÉÄÜ»á³öÎÊÌ⣩¡£

¡¡¡¡Çé¿ö(b)ÖУ¬Ö»ÊÇÊý¾ÝµÄµØÖ·±»·¢Ë͵½É豸£¬É豸ʹÓÃDMAʵ¼Ê ·ÃÎÊÖ÷´æÖеÄÊý¾Ý¡£´æÔÚÁ½¸öÏÞÖÆ£ºÊ×ÏÈ£¬ISA¿¨Ö»ÄÜ·ÃÎÊ16MBÒÔÏ µÄÄÚ´æ¡£Æä´Î£¬Ð鵨ַ¿Õ¼äÖÐÁ¬ÐøµÄÒ³ÃæÔÚÎïÀíµØÖ·¿Õ¼äÖпÉÄܲ» Á¬Ðø£¬É豸¿ÉÄܲ»µÃ²»½øÐзÖÉ¢/ÊÕ¼¯²Ù×÷¡£×ÜÏß×ÓϵͳΪÕâЩÎÊÌâ ÌṩÏÖ³ÉÏֳɵĽâ¾ö°ì·¨£¬Ê£ÏµıØÐëÓÉÇý¶¯³ÌÐò×Ô¼ºÍê³É¡£

¡¡¡¡DMAÄÚ´æ·ÖÅäʹÓÃÁËÁ½¸ö½á¹¹£¬ bus_dma_tag_t ºÍ bus_dmamap_t¡£ ±êÇ©£¨tag£©ÃèÊöÁËDMAÄÚ´æÒªÇóµÄÌØÐÔ¡£Ó³É䣨map£©±íʾ°´ÕÕÕâЩ ÌØÐÔ·ÖÅäµÄÄÚ´æ¿é¡£¶à¸öÓ³Éä¿ÉÒÔÓëͬһ±êÇ©¹ØÁª¡£

¡¡¡¡±êÇ©°´ÕÕ¶ÔÌØÐԵļ̳жø±»×éÖ¯³ÉÊ÷ÐͲã´Î½á¹¹¡£×Ó±êÇ©¼Ì³Ð¸¸ ±êÇ©µÄËùÓÐÒªÇ󣬿ÉÒÔÁîÆä¸üÑϸñ£¬µ«²»ÔÊÐí·Å¿íÒªÇó¡£

¡¡¡¡Ò»°ãµØ£¬Ã¿¸öÉ豸µ¥Ôª´´½¨Ò»¸ö¶¥²ã±êÇ©£¨Ã»Óи¸±êÇ©£©¡£Èç¹û ÿ¸öÉ豸ÐèÒª²»Í¬ÒªÇóµÄÄÚ´æÇø£¬ÔòΪÿ¸öÄÚ´æÇø¶¼»á´´½¨Ò»¸ö±êÇ©£¬ÕâЩ ±êÇ©×÷Ϊ¸¸±êÇ©µÄº¢×Ó¡£

¡¡¡¡Ê¹ÓñêÇ©´´½¨Ó³ÉäµÄ·½·¨ÓÐÁ½ÖÖ¡£

¡¡¡¡ÆäÒ»£¬·ÖÅäÒ»´ó¿é·ûºÏ±êǩҪÇóµÄÁ¬ÐøÄڴ棨ÒÔºó¿ÉÒÔ±»ÊÍ·Å£©¡£ ÕâÒ»°ãÓÃÓÚ·ÖÅäΪÁËÓëÉ豸ͨÐŶø´æÔÚÏà¶Ô½Ï³¤Ê±¼äµÄÄÇЩÄÚ´æÇø¡£ ½«ÕâÑùµÄÄÚ´æ¼ÓÔØµ½Ó³ÉäÖзdz£ÈÝÒ×£ºËü×ÜÊDZ»¿´×÷λÓÚÊʵ±ÎïÀí Äڴ淶ΧµÄÒ»Õû¿é¡£

¡¡¡¡Æä¶þ£¬½«ÐéÄâÄÚ´æÖеÄÈÎÒâÇøÓò¼ÓÔØµ½Ó³ÉäÖС£ÕâÆ¬ÄÚ´æµÄ ÿһҳ¶¼±»¼ì²é£¬¿´ÊÇ·ñ·ûºÏÓ³ÉäµÄÒªÇó¡£ÈçºÎ·ûºÏÔòÁôÔÚԭʼλÖᣠÈç¹û²»·ûºÏÔò·ÖÅäÒ»¸öеķûºÏÒªÇóµÄ ¡°·´µ¯Ò³Ãæ(bounce page)¡±£¬ÓÃ×÷ÖÐ¼ä´æ´¢¡£ µ±´Ó²»·ûºÏµÄÔ­Ê¼Ò³ÃæÐ´ÈëÊý¾Ýʱ£¬Êý¾ÝÊ×Ïȱ»¿½±´µ½·´µ¯Ò³Ã棬 È»ºó´Ó·´µ¯Ò³Ãæ´«µÝµ½É豸¡£µ±¶Áȡʱ£¬Êý¾Ý½«»á´ÓÉ豸µ½·´µ¯Ò³Ã棬 È»ºó±»¿½±´µ½ËüÃDz»·ûºÏµÄÔ­Ê¼Ò³Ãæ¡£Ô­Ê¼ºÍ·´µ¯Ò³ÃæÖ®¼äµÄ¿½±´ ´¦Àí±»³Æ×÷ͬ²½¡£ÕâÒ»°ãÓÃÓÚµ¥´Î´«ÊäµÄ»ù´¡Ö®ÉÏ£ºÃ¿´Î´«Êäʱ ¼ÓÔØ»º³åÇø£¬Íê³É´«Êä£¬Ð¶ÔØ»º³åÇø¡£

¡¡¡¡¹¤×÷ÔÚDMAÄÚ´æÉϵĺ¯ÊýÓУº

  • int bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment, bus_size_t boundary, bus_addr_t lowaddr, bus_addr_t highaddr, bus_dma_filter_t *filter, void *filterarg, bus_size_t maxsize, int nsegments, bus_size_t maxsegsz, int flags, bus_dma_tag_t *dmat)

    ´´½¨Ð±êÇ©¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£

    • parent - ¸¸±êÇ©»òÕßNULL£¬ NULLÓÃÓÚ´´½¨¶¥²ã±êÇ©¡£

    • alignment - ¶Ô½«Òª·ÖÅ䏸±êÇ©µÄÄÚ´æÇøµÄ¶ÔÆëÒªÇ󡣡°no specific alignment¡±Ê±ÖµÎª1¡£½öÓ¦ÓÃÓÚÒÔºóµÄ bus_dmamem_alloc()¶ø²»ÊÇ bus_dmamap_create()µ÷Óá£

    • boundary - ÎïÀíµØÖ·±ß½ç£¬ ·ÖÅäÄÚ´æÊ±²»ÄÜ´©¹ý¡£¶ÔÓÚ¡°no boundary¡± ʹÓÃ0¡£½öÓ¦ÓÃÓÚÒÔºóµÄ bus_dmamem_alloc()¶ø²»ÊÇ bus_dmamap_create()µ÷Óᣠ±ØÐëΪ2µÄ³Ë·½¡£Èç¹û¼Æ»®ÒԷDzãµþDMA·½Ê½Ê¹ÓÃÄڴ棨Ҳ¾ÍÊÇ˵£¬ DMAµØÖ·ÓÉISA DMA¿ØÖÆÆ÷Ìṩ¶ø²»ÊÇÉ豸×ÔÉí£©£¬ÔòÓÉÓÚDMAÓ²¼þ ÏÞÖÆ£¬±ß½ç±ØÐë²»ÄÜ´óÓÚ64KB (64*1024)¡£

    • lowaddr, highaddr - Ãû×ÖÉÔ΢ ÓÐЩÎ󵼡£ÕâЩֵÓÃÓÚÏÞÖÆ¿ÉÓÃÓÚÄÚ´æ·ÖÅäµÄÎïÀíµØÖ·µÄÔÊÐí ·¶Î§¡£ÆäÈ·Çк¬Òå¸ù¾ÝÒÔºó²»Í¬µÄʹÓöøÓÐËù²»Í¬¡£

      • ¶ÔÓÚbus_dmamem_alloc()£¬ ´Ó0µ½lowaddr-1µÄËùÓеØÖ·±»ÊÓΪÔÊÐí£¬¸ü¸ßµÄµØÖ·²»ÔÊÐí ʹÓá£

      • ¶ÔÓÚbus_dmamap_create()£¬ ±ÕÇø¼ä[lowaddr; highaddr]Ö®ÍâµÄËùÓеØÖ·±»ÊÓΪ¿É·ÃÎÊ¡£ ·¶Î§Ö®ÄڵĵØÖ·Ò³Ãæ±»´«µÝ¸ø¹ýÂ˺¯Êý£¬ÓÉËü¾ö¶¨ÊÇ·ñ¿É·ÃÎÊ¡£ Èç¹ûûÓÐÌṩ¹ýÂ˺¯Êý£¬ÔòÕû¸öÇø¼ä±»ÊÓΪ²»¿É·ÃÎÊ¡£

      • ¶ÔÓÚISAÉ豸£¬Õý³£Öµ£¨Ã»ÓйýÂ˺¯Êý£©Îª£º

        lowaddr = BUS_SPACE_MAXADDR_24BIT

        highaddr = BUS_SPACE_MAXADDR

    • filter, filterarg - ¹ýÂ˺¯Êý¼°Æä ²ÎÊý¡£Èç¹ûfilterΪNULL£¬Ôòµ±µ÷Óà bus_dmamap_create()ʱ£¬Õû¸öÇø¼ä [lowaddr, highaddr]±»ÊÓΪ²»¿É·ÃÎÊ¡£ ·ñÔò£¬Çø¼ä[lowaddr; highaddr]ÄÚµÄÿ¸ö±»ÊÔͼ·ÃÎʵÄÒ³ÃæµÄ ÎïÀíµØÖ·±»´«µÝ¸ø¹ýÂ˺¯Êý£¬ÓÉËü¾ö¶¨ÊÇ·ñ¿É·ÃÎÊ¡£¹ýÂ˺¯ÊýµÄ Ô­ÐÍΪ£ºint filterfunc(void *arg, bus_addr_t paddr)¡£µ±Ò³Ãæ¿ÉÒÔ±»·ÃÎÊʱËü±ØÐë ·µ»Ø0£¬·ñÔò·µ»Ø·ÇÁãÖµ¡£

    • maxsize - ͨ¹ý´Ë±êÇ©¿ÉÒÔ·ÖÅäµÄ ×î´óÄÚ´æÖµ£¨ÒÔ×ֽڼƣ©¡£ÓÐʱÕâ¸öÖµºÜÄѹÀË㣬»òÕß¿ÉÒÔÈÎÒâ´ó£¬ ÕâÖÖÇé¿öÏ£¬¶ÔÓÚISAÉ豸Õâ¸öÖµ¿ÉÒÔÉèΪ BUS_SPACE_MAXSIZE_24BIT¡£

    • nsegments - É豸֧³ÖµÄ·ÖÉ¢/ÊÕ¼¯¶Î µÄ×î´óÊýÄ¿¡£Èç¹û²»¼ÓÏÞÖÆ£¬ÔòʹÓÃÓ¦µ±Ê¹ÓÃÖµ BUS_SPACE_UNRESTRICTED¡£ ½¨Òé¶Ô¸¸±êǩʹÓÃÕâ¸öÖµ£¬¶øÎª×ÓËï±êǩָ¶¨Êµ¼ÊÏÞÖÆ¡£ nsegmentsÖµµÈÓÚ BUS_SPACE_UNRESTRICTED µÄ±êÇ©²»ÄÜÓÃÓÚʵ¼Ê¼ÓÔØÓ³É䣬½ö¿ÉÒÔ½«ËüÃÇ×÷Ϊ¸¸±êÇ©¡£ nsetments µÄʵ¼ÊÏÞÖÆ´óԼΪ250-300£¬ÔٸߵÄÖµ½«µ¼ÖÂÄں˶ÑÕ»Òç³ö£¨Ó²¼þ ÎÞ·¨Õý³£Ö§³ÖÄÇô¶àµÄ·ÖÉ¢/ÊÕ¼¯»º³åÇø£©¡£

    • maxsegsz - É豸֧³ÖµÄ·ÖÉ¢/ÊÕ¼¯¶Î µÄ×î´ó³ß´ç¡£¶ÔÓÚISAÉ豸µÄ×î´óֵΪ BUS_SPACE_MAXSIZE_24BIT¡£

    • flags - Æì±êµÄλͼ¡£¸ÐÐËȤµÄÆì±ê Ö»ÓУº

      • BUS_DMA_ALLOCNOW - ´´½¨±êǩʱ ÇëÇó·ÖÅäËùÓпÉÄÜÓõ½µÄ·´ÉäÒ³Ãæ¡£

      • BUS_DMA_ISA - ±È½ÏÉñÃØµÄÒ»¸ö±êÖ¾£¬ ½öÓÃÓÚAlpha»úÆ÷¡£i386»úÆ÷ûÓж¨ÒåËü¡£Alpha»úÆ÷µÄËùÓÐISAÉ豸 ¶¼Ó¦µ±Ê¹ÓÃÕâ¸ö±êÖ¾£¬µ«Ëƺõ»¹Ã»ÓÐÕâÑùµÄÇý¶¯³ÌÐò¡£

    • dmat - Ö¸Ïò·µ»ØµÄбêÇ©µÄ´æ´¢µÄ Ö¸Õë¡£

  • int bus_dma_tag_destroy(bus_dma_tag_t dmat)

    Ïú»Ù±êÇ©¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£

    dmat - ±»Ïú»ÙµÄ±êÇ©¡£

  • int bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags, bus_dmamap_t *mapp)

    ·ÖÅä±êÇ©ËùÃèÊöµÄÒ»¿éÁ¬ÐøÄÚ´æÇø¡£±»·ÖÅäµÄÄÚ´æµÄ´óСΪ±êÇ©µÄ maxsize¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£µ÷Óýá¹û±»ÓÃÓÚ»ñÈ¡ÄÚ´æµÄ ÎïÀíµØÖ·£¬µ«ÔÚ´Ë֮ǰ±ØÐëÓÃbus_dmamap_load() ½«Æä¼ÓÔØ¡£

    • dmat - ±êÇ©

    • vaddr - Ö¸Ïò´æ´¢µÄÖ¸Õ룬¸Ã´æ´¢¿Õ¼ä ÓÃÓÚ·µ»ØµÄ·ÖÅäÇøÓòµÄÄÚºËÐ鵨ַ¡£

    • flags - Æì±êµÄλͼ¡£Î¨Ò»¸ÐÐËȤµÄÆì±êΪ£º

      • BUS_DMA_NOWAIT - Èç¹ûÄÚ´æ²»ÄÜ Á¢¼´¿ÉÓÃÔò·µ»Ø´íÎó¡£Èç¹û´Ë±ê־ûÓÐÉèÖã¬ÔòÔÊÐíÀý³Ì ˯Ãߣ¬Ö±µ½ÄÚ´æ¿ÉÓÃΪֹ¡£

    • mapp - Ö¸Ïò·µ»ØµÄÐÂÓ³ÉäµÄ´æ´¢µÄÖ¸Õë¡£

  • void bus_dmamem_free(bus_dma_tag_t dmat, void *vaddr, bus_dmamap_t map)

    ÊÍ·ÅÓÉbus_dmamem_alloc()·ÖÅäµÄÄÚ´æ¡£ Ŀǰ£¬¶Ô·ÖÅäµÄ´øÓÐISAÏÞÖÆµÄÄÚ´æµÄÊÍ·ÅûÓÐʵÏÖ¡£Òò´Ë£¬½¨ÒéµÄ ʹÓÃÄ£ÐÍΪ¾¡¿ÉÄܳ¤Ê±¼äµØ±£³ÖºÍÖØÓ÷ÖÅäµÄÇøÓò¡£²»ÒªÇáÒ×µØ ÊÍ·ÅÄ³Ð©ÇøÓò£¬È»ºóÔÙ¶Ìʱ¼äµØ·ÖÅäËü¡£Õâ²¢²»Òâζ×Ų»Ó¦µ±Ê¹Óà bus_dmamem_free()£ºÏ£ÍûºÜ¿ìËü¾Í»á±» ÍêÕûµØÊµÏÖ¡£

    • dmat - ±êÇ©

    • vaddr - ÄÚ´æµÄÄÚºËÐ鵨ַ

    • map - ÄÚ´æµÄÓ³É䣨¸ú bus_dmamem_alloc()·µ»ØµÄÒ»Ñù£©

  • int bus_dmamap_create(bus_dma_tag_t dmat, int flags, bus_dmamap_t *mapp)

    Ϊ±êÇ©´´½¨Ó³É䣬ÒÔºóÓÃÓÚ bus_dmamap_load()¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò ·µ»Ø´íÎóÂë¡£

    • dmat - ±êÇ©

    • flags - ÀíÂÛÉÏÊÇÆì±êµÄλͼ¡£µ«»¹ ´Ó䶨Òå¹ýÈÎºÎÆì±ê£¬Òò´ËĿǰ×ÜÊÇ0¡£

    • mapp - Ö¸Ïò·µ»ØµÄÐÂÓ³ÉäµÄ´æ´¢µÄÖ¸Õë¡£

  • int bus_dmamap_destroy(bus_dma_tag_t dmat, bus_dmamap_t map)

    Ïú»ÙÓ³Éä¡£³É¹¦Ôò·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£

    • dmat - ÓëÓ³É乨ÁªµÄ±êÇ©

    • map - ½«Òª±»Ïú»ÙµÄÓ³Éä

  • int bus_dmamap_load(bus_dma_tag_t dmat, bus_dmamap_t map, void *buf, bus_size_t buflen, bus_dmamap_callback_t *callback, void *callback_arg, int flags)

    ¼ÓÔØ»º³åÇøµ½Ó³ÉäÖÐ(Ó³É䱨ÐëÊÂÏÈÓÉ bus_dmamap_create()»òÕß bus_dmamem_alloc())´´½¨¡£»º³åÇøµÄËùÓÐ Ò³Ãæ¶¼»á±»¼ì²é£¬¿´ÊÇ·ñ·ûºÏ±êÇ©µÄÒªÇ󣬲¢ÎªÄÇЩ²»·ûºÏµÄ·ÖÅä ·´µ¯Ò³Ãæ¡£»á´´½¨ÎïÀí¶ÎÃèÊö·ûµÄÊý×飬²¢½«Æä´«µÝ¸ø»Øµ÷º¯Êý¡£ »Øµ÷º¯ÊýÒÔijÖÖ·½Ê½´¦ÀíÕâ¸öÊý×顣ϵͳÖеķ´µ¯»º³åÇøÊÇÊÜÏ޵ģ¬ Òò´ËÈç¹ûÐèÒªµÄ·´µ¯»º³åÇø²»ÄÜÁ¢¼´»ñµÃ£¬Ôò½«ÇëÇóÈë¶Ó£¬µ±·´µ¯ »º³åÇø¿ÉÓÃʱÔÙµ÷Óûص÷º¯Êý¡£Èç¹û»Øµ÷º¯ÊýÁ¢¼´Ö´ÐÐÔò·µ»Ø0£¬ Èç¹ûÇëÇó±»ÅŶӣ¬µÈ´ý½«À´Ö´ÐУ¬Ôò·µ»Ø ¡°EINPROGRESS¡±¡£ºóÒ»ÖÖÇé¿öÏ£¬ ÓëÅŶӵĻص÷º¯ÊýÖ®¼äµÄͬ²½ÓÉÇý¶¯³ÌÐò¸ºÔð¡£

    • dmat - ±êÇ©

    • map - Ó³Éä

    • buf - »º³åÇøµÄÄÚºËÐ鵨ַ

    • buflen - »º³åÇøµÄ³¤¶È

    • callback, callback_arg - »Øµ÷º¯Êý¼°Æä²ÎÊý

    »Øµ÷º¯ÊýµÄÔ­ÐÍΪ£º

    void callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)

    • arg - Óë´«µÝ¸ø bus_dmamap_load()µÄcallback_arg Ïàͬ¡£

    • seg - ¶ÎÃèÊö·ûµÄÊý×é

    • nseg - Êý×éÖеÄÃèÊö·û¸öÊý

    • error - ±íʾ¶ÎÊýÄ¿Òç³ö£ºÈç±»ÉèΪ ¡°EFBIG¡±£¬ Ôò±êÇ©ÔÊÐíµÄ×î´óÊýÄ¿µÄ¶ÎÎÞ·¨ÈÝÄÉ»º³åÇø¡£ ÕâÖÖÇé¿öÏÂÊý×éÖеÄÃèÊö·ûµÄÊýĿֻÓбêÇ©Ðí¿ÉµÄÄÇô¶à¡£ ¶ÔÕâÖÖÇé¿öµÄ´¦ÀíÓÉÇý¶¯³ÌÐò¾ö¶¨£º¸ù¾ÝÏ£ÍûµÄÓïÒ壬Çý¶¯ ³ÌÐò¿ÉÒÔÊÓÆäΪ´íÎ󣬻ò½«»º³åÇø·ÖΪÁ½¸ö²¢µ¥¶À´¦ÀíµÚ¶þ¸ö¡£

    ¶ÎÊý×éÖеÄÿһÏî°üº¬ÈçÏÂ×ֶΣº

    • ds_addr - ¶ÎÎïÀíµØÖ·

    • ds_len - ¶Î³¤¶È

  • void bus_dmamap_unload(bus_dma_tag_t dmat, bus_dmamap_t map)

    unload the map.

    • dmat - ±êÇ©

    • map - ÒѼÓÔØµÄÓ³Éä

  • void bus_dmamap_sync (bus_dma_tag_t dmat, bus_dmamap_t map, bus_dmasync_op_t op)

    ÓëÉ豸½øÐÐÎïÀí´«Êäǰºó£¬½«¼ÓÔØµÄ»º³åÇøÓëÆä·´µ¯Ò³Ãæ½øÐÐͬ²½¡£ ´Ëº¯ÊýÍê³Éԭʼ»º³åÇøÓëÆäÓ³Éä°æ±¾Ö®¼äËùÓбØÐèµÄÊý¾Ý¿½±´¹¤×÷¡£ ½øÐд«Êä֮ǰºÍÖ®ºó±ØÐë¶Ô»º³åÇø½øÐÐͬ²½¡£

    • dmat - ±êÇ©

    • map - ÒѼÓÔØµÄÓ³Éä

    • op - ÒªÖ´ÐеÄͬ²½²Ù×÷µÄÀàÐÍ£º

    • BUS_DMASYNC_PREREAD - ´ÓÉ豸µ½ »º³åÇøµÄ¶Á²Ù×÷֮ǰ

    • BUS_DMASYNC_POSTREAD - ´ÓÉ豸µ½ »º³åÇøµÄ¶Á²Ù×÷Ö®ºó

    • BUS_DMASYNC_PREWRITE - ´Ó»º³åÇøµ½ É豸µÄд²Ù×÷֮ǰ

    • BUS_DMASYNC_POSTWRITE - ´Ó»º³åÇøµ½ É豸µÄд²Ù×÷Ö®ºó

¡¡¡¡ µ±Ç°PREREADºÍPOSTWRITEΪ¿Õ²Ù×÷£¬µ«½«À´¿ÉÄÜ»á¸Ä±ä£¬Òò´ËÇý¶¯³ÌÐò Öв»ÄܺöÂÔËüÃÇ¡£ÓÉbus_dmamem_alloc() »ñµÃµÄÄÚ´æ²»ÐèҪͬ²½¡£

¡¡¡¡ ´Óbus_dmamap_load()Öе÷Óûص÷º¯Êý֮ǰ£¬ ¶ÎÊý×éÊÇ´æ´¢ÔÚÕ»Öеġ£²¢ÇÒÊǰ´±êÇ©ÔÊÐíµÄ×î´óÊýÄ¿µÄ¶ÎÔ¤ÏÈ·ÖÅä ºÃµÄ¡£ÕâÑùÓÉÓÚi386Ìåϵ½á¹¹É϶ԶÎÊýÄ¿µÄʵ¼ÊÏÞÖÆÔ¼Îª250-300 £¨ÄÚºËջΪ4KB¼õÈ¥Óû§½á¹¹µÄ´óС£¬¶ÎÊý×éÌõÄ¿µÄ´óСΪ8×Ö½Ú£¬ºÍ ÆäËü±ØÐëÁô³öÀ´µÄ¿Õ¼ä£©¡£ÓÉÓÚÊý×é»ùÓÚ×î´óÊýÄ¿¶ø·ÖÅ䣬Òò´ËÕâ¸öÖµ ±ØÐë²»ÄÜÉèÖóɳ¬³öʵ¼ÊÐèÒª¡£ÐÒÔ˵ÄÊÇ£¬¶ÔÓÚ´ó¶àÊýÓ²¼þ¶øÑÔ£¬ ËùÖ§³ÖµÄ¶ÎµÄ×î´óÊýÄ¿µÍºÜ¶à¡£µ«Èç¹ûÇý¶¯³ÌÐòÏë´¦Àí¾ßÓзdz£¶à ·ÖÉ¢/ÊÕ¼¯¶ÎµÄ»º³åÇø£¬ÔòÓ¦µ±Ò»²¿·ÖÒ»²¿·ÖµØ´¦Àí£º¼ÓÔØ»º³åÇøµÄ Ò»²¿·Ö£¬´«Êäµ½É豸£¬È»ºó¼ÓÔØ»º³åÇøµÄÏÂÒ»²¿·Ö£¬Èç´Ë·´¸´¡£

¡¡¡¡ ÁíÒ»¸öʵ¼ù½áÂÛÊǶÎÊýÄ¿¿ÉÄÜÏÞÖÆ»º³åÇøµÄ´óС¡£Èç¹û»º³åÇøÖÐµÄ ËùÓÐÒ³ÃæÅöÇÉÎïÀíÉϲ»Á¬Ðø£¬Ôò·ÖƬÇé¿öÏÂÖ§³ÖµÄ×î´ó»º³åÇø³ß´ç Ϊ(nsegments * page_size)¡£ÀýÈ磬Èç¹ûÖ§³ÖµÄ¶ÎµÄ×î´óÊýĿΪ10£¬ ÔòÔÚi386ÉÏ¿ÉÒÔÈ·±£Ö§³ÖµÄ×î´ó»º³åÇø´óСΪ40K¡£Èç¹ûÏ£Íû¸ü´óµÄ ÔòÐèÒªÔÚÇý¶¯³ÌÐòÖÐʹÓÃÒ»Ð©ÌØÊâ¼¼ÇÉ¡£

¡¡¡¡ Èç¹ûÓ²¼þ¸ù±¾²»Ö§³Ö·ÖÉ¢/ÊÕ¼¯£¬»òÕßÇý¶¯³ÌÐòÏ£Íû¼´Ê¹ÔÚÑÏÖØ·ÖƬµÄ Çé¿öÏÂÈÔȻ֧³ÖijÖÖ»º³åÇø´óС£¬Ôò½â¾ö°ì·¨ÊÇ£ºÈç¹ûÎÞ·¨ÈÝÄÉÏÂԭʼ »º³åÇø£¬¾ÍÔÚÇý¶¯³ÌÐòÖзÖÅäÒ»¸öÁ¬ÐøµÄ»º³åÇø×÷ΪÖÐ¼ä´æ´¢¡£

¡¡¡¡ ÏÂÃæÊǵ±Ê¹ÓÃÓ³ÉäʱµÄµäÐ͵÷ÓÃ˳Ðò£¬¸ù¾Ý¶ÔÓ³ÉäµÄ¾ßÌåʹÓöø²»Í¬¡£ ×Ö·û->ÓÃÓÚÏÔʾʱ¼äÁ÷¡£

¡¡¡¡ ¶ÔÓÚ´ÓÁ¬½Óµ½·ÖÀëÉ豸£¬ÕâÆÚ¼äλÖÃÒ»Ö±²»±äµÄ»º³åÇø£º

¡¡¡¡ bus_dmamem_alloc -> bus_dmamap_load -> ...use buffer... -> -> bus_dmamap_unload -> bus_dmamem_free

¡¡¡¡¶ÔÓÚ´ÓÇý¶¯³ÌÐòÍⲿ´«µÝ½øÈ¥£¬²¢ÇÒ¾­³£±ä»¯µÄ»º³åÇø£º

          bus_dmamap_create ->
          -> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->
          -> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->
          ...
          -> bus_dmamap_load -> bus_dmamap_sync(PRE...) -> do transfer ->
          -> bus_dmamap_sync(POST...) -> bus_dmamap_unload ->
          -> bus_dmamap_destroy        

¡¡¡¡ µ±¼ÓÔØÓÉbus_dmamem_alloc()´´½¨µÄÓ³Éäʱ£¬´«µÝ ½øÈ¥µÄ»º³åÇøµÄµØÖ·ºÍ´óС±ØÐëºÍ bus_dmamem_alloc()ÖÐʹÓõÄÒ»Ñù¡£ÕâÖÖÇé¿öÏÂ¾Í ¿ÉÒÔ±£Ö¤Õû¸ö»º³åÇø±»×÷Ϊһ¸ö¶Î¶øÓ³É䣨Òò¶ø»Øµ÷¿ÉÒÔ»ùÓڴ˼ÙÉ裩£¬ ²¢ÇÒÇëÇó±»Á¢¼´Ö´ÐУ¨ÓÀÔ¶²»»á·µ»ØEINPROGRESS£©¡£ÕâÖÖÇé¿öÏ»ص÷º¯Êý ÐèÒª×÷µÄÖ»ÊDZ£´æÎïÀíµØÖ·¡£

¡¡¡¡ µäÐÍʾÀýÈçÏ£º

          static void
        alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)
        {
          *(bus_addr_t *)arg = seg[0].ds_addr;
        }

          ...
          int error;
          struct somedata {
            ....
          };
          struct somedata *vsomedata; /* Ð鵨ַ */
          bus_addr_t psomedata; /* ÎïÀí×ÜÏßÏà¹ØµÄµØÖ· */
          bus_dma_tag_t tag_somedata;
          bus_dmamap_t map_somedata;
          ...

          error=bus_dma_tag_create(parent_tag, alignment,
           boundary, lowaddr, highaddr, /*filter*/ NULL, /*filterarg*/ NULL,
           /*maxsize*/ sizeof(struct somedata), /*nsegments*/ 1,
           /*maxsegsz*/ sizeof(struct somedata), /*flags*/ 0,
           &tag_somedata);
          if(error)
          return error;

          error = bus_dmamem_alloc(tag_somedata, &vsomedata, /* flags*/ 0,
             &map_somedata);
          if(error)
             return error;

          bus_dmamap_load(tag_somedata, map_somedata, (void *)vsomedata,
             sizeof (struct somedata), alloc_callback,
             (void *) &psomedata, /*flags*/0);        

¡¡¡¡ ´úÂë¿´ÆðÀ´Óе㳤£¬Ò²±È½Ï¸´ÔÓ£¬µ«ÄÇÊÇÕýÈ·µÄʹÓ÷½·¨¡£Êµ¼Ê½á¹ûÊÇ£º Èç¹û·ÖÅä¶à¸öÄÚ´æÇøÓò£¬Ôò×ܽ«ËüÃÇ×éºÏ³ÉÒ»¸ö½á¹¹²¢×÷ΪÕûÌå·ÖÅä £¨Èç¹û¶ÔÆëºÍ±ß½çÏÞÖÆÔÊÐíµÄ»°£©ÊÇÒ»¸öºÜºÃµÄÖ÷Òâ¡£

¡¡¡¡ µ±¼ÓÔØÈÎÒ⻺³åÇøµ½ÓÉbus_dmamap_create() ´´½¨µÄÓ³Éäʱ£¬ÓÉÓڻص÷¿ÉÄܱ»ÑÓ³Ù£¬Òò´Ë±ØÐë²ÉÈ¡ÌØÊâ´ëÊ©Óë»Øµ÷ º¯Êý½øÐÐͬ²½¡£´úÂë¿´ÆðÀ´ÏñÏÂÃæµÄÑù×Ó£º

          {
           int s;
           int error;

           s = splsoftvm();
           error = bus_dmamap_load(
               dmat,
               dmamap,
               buffer_ptr,
               buffer_len,
               callback,
               /*callback_arg*/ buffer_descriptor,
               /*flags*/0);
           if (error == EINPROGRESS) {
               /*
                * Ö´ÐбØÒªµÄ²Ù×÷ÒÔÈ·±£Óë»Øµ÷µÄͬ²½¡£
                * »Øµ÷±»È·±£Ö±µ½ÎÒÃÇÖ´ÐÐÁËsplx()»òtsleep()²Å»á±»µ÷Óá£
                */
              }
           splx(s);
          }        

¡¡¡¡ ´¦ÀíÇëÇóµÄÁ½ÖÖ·½·¨·Ö±ðÊÇ£º

¡¡¡¡ 1. Èç¹ûͨ¹ýÏÔʽµØ±ê¼ÇÇëÇóÒѾ­½áÊøÀ´Íê³ÉÇëÇó£¨ÀýÈçCAMÇëÇ󣩣¬Ôò ½«ËùÓнøÒ»²½µÄ´¦Àí·ÅÈë»Øµ÷Çý¶¯³ÌÐòÖлá±È½Ï¼òµ¥£¬»Øµ÷½áÊøºó»á ±ê¼ÇÇëÇó¡£Ö®ºó²»ÐèҪ̫¶à¶îÍâµÄͬ²½¡£ÓÉÓÚÁ÷¿ØÖƵÄÔ­Òò£¬¶³½áÇëÇó ¶ÓÁÐÖ±µ½ÇëÇóÍê³É²ÅÊÍ·Å¿ÉÄÜÊǸöºÃÖ÷Òâ¡£

¡¡¡¡ 2. Èç¹ûÇëÇóÊÇÔÚº¯Êý·µ»ØÊ±Íê³É£¨ÀýÈç×Ö·ûÉ豸ÉÏ´«Í³µÄ¶ÁдÇëÇ󣩣¬ ÔòÐèÒªÔÚ»º³åÇøÃèÊö·ûÉÏÉèÖÃͬ²½±êÖ¾£¬²¢µ÷Óà tsleep()¡£ºóÃæµ±»Øµ÷º¯Êý±»µ÷ÓÃʱ£¬Ëü½« Ö´Ðд¦Àí²¢¼ì²éͬ²½±êÖ¾¡£Èç¹ûÉèÖÃÁËͬ²½±êÖ¾£¬ËüÓ¦¸Ã·¢³öÒ»¸ö »½ÐѲÙ×÷¡£ÔÚÕâÖÖ·½·¨ÖУ¬»Øµ÷º¯Êý»òÕß½øÐÐËùÓɱØÐèµÄ´¦Àí£¨¾ÍÏñ Ç°ÃæµÄÇé¿ö£©£¬»òÕß¼òµ¥ÔÚ»º³åÇøÃèÊö·ûÖд洢¶ÎÊý×é¡£»Øµ÷Íê³É ºó£¬»Øµ÷º¯Êý¾ÍÄÜʹÓÃÕâ¸ö´æ´¢µÄ¶ÎÊý×é²¢½øÐÐËùÓеĴ¦Àí¡£


10.7 DMA

¡¡¡¡ ISA×ÜÏßÖÐDirect Memory Access (DMA)ÊÇͨ¹ýDMA¿ØÖÆÆ÷£¨Êµ¼ÊÉÏÊÇËüÃÇ ÖеÄÁ½¸ö£¬µ«ÕâÖ»ÊÇÎÞ¹ØÏ¸½Ú£©ÊµÏֵġ£ÎªÁËʹÒÔǰµÄISAÉ豸¼òµ¥±ãÒË£¬ ×ÜÏß¿ØÖƺ͵ØÖ·²úÉúµÄÂß¼­¶¼¼¯ÖÐÔÚDMA¿ØÖÆÆ÷ÖС£ÐÒÔ˵ÄÊÇ£¬FreeBSD ÌṩÁËÒ»Ì׺¯Êý£¬ÕâЩº¯Êý´ó¶à°ÑDMA¿ØÖÆÆ÷µÄ·±Ëöϸ½Ú¶ÔÉ豸Çý¶¯³ÌÐò Òþ²ØÁËÆðÀ´¡£

¡¡¡¡ ×î¼òµ¥Çé¿öÊÇÄÇЩ±È½ÏÖÇÄܵÄÉ豸¡£¾ÍÏóPCIÉϵÄ×ÜÏßÖ÷É豸һÑù£¬ ËüÃÇ×Ô¼ºÄܲúÉú×ÜÏßÖÜÆÚºÍÄÚ´æµØÖ·¡£ËüÃÇÕæÕý´ÓDMA¿ØÖÆÆ÷ÐèÒªµÄ ΨһÊÂÇéÊÇ×ÜÏßÖٲá£ËùÒÔΪÁË´ËÄ¿µÄ£¬ËüÃǼÙ×°ÊǼ¶Áª´ÓDMA¿ØÖÆÆ÷¡£ µ±Á¬½ÓÇý¶¯³ÌÐòʱ£¬ÏµÍ³DMA¿ØÖÆÆ÷ÐèÒª×öµÄΨһÊÂÇé¾ÍÊÇͨ¹ýµ÷Óà ÈçϺ¯ÊýÔÚÒ»¸öDMAͨµÀÉϼ¤»î¼¶ÁªÄ£Ê½¡£

¡¡¡¡ void isa_dmacascade(int channel_number)

¡¡¡¡ ËùÓнøÒ»²½µÄ»î¶¯Í¨¹ý¶ÔÉ豸±à³ÌÍê³É¡£µ±Ð¶ÔØÇý¶¯³ÌÐòʱ£¬²»ÐèÒª µ÷ÓÃDMAÏà¹ØµÄº¯Êý¡£

¡¡¡¡ ¶ÔÓڽϼòµ¥µÄÉ豸£¬ÊÂÇé·´¶ø±äµÃ¸´ÔÓ¡£Ê¹Óõĺ¯Êý°üÀ¨£º

  • int isa_dma_acquire(int chanel_number)

    ±£ÁôÒ»¸öDMAͨµÀ¡£³É¹¦Ôò·µ»Ø0£¬Èç¹ûͨµÀÒѾ­±»±£Áô»ò±»ÆäËü Çý¶¯³ÌÐò±£ÁôÔò·µ»ØEBUSY¡£´ó¶àÊýµÄISAÉ豸¶¼²»Äܹ²ÏíDMAͨµÀ£¬ Òò´ËÕâ¸öº¯Êýͨ³£ÔÚÁ¬½ÓÉ豸ʱµ÷Óá£×ÜÏß×ÊÔ´µÄÏÖ´ú½Ó¿ÚʹµÃ ÕâÖÖ±£Áô³ÉΪ¶àÓ࣬µ«Ä¿Ç°ÈÔ±ØÐëʹÓá£Èç¹û²»Ê¹Óã¬ÔòºóÃæÆäËü DMAÀý³Ì½«»ápanic¡£

  • int isa_dma_release(int chanel_number)

    ÊÍ·ÅÏÈǰ±£ÁôµÄDMAͨµÀ¡£ÊÍ·ÅͨµÀʱ±ØÐë²»ÄÜÓÐÕýÔÚ½øÐÐÖÐµÄ ´«Ê䣨ÁíÍ⣬ÊÍ·ÅͨµÀºóÉ豸±ØÐë²»ÄÜÔÙÊÔͼ·¢Æð´«Ê䣩¡£

  • void isa_dmainit(int chan, u_int bouncebufsize)

    ·ÖÅäÓÉÌØ¶¨Í¨µÀʹÓõķ´µ¯»º³åÇø¡£ÇëÇóµÄ»º³åÇø´óС²»Äܳ¬¹ý 64KB¡£ÒÔºó£¬Èç¹û´«Ê仺³åÇøÅöÇɲ»ÊÇÎïÀíÁ¬ÐøµÄ£¬»ò³¬³öISA ×ÜÏ߿ɷÃÎʵÄÄڴ淶Χ£¬»ò¿çÔ½64KBµÄ±ß½ç£¬Ôò»á×Ô¶¯Ê¹Ó÷´µ¯ »º³åÇø¡£Èç¹û´«Êä×ÜÊÇʹÓ÷ûºÏÉÏÊöÌõ¼þµÄ»º³åÇø£¨ÀýÈ磬ÓÉ bus_dmamem_alloc()·ÖÅäµÄÄÇЩ£©£¬Ôò ²»ÐèÒªµ÷ÓÃisa_dmainit()¡£µ«Ê¹Óô˺¯Êý »áÈÃͨ¹ýDMA¿ØÖÆÆ÷´«ÊäÈÎÒâÊý¾Ý±äµÃ·Ç³£·½±ã¡£

    • chan - ͨµÀºÅ

    • bouncebufsize - ÒÔ×Ö½Ú¼ÆÊýµÄ·´µ¯ »º³åÇøµÄ´óС

  • void isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan)

    ×¼±¸Æô¶¯DMA´«Ê䡣ʵ¼ÊÆô¶¯É豸ÉϵĴ«Êä֮ǰ±ØÐèµ÷Óô˺¯Êý À´ÉèÖÃDMA¿ØÖÆÆ÷¡£Ëü¼ì²é»º³åÇøÊÇ·ñÁ¬ÐøµÄÇÒÔÚISAÄڴ淶Χ Ö®ÄÚ£¬Èç¹û²»ÊÇÔò×Ô¶¯Ê¹Ó÷´µ¯»º³åÇø¡£Èç¹ûÐèÒª·´µ¯»º³åÇø£¬ µ«·´µ¯»º³åÇøÃ»ÓÐÓÃisa_dmainit() ÉèÖ㬻ò¶ÔÓÚÇëÇóµÄ´«Êä´óСÀ´ËµÌ«Ð¡£¬Ôòϵͳ½«panic¡£ дÇëÇóÇÒʹÓ÷´µ¯»º³åÇøµÄÇé¿öÏ£¬Êý¾Ý½«±»×Ô¶¯¿½±´µ½·´µ¯ »º³åÇø¡£

  • flags - λÑÚÂ룬¾ö¶¨½«ÒªÍê³ÉµÄ²Ù×÷µÄÀàÐÍ¡£·½ÏòλB_READºÍ B_WRITE»¥³â¡£

    • B_READ - ´ÓISA×ÜÏß¶Áµ½ÄÚ´æ

    • B_WRITE - ´ÓÄÚ´æÐ´µ½ISA×ÜÏßÉÏ

    • B_RAW - Èç¹ûÉèÖÃÔòDMA¿ØÖÆÆ÷½«»á¼Çס»º³åÇø£¬²¢ÔÚ´«Êä½áÊøºó ×Ô¶¯ÖØÐ³õʼ»¯Ëü×Ô¼º£¬ÔÙ´ÎÖØ¸´´«Êäͬһ»º³åÇø£¨µ±È»£¬Çý¶¯ ³ÌÐò¿ÉÄÜ·¢ÆðÉ豸µÄÁíÒ»¸ö´«Êä֮ǰ¸Ä±ä»º³åÇøÖеÄÊý¾Ý£©¡£ Èç¹ûûÓÐÉèÖ㬲ÎÊýÖ»¶ÔÒ»´Î´«ÊäÓÐЧ£¬ÔÚ·¢ÆðÏÂÒ»´Î´«Êä֮ǰ ±ØÐëÔٴε÷ÓÃisa_dmastart()¡£Ö»ÓÐÔÚ²» ʹÓ÷´µ¯»º³åÇøÊ±Ê¹ÓÃB_RAW²ÅÓÐÒâÒå¡£

  • addr - »º³åÇøµÄÐ鵨ַ

  • nbytes - »º³åÇø³¤¶È¡£±ØÐëСÓÚµÈÓÚ64KB¡£²»ÔÊÐí³¤¶ÈΪ0£ºÒòΪ DMA¿ØÖÆÆ÷½«»áÀí½âΪ64KB£¬¶øÄں˴úÂë°ÑËüÀí½âΪ0£¬ÄÇÑù¾Í»áµ¼Ö ²»¿ÉÔ¤²âµÄЧ¹û¡£¶ÔÓÚͨµÀºÅµÈÓں͸ßÓÚ4µÄÇé¿ö£¬³¤¶È±ØÐèΪżÊý£¬ ÒòΪÕâЩͨµÀÿ´Î´«Êä2×Ö½Ú¡£ÆæÊý³¤¶ÈÇé¿öÏ£¬×îºóÒ»¸ö×Ö½Ú²»±» ´«Êä¡£

  • chan - ͨµÀºÅ

  • void isa_dmadone(int flags, caddr_t addr, int nbytes, int chan)

    É豸±¨¸æ´«ÊäÍê³Éºó£¬Í¬²½ÄÚ´æ¡£Èç¹ûÊÇʹÓ÷´µ¯»º³åÇøµÄ¶Á²Ù×÷£¬ Ôò½«Êý¾Ý´Ó·´µ¯»º³åÇø¿½±´µ½Ô­Ê¼»º³åÇø¡£²ÎÁ¿Óë isa_dmastart()µÄÏàͬ¡£ÔÊÐíʹÓÃB_RAW±êÖ¾£¬ µ«ËüÒ»µãÒ²²»»áÓ°Ïìisa_dmadone()¡£

  • int isa_dmastatus(int channel_number)

    ·µ»Øµ±Ç°´«ÊäÖÐÊ£ÓàµÄ×Ö½ÚÊý¡£ÔÚ isa_dmastart()ÖÐÉèÖÃÁËB_READµÄÇé¿öÏ£¬ ·µ»ØµÄÊý×ÖÒ»¶¨²»»áµÈÓÚÁã¡£´«Êä½áÊøÊ±Ëü»á±»×Ô¶¯¸´Î»µ½»º³åÇøµÄ ³¤¶È¡£ÕýʽµÄÓ÷¨ÊÇÔÚÉ豸·¢ÐźÅָʾ´«ÊäÒÑÍê³Éʱ¼ì²éÊ£ÓàµÄ×Ö½ÚÊý¡£ Èç¹û×Ö½ÚÊý²»Îª0£¬Ôò´Ë´Î´«Êä¿ÉÄÜÓÐÎÊÌâ¡£

  • int isa_dmastop(int channel_number)

    ·ÅÆúµ±Ç°µÄ´«Êä²¢·µ»ØÊ£Óàδ´«ÊäµÄ×Ö½ÚÊý¡£


10.8 xxx_isa_probe

¡¡¡¡ Õâ¸öº¯Êý̽²âÉ豸ÊÇ·ñ´æÔÚ¡£Èç¹ûÇý¶¯³ÌÐòÖ§³Ö×Ô¶¯Õì²âÉ豸ÅäÖÃµÄ Ä³Ð©²¿·Ö£¨ÈçÖжÏÏòÁ¿»òÄÚ´æµØÖ·£©£¬Ôò×Ô¶¯Õì²â±ØÐëÔÚ´ËÀý³ÌÖÐÍê³É¡£

¡¡¡¡ ¶ÔÓÚÈÎÒâÆäËû×ÜÏߣ¬Èç¹û²»ÄÜÕì²âµ½É豸£¬»òÕßÕì²âµ½µ«×Ô¼ìʧ°Ü£¬ »òÕß·¢ÉúijЩÆäËûÎÊÌ⣬ÔòÓ¦µ±·µ»ØÒ»¸öÕýÖµµÄ´íÎó¡£Èç¹ûÉ豸²» ´æÔÚÔò±ØÐë·µ»ØÖµ ¡°ENXIO¡±¡£ ÆäËû´íÎóÖµ¿ÉÄܱíʾÆäËûÌõ¼þ¡£Áã»ò¸ºÖµ Òâζ×ųɹ¦¡£´ó¶àÊýÇý¶¯³ÌÐò·µ»ØÁã±íʾ³É¹¦¡£

¡¡¡¡ µ±PnPÉ豸֧³Ö¶à¸ö½Ó¿ÚʱʹÓøº·µ»ØÖµ¡£ÀýÈ磬²»Í¬Çý¶¯³ÌÐòÖ§³Ö ÀϵļæÈݽӿںͽÏеĸ߼¶½Ó¿Ú¡£ÔòÁ½¸öÇý¶¯³ÌÐò¶¼½«Õì²âÉ豸¡£ ÔÚ̽²âÀý³ÌÖзµ»Ø½Ï¸ßÖµµÄÇý¶¯³ÌÐò»ñµÃÓÅÏÈ£¨»»¾ä»°Ëµ£¬·µ»Ø0µÄ Çý¶¯³ÌÐò¾ßÓÐ×î¸ßµÄÓÅÏȼ¶£¬·µ»Ø-1µÄÆä´Î£¬·µ»Ø-2µÄ¸üºó£¬µÈµÈ£©¡£ ÕâÑù£¬½öÖ§³ÖÀϽӿڵÄÉ豸½«±»ÀÏÇý¶¯³ÌÐò´¦Àí£¨ÆäÓ¦µ±´Ó̽²âÀý³ÌÖÐ ·µ»Ø-1£©£¬¶øÍ¬Ê±Ò²Ö§³ÖнӿڵÄÉ豸½«ÓÉÐÂÇý¶¯³ÌÐò´¦Àí£¨ÆäÓ¦µ±´Ó ̽²âÀý³ÌÖзµ»Ø0£©¡£

¡¡¡¡ É豸ÃèÊö·û½á¹¹xxx_softcÓÉϵͳÔÚµ÷ÓÃ̽²âÀý³Ì֮ǰ·ÖÅä¡£Èç¹û ̽²âÀý³Ì·µ»Ø´íÎó£¬ÃèÊö·û»á±»ÏµÍ³×Ô¶¯È¡Ïû·ÖÅä¡£Òò´ËÈç¹û³öÏÖ Ì½²â´íÎó£¬Çý¶¯³ÌÐò±ØÐ뱣֤ȡÏû·ÖÅä̽²âÆÚ¼äËüʹÓõÄËùÓÐ×ÊÔ´£¬ ÇÒÈ·±£Ã»ÓÐʲôÄܹ»×èÖ¹ÃèÊö·û±»°²È«µØÈ¡Ïû·ÖÅä¡£Èç¹û̽²â³É¹¦ Íê³É£¬ÃèÊö·û½«ÓÉϵͳ±£´æ²¢ÔÚÒԺ󴫵ݸøÀý³Ì xxx_isa_attach()¡£Èç¹ûÇý¶¯³ÌÐò·µ»Ø¸ºÖµ£¬ ¾Í²»Äܱ£Ö¤Ëü½«»ñµÃ×î¸ßÓÅÏÈȨÇÒÆäÁ¬½ÓÀý³Ì»á±»µ÷Óá£Òò´ËÕâÖÖ Çé¿öÏÂËüÒ²±ØÐëÔÚ·µ»ØÇ°ÊÍ·ÅËùÓеÄ×ÊÔ´£¬²¢ÔÚÐèÒªµÄʱºòÔÚÁ¬½Ó Àý³ÌÖÐÖØÐ·ÖÅäËüÃÇ¡£µ±xxx_isa_probe() ·µ»Ø0ʱ£¬ÔÚ·µ»ØÇ°ÊÍ·Å×ÊÔ´Ò²ÊÇÒ»¸öºÃÖ÷Ò⣬¶øÇÒÖйæÖоصÄÇý¶¯ ³ÌÐòÓ¦µ±ÕâÑù×ö¡£µ«ÔÚÊÍ·Å×ÊÔ´»á´æÔÚijЩÎÊÌâµÄÇé¿öÏ£¬ÔÊÐíÇý¶¯ ³ÌÐòÔÚ´Ó̽²âÀý³Ì·µ»Ø0ºÍÁ¬½ÓÀý³ÌµÄÖ´ÐÐÖ®¼ä±£³Ö×ÊÔ´¡£

¡¡¡¡ µäÐ͵Ä̽²âÀý³ÌÒÔÈ¡µÃÉ豸ÃèÊö·ûºÍµ¥ÔªºÅ¿ªÊ¼£º

         struct xxx_softc *sc = device_get_softc(dev);
          int unit = device_get_unit(dev);
          int pnperror;
          int error = 0;

          sc->dev = dev; /* Á´½Ó»ØÀ´ */
          sc->unit = unit;        

¡¡¡¡ È»ºó¼ì²éPnPÉ豸¡£¼ì²éÊÇͨ¹ýÒ»¸ö°üº¬PnP IDÁбíµÄ±í½øÐеġ£´Ë±í °üº¬Õâ¸öÇý¶¯³ÌÐòÖ§³ÖµÄPnP IDºÍÒÔÈ˹¤¿É¶ÁÐÎʽ¸ø³öµÄ¶ÔÓ¦ÕâЩIDµÄ É豸ÐͺŵÄÃèÊö¡£

        pnperror=ISA_PNP_PROBE(device_get_parent(dev), dev,
        xxx_pnp_ids); if(pnperror == ENXIO) return ENXIO;
        

¡¡¡¡ ISA_PNP_PROBEµÄÂß¼­ÈçÏ£ºÈç¹û¿¨£¨É豸µ¥Ôª£©Ã»Óб»×÷ΪPnPÕì²âµ½£¬ Ôò·µ»ØENOENT¡£Èç¹û±»×÷ΪPnPÕì²âµ½£¬µ«Õì²âµ½µÄID²»Æ¥Åä±íÖÐµÄ ÈÎÒ»ID£¬Ôò·µ»ØENXIO¡£×îºó£¬Èç¹ûÉ豸ÄÜÖ§³ÖPnPÇÒÆ¥Åä±íÖеÄÒ»¸ö ID£¬Ôò·µ»Ø0£¬²¢ÇÒÓÉdevice_set_desc()´Ó ±íÖÐÈ¡µÃÊʵ±µÄÃèÊö½øÐÐÉèÖá£

¡¡¡¡ Èç¹ûÉ豸Çý¶¯³ÌÐò½öÖ§³ÖPnPÉ豸£¬ÔòÇé¿ö¿´ÆðÀ´ÈçÏ£º

          if(pnperror != 0)
              return pnperror;        

¡¡¡¡ ¶ÔÓÚ²»Ö§³ÖPnPµÄÇý¶¯³ÌÐò²»ÐèÒªÌØÊâ´¦Àí£¬ÒòΪÇý¶¯³ÌÐò»á´«µÝ¿ÕµÄ PnP ID±í£¬ÇÒÈç¹ûÔÚPnP¿¨Éϵ÷ÓûáµÃµ½ENXIO¡£

¡¡¡¡ ̽²âÀý³Ìͨ³£ÖÁÉÙÐèҪijЩ×îÉÙÁ¿µÄ×ÊÔ´£¬ÈçI/O¶Ë¿ÚºÅ£¬À´·¢ÏÖ²¢Ì½²â¿¨¡£ ¶ÔÓÚ²»Í¬µÄÓ²¼þ£¬Çý¶¯³ÌÐò¿ÉÄÜ»á×Ô¶¯·¢ÏÖÆäËû±ØÐèµÄ×ÊÔ´¡£PnPÉ豸µÄ ËùÓÐ×ÊÔ´ÓÉPnP×ÓϵͳԤÏÈÉèÖã¬Òò´ËÇý¶¯³ÌÐò²»ÐèÒª×Ô¼º·¢ÏÖËüÃÇ¡£

¡¡¡¡ ͨ³£·ÃÎÊÉ豸ËùÐèÒªµÄ×îÉÙÐÅÏ¢¾ÍÊǶ˿ںš£È»ºóijЩÉ豸ÔÊÐí´ÓÉ豸 ÅäÖüĴæÆ÷ÖÐÈ¡µÃÆäÓàÐÅÏ¢£¨¾¡¹Ü²»ÊÇËùÓеÄÉ豸¶¼ÕâÑù£©¡£Òò´ËÊ×ÏÈ ÎÒÃdz¢ÊÔÈ¡µÃ¶Ë¿ÚÆðʼֵ£º

 sc->port0 = bus_get_resource_start(dev,
        SYS_RES_IOPORT, 0 /*rid*/); if(sc->port0 == 0) return ENXIO;
        

¡¡¡¡ »ù¶Ë¿ÚµØÖ·±»±£´æÔÚsoftc½á¹¹ÖУ¬ÒԱ㽫À´Ê¹Óá£Èç¹ûÐèÒª¾­³£Ê¹Óà ¶Ë¿Ú£¬Ôòÿ´Î¶¼µ÷ÓÃ×ÊÔ´º¯Êý½«»áÂýµÄÎÞ·¨ÈÌÊÜ¡£Èç¹ûÎÒÃÇûÓеõ½ ¶Ë¿Ú£¬Ôò·µ»Ø´íÎó¼´¿É¡£Ïà·´£¬Ò»Ð©É豸Çý¶¯³ÌÐòÏ൱´ÏÃ÷£¬³¢ÊÔ̽²â ËùÓпÉÄܵĶ˿ڣ¬ÈçÏ£º

          
          /* ´ËÉ豸ËùÓпÉÄܵĻùI/O¶Ë¿ÚµØÖ·±í */
          static struct xxx_allports {
              u_short port; /* ¶Ë¿ÚµØÖ· */
              short used; /* Æì±ê£º´Ë¶Ë¿ÚÊÇ·ñÒѱ»ÆäËûµ¥ÔªÊ¹Óà */
          } xxx_allports = {
              { 0x300, 0 },
              { 0x320, 0 },
              { 0x340, 0 },
              { 0, 0 } /* ±í½áÊø */
          };

          ...
          int port, i;
          ...

          port =  bus_get_resource_start(dev, SYS_RES_IOPORT, 0 /*rid*/);
          if(port !=0 ) {
              for(i=0; xxx_allports[i].port!=0; i++) {
                  if(xxx_allports[i].used || xxx_allports[i].port != port)
                      continue;

                  /* ÕÒµ½ÁË */
                  xxx_allports[i].used = 1;
                  /* ÔÚÒÑÖª¶Ë¿ÚÉÏ̽²â */
                  return xxx_really_probe(dev, port);
              }
              return ENXIO; /* ¶Ë¿ÚÎÞ·¨Ê¶±ð»òÒѾ­±»Ê¹Óà */
          }

          /* ½öÔÚÐèÒª²Â²â¶Ë¿ÚµÄʱºò²Å»áµ½´ïÕâ¶ù */
          for(i=0; xxx_allports[i].port!=0; i++) {
              if(xxx_allports[i].used)
                  continue;

              /* ±ê¼ÇΪÒѱ»Ê¹Óà - ¼´Ê¹ÎÒÃÇÔڴ˶˿ÚʲôҲûÓз¢ÏÖ
               * ÖÁÉÙÎÒÃÇÒÔºó²»»áÔÙ´Î̽²â
               */
               xxx_allports[i].used = 1;

              error = xxx_really_probe(dev, xxx_allports[i].port);
              if(error == 0) /* ÔÚÄǸö¶Ë¿ÚÕÒµ½Ò»¸öÉ豸 */
                  return 0;
          }
          /* ̽²â¹ýËùÓпÉÄܵĵØÖ·£¬µ«Ã»ÓпÉÓÃµÄ */
          return ENXIO;

¡¡¡¡ µ±È»£¬×öÕâЩÊÂÇéͨ³£Ó¦¸ÃʹÓÃÇý¶¯³ÌÐòµÄ identify()Àý³Ì¡£µ«¿ÉÄÜÓÐÒ»¸öÕýµ±µÄÀíÓÉÀ´ ˵Ã÷ΪʲôÔÚº¯Êýprobe()ÖÐÍê³É¸üºÃ£ºÈç¹û ÕâÖÖ̽²â»áÈÃһЩÆäËûÃô¸ÐÉ豸·¢·è¡£Ì½²âÀý³Ì°´Æì±ê sensitiveÅÅÐò£ºÃô¸ÐÉ豸Ê×Ïȱ»Ì½²â£¬È»ºóÊÇ ÆäËûÉ豸¡£µ«identify()Àý³ÌÔÚËùÓÐ̽²â֮ǰ ±»µ÷Óã¬Òò´ËËüÃDz»»á¿¼ÂÇÃô¸ÐÉ豸²¢¿ÉÄÜÈÅÂÒÕâЩÉ豸¡£

¡¡¡¡ ÏÖÔÚ£¬ÎÒÃǵõ½Æðʼ¶Ë¿ÚÒÔºó¾ÍÐèÒªÉèÖö˿ÚÊý£¨PnPÉ豸³ýÍ⣩£¬ÒòΪ ÄÚºËÔÚÅäÖÃÎļþÖÐûÓÐÕâ¸öÐÅÏ¢¡£

          
         if(pnperror /* Ö»¶Ô·ÇPnPÉ豸 */
         && bus_set_resource(dev, SYS_RES_IOPORT, 0, sc->port0, 
         XXX_PORT_COUNT)<0)
             return ENXIO;

¡¡¡¡ ×îºó·ÖÅä²¢¼¤»îһƬ¶Ë¿ÚµØÖ·¿Õ¼ä£¨ÌØÊâÖµstartºÍendÒâ˼ÊÇ˵ ¡°Ê¹ÓÃÎÒÃÇͨ¹ýbus_set_resource() ÉèÖõÄÄÇЩֵ¡±£©£º

          sc->port0_rid = 0;
          sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,  
          &sc->port0_rid,
              /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);

          if(sc->port0_r == NULL)
              return ENXIO;

¡¡¡¡ ÏÖÔÚ¿ÉÒÔ·ÃÎʶ˿ÚÓ³ÉäµÄ¼Ä´æÆ÷ºó£¬ÎÒÃǾͿÉÒÔÒÔijÖÖ·½Ê½ÏòÉ豸дÈë Êý¾Ý²¢¼ì²éÉ豸ÊÇ·ñÈçÎÒÃÇÆÚÍûµÄÄÇÑù×÷³ö·´Ó¦¡£Èç¹ûûÓУ¬Ôò˵Ã÷ ¿ÉÄÜÆäËûµÄÉ豸ÔÚÕâ¸öµØÖ·ÉÏ£¬»òÕßÕâ¸öµØÖ·Éϸù±¾Ã»ÓÐÉ豸¡£

¡¡¡¡ ͨ³£Çý¶¯³ÌÐòÖ±µ½Á¬½ÓÀý³Ì²Å»áÉèÖÃÖжϴ¦Àíº¯Êý¡£Õâ֮ǰÎÒÃÇÌæ´úÒÔ ÂÖѯģʽ½øÐÐ̽²â£¬³¬Ê±ÔòÒÔDELAY()ʵÏÖ¡£ ̽²âÀý³Ì±ØÐëÈ·±£²»ÄÜÓÀ¾Ã¹ÒÆð£¬É豸ÉϵÄËùÓеȴý±ØÐëÔÚ³¬Ê±ÄÚÍê³É¡£ Èç¹ûÉ豸²»ÔÚÕâ¶Îʱ¼äÄÚÏìÓ¦£¬Ôò¿ÉÄÜÉ豸³ö¹ÊÕÏ»òÅäÖôíÎó£¬Çý¶¯³ÌÐò ±ØÐë·µ»Ø´íÎ󣬵±È·¶¨³¬Ê±¼ä¸ôʱ£¬¸øÉ豸һЩ¶îÍâʱ¼äÒÔÈ·±£¿É¿¿£º ¾¡¹Ü¼Ù¶¨DELAY()ÔÚÈκλúÆ÷É϶¼ÑÓʱÏàͬÊýÁ¿µÄ ʱ¼ä£¬µ«Ëæ¾ßÌåCPUµÄ²»Í¬£¬´Ëº¯Êý»¹ÊÇÓÐÒ»¶¨µÄÎó²î·ù¶È¡£

¡¡¡¡ Èç¹û̽²âÀý³ÌÕæµÄÏë¼ì²éÖжÏÊÇ·ñÕæµÄ¹¤×÷£¬Ëü¿ÉÒÔÒ²ÅäÖúÍ̽²âÖжϡ£ µ«²»½¨ÒéÕâÑù¡£

          
          /* ÒÔÑÏÖØÒÀÀµÓÚ¾ßÌåÉ豸µÄ·½Ê½ÊµÏÖ */
          if(error = xxx_probe_ports(sc))
              goto bad; /* ·µ»ØÇ°ÊÍ·Å×ÊÔ´ */
        

¡¡¡¡ ÒÀÀµÓÚËù·¢ÏÖÉ豸µÄÈ·ÇÐÐͺţ¬º¯Êý xxx_probe_ports()Ò²¿ÉÄÜÉèÖÃÉ豸ÃèÊö¡£µ« Èç¹ûÖ»Ö§³ÖÒ»ÖÖÉ豸Ðͺţ¬ÔòÒ²¿ÉÒÔÓ²±àÂëµÄÐÎʽÍê³É¡£µ±È»£¬¶ÔÓÚ PnPÉ豸£¬PnPÖ§³Ö´Ó±íÖÐ×Ô¶¯ÉèÖÃÃèÊö¡£

          if(pnperror)
              device_set_desc(dev, "Our device model 1234");
        

¡¡¡¡ ̽²âÀý³ÌÓ¦µ±»òÕßͨ¹ý¶ÁÈ¡É豸ÅäÖüĴæÆ÷À´·¢ÏÖËùÓÐ×ÊÔ´µÄ·¶Î§£¬ »òÕßÈ·±£ÓÉÓû§ÏÔʽÉèÖá£ÎÒÃǽ«¼Ù¶¨Ò»¸ö´ø°åÉÏÄÚ´æµÄÀý×Ó¡£ ̽²âÀý³ÌÓ¦µ±¾¡¿ÉÄÜÊǷDzåÈëʽµÄ£¬ÕâÑù·ÖÅäºÍ¼ì²éÆäÓà×ÊÔ´¹¦ÄÜÐÔ µÄ¹¤×÷¾Í¿ÉÒÔ¸üºÃµØÁô¸øÁ¬½ÓÀý³ÌÀ´×ö¡£

¡¡¡¡ ÄÚ´æµØÖ·¿ÉÒÔÔÚÄÚºËÅäÖÃÎļþÖÐÖ¸¶¨£¬»òÕß¶ÔӦijЩÉ豸¿ÉÒÔÔÚ·ÇÒ×ʧÐÔ ÅäÖüĴæÆ÷ÖÐÔ¤ÏÈÅäÖá£Èç¹ûÁ½ÖÖ×ö·¨¾ù¿ÉÓÃÈ´²»Í¬£¬ÄÇôӦµ±Óà ÄĸöÄØ£¿¿ÉÄÜÓû§Ñá·³ÔÚÄÚºËÅäÖÃÎļþÖÐÃ÷È·ÉèÖõØÖ·£¬µ«ËûÃÇÖªµÀ ×Ô¼ºÔÚ¸Éʲô£¬ÔòÓ¦µ±ÓÅÏÈʹÓÃÕâ¸ö¡£Ò»¸öʵÏÖµÄÀý×Ó¿ÉÄÜÊÇÕâÑùµÄ£º

          
          /* Ê×ÏÈÊÔͼÕÒ³öÅäÖõØÖ· */
          sc->mem0_p = bus_get_resource_start(dev, SYS_RES_MEMORY, 0 /*rid*/);
          if(sc->mem0_p == 0) { /* ûÓУ¬Óû§Ã»Ö¸¶¨ */
              sc->mem0_p = xxx_read_mem0_from_device_config(sc);


          if(sc->mem0_p == 0)
                  /* ´ÓÉ豸ÅäÖüĴæÆ÷Ò²µ½²»ÁËÕâ¶ù */
                  goto bad;
          } else {
              if(xxx_set_mem0_address_on_device(sc) < 0)
                  goto bad; /* É豸²»Ö§³ÖÄǵØÖ· */
          }

          /* ¾ÍÏñ¶Ë¿Ú£¬ÉèÖÃÄÚ´æ´óС£¬
           * ¶ÔÓÚijЩÉ豸£¬ÄÚ´æ´óС²»Êdz£Êý£¬
           * ¶øÓ¦µ±´ÓÉ豸ÅäÖüĴæÆ÷ÖжÁÈ¡£¬ÒÔÊÊÓ¦É豸µÄ²»Í¬ÐͺÅ
           * ÁíÒ»¸öÑ¡ÔñÊÇÈÃÓû§°ÑÄÚ´æ´óСÉèÖÃΪ¡°msize¡±ÅäÖÃ×ÊÔ´£¬
           * ÓÉISA×ÜÏß×Ô¶¯´¦Àí
           */
           if(pnperror) { /*½ö¶Ô·ÇPnPÉ豸 */
              sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);
              if(sc->mem0_size == 0) /* Óû§Ã»ÓÐÖ¸¶¨ */
                  sc->mem0_size = xxx_read_mem0_size_from_device_config(sc);

              if(sc->mem0_size == 0) {
                  /* ¼Ù¶¨ÕâÊÇÉ豸·Ç³£ÀϵÄÒ»ÖÖÐͺţ¬Ã»ÓÐ×Ô¶¯ÅäÖÃÌØÐÔ£¬
                   * Óû§Ò²Ã»ÓÐÆ«ºÃÉèÖã¬Òò´Ë¼Ù¶¨×îµÍÒªÇóµÄÇé¿ö
                   * £¨µ±È»£¬ÕæÊµÖµ½«¸ù¾ÝÉ豸Çý¶¯³ÌÐò¶ø²»Í¬£©
                   */
                  sc->mem0_size = 8*1024;
              }

              if(xxx_set_mem0_size_on_device(sc) < 0)
                  goto bad; /*É豸²»Ö§³ÖÄǸö´óС */

              if(bus_set_resource(dev, SYS_RES_MEMORY, /*rid*/0,
                      sc->mem0_p, sc->mem0_size)<0)
                  goto bad;
          } else {
              sc->mem0_size = bus_get_resource_count(dev, SYS_RES_MEMORY, 0 /*rid*/);
          }        

¡¡¡¡ ÀàËÆ, ºÜÈÝÒ×¼ì²éIRQºÍDRQËùÓõÄ×ÊÔ´¡£

¡¡¡¡ Èç¹ûÒ»ÇнøÐÐÕý³££¬È»ºó¾Í¿ÉÒÔÊÍ·ÅËùÓÐ×ÊÔ´²¢·µ»Ø³É¹¦¡£

          xxx_free_resources(sc);
          return 0;

¡¡¡¡ ×îºó£¬´¦Àí¼¬ÊÖÇé¿ö¡£ËùÓÐ×ÊÔ´Ó¦µ±ÔÚ·µ»ØÇ°±»ÊÍ·Å¡£ÎÒÃÇÀûÓÃÕâÑùÒ»¸ö ÊÂʵ£ºsoftc½á¹¹ÔÚ´«µÝ¸øÎÒÃÇÒÔǰ±»Á㻯£¬Òò´ËÎÒÃÇÄܹ»ÕÒ³öÊÇ·ñ·ÖÅäÁË Ä³Ð©×ÊÔ´£ºÈç¹û·ÖÅäÔòÕâЩ×ÊÔ´µÄÃèÊö·û·ÇÁã¡£

          bad:

          xxx_free_resources(sc);
          if(error)
                return error;
          else /* È·ÇдíÎóδ֪ */
              return ENXIO;

¡¡¡¡ ÕâÊÇÍêÕûµÄ̽²âÀý³Ì¡£×ÊÔ´µÄÊÍ·Å´Ó¶à¸öµØ·½Íê³É£¬Òò´Ë½«ËüŲµ½Ò»¸ö º¯ÊýÖУ¬¿´ÆðÀ´¿ÉÄÜÏñÏÂÃæµÄÑù×Ó£º

static void
           xxx_free_resources(sc)
              struct xxx_softc *sc;
          {
              /* ¼ì²éÿ¸ö×ÊÔ´£¬Èç¹û·Ç0ÔòÊÍ·Å */

              /* Öжϴ¦Àíº¯Êý */
              if(sc->intr_r) {
                  bus_teardown_intr(sc->dev, sc->intr_r, sc->intr_cookie);
                  bus_release_resource(sc->dev, SYS_RES_IRQ, sc->intr_rid,
                      sc->intr_r);
                  sc->intr_r = 0;
              }

              /* ÎÒÃÇ·ÖÅä¹ýµÄËùÓÐÖÖÀàµÄÄÚ´æ */
              if(sc->data_p) {
                  bus_dmamap_unload(sc->data_tag, sc->data_map);
                  sc->data_p = 0;
              }
               if(sc->data) { /* sc->data_mapµÈÓÚ0ÓпÉÄܺϷ¨ */
                  /* the map will also be freed */
                  bus_dmamem_free(sc->data_tag, sc->data, sc->data_map);
                  sc->data = 0;
              }
              if(sc->data_tag) {
                  bus_dma_tag_destroy(sc->data_tag);
                  sc->data_tag = 0;
              }

              ... Èç¹ûÓУ¬ÊÍ·ÅÆäËûµÄÓ³ÉäºÍ±êÇ© ...

              if(sc->parent_tag) {
                  bus_dma_tag_destroy(sc->parent_tag);
                  sc->parent_tag = 0;
              }

              /* ÊÍ·ÅËùÓÐ×ÜÏß×ÊÔ´ */
              if(sc->mem0_r) {
                  bus_release_resource(sc->dev, SYS_RES_MEMORY, sc->mem0_rid,
                      sc->mem0_r);
                  sc->mem0_r = 0;
              }
              ...
              if(sc->port0_r) {
                  bus_release_resource(sc->dev, SYS_RES_IOPORT, sc->port0_rid,
                      sc->port0_r);
                  sc->port0_r = 0;
              }
          }

10.9 xxx_isa_attach

¡¡¡¡Èç¹û̽²âÀý³Ì·µ»Ø³É¹¦²¢ÇÒϵͳѡÔñÁ¬½ÓÄǸöÇý¶¯³ÌÐò£¬ÔòÁ¬½ÓÀý³Ì ¸ºÔð½«Çý¶¯³ÌÐòʵ¼ÊÁ¬½Óµ½ÏµÍ³¡£Èç¹û̽²âÀý³Ì·µ»Ø0 £¬ÔòÁ¬½ÓÀý³ÌÆÚÍû ½ÓÊÕÍêÕûµÄÉ豸½á¹¹softc£¬´Ë½á¹¹ÓÉ̽²âÀý³ÌÉèÖá£Í¬Ê±£¬Èç¹û̽²âÀý³Ì ·µ»Ø0£¬Ëü¿ÉÄÜÆÚÍûÕâ¸öÉ豸µÄÁ¬½ÓÀý³ÌÓ¦µ±ÔÚ½«À´µÄijµã±»µ÷Óá£Èç¹û ̽²âÀý³Ì·µ»Ø¸ºÖµ£¬ÔòÇý¶¯³ÌÐò¿ÉÄܲ»»á×÷´Ë¼ÙÉè¡£

¡¡¡¡Èç¹û³É¹¦Íê³É£¬Á¬½ÓÀý³Ì·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£

¡¡¡¡Á¬½ÓÀý³ÌµÄÆô¶¯¸ú̽²âÀý³ÌÏàËÆ£¬½«Ò»Ð©³£ÓÃÊý¾ÝÈ¡µ½Ò»Ð©¸üÈÝÒ× ·ÃÎʵıäÁ¿ÖС£

          struct xxx_softc *sc = device_get_softc(dev);
          int unit = device_get_unit(dev);
          int error = 0;

¡¡¡¡È»ºó·ÖÅä²¢¼¤»îËùÐè×ÊÔ´¡£ÓÉÓڶ˿ڷ¶Î§Í¨³£ÔÚ´Ó̽²â·µ»ØÇ°¾Í ±»ÊÍ·Å£¬Òò´ËÐèÒªÖØÐ·ÖÅä¡£ÎÒÃÇÏ£Íû̽²âÀý³ÌÒѾ­Êʵ±µØÉèÖÃÁË ËùÓеÄ×ÊÔ´·¶Î§£¬²¢½«ËüÃDZ£´æÔڽṹsoftcÖС£Èç¹û̽²âÀý³ÌÁôÏÂÁË Ò»Ð©±»·ÖÅäµÄ×ÊÔ´£¬¾Í²»ÐèÒªÔٴηÖÅ䣍֨зÖÅä±»ÊÓΪ´íÎ󣩡£

          sc->port0_rid = 0;
          sc->port0_r = bus_alloc_resource(dev, SYS_RES_IOPORT,  &sc->port0_rid,
              /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);

          if(sc->port0_r == NULL)
               return ENXIO;

          /* °åÉÏÄÚ´æ */
          sc->mem0_rid = 0;
          sc->mem0_r = bus_alloc_resource(dev, SYS_RES_MEMORY,  &sc->mem0_rid,
              /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);

          if(sc->mem0_r == NULL)
                goto bad;

          /* È¡µÃÐ鵨ַ */
          sc->mem0_v = rman_get_virtual(sc->mem0_r);

¡¡¡¡DMAÇëÇóͨµÀ(DRQ)ÒÔÏàËÆ·½Ê½±»·ÖÅ䡣ʹÓà isa_dma*()º¯Êý×å½øÐгõʼ»¯¡£ÀýÈ磺

¡¡¡¡isa_dmacascade(sc->drq0);

¡¡¡¡ÖжÏÇëÇóÏß(IRQ)ÓеãÌØÊâ¡£³ýÁË·ÖÅäÒÔÍ⣬Çý¶¯³ÌÐòµÄÖжϴ¦Àí º¯ÊýÒ²Ó¦µ±ÓëËü¹ØÁª¡£ÔÚ¹ÅÀϵÄISAÇý¶¯³ÌÐòÖУ¬ÓÉϵͳ´«µÝ¸øÖжϴ¦Àí º¯ÊýµÄ²ÎÁ¿ÊÇÉ豸µ¥ÔªºÅ¡£µ«ÔÚÏÖ´úÇý¶¯³ÌÐòÖУ¬°´ÕÕÔ¼¶¨£¬½¨Òé´«µÝ Ö¸Ïò½á¹¹softcµÄÖ¸Õë¡£Ò»¸öºÜÖØÒªµÄÔ­ÒòÔÚÓÚµ±½á¹¹softc±»¶¯Ì¬·ÖÅäºó£¬ ´ÓsoftcÈ¡µÃµ¥ÔªºÅºÜÈÝÒ×£¬¶ø´Óµ¥ÔªºÅÈ¡µÃsoftcºÜÀ§ÄÑ¡£Í¬Ê±£¬Õâ¸ö Ô¼¶¨Ò²Ê¹µÃÓÃÓÚ²»Í¬×ÜÏßµÄÓ¦ÓóÌÐò¿´ÆðÀ´Í³Ò»£¬²¢ÔÊÐíËüÃǹ²Ïí´úÂ룺 ÿ¸ö×ÜÏßÓÐÆä×Ô¼ºµÄ̽²â£¬Á¬½Ó£¬·ÖÀëºÍÆäËû×ÜÏßÏà¹ØµÄÀý³Ì£¬¶øËüÃÇ Ö®¼ä¿ÉÒÔ¹²Ïí´ó¿éµÄÇý¶¯³ÌÐò´úÂë¡£

          sc->intr_rid = 0;
          sc->intr_r = bus_alloc_resource(dev, SYS_RES_MEMORY,  &sc->intr_rid,
                /*start*/ 0, /*end*/ ~0, /*count*/ 0, RF_ACTIVE);

          if(sc->intr_r == NULL)
              goto bad;

          /*
           * ¼Ù¶¨¶ÔXXX_INTR_TYPEµÄ¶¨ÒåÒÀÀµÓÚÇý¶¯³ÌÐòµÄÀàÐÍ£¬
           * ÀýÈçINTR_TYPE_CAMÓÃÓÚCAMµÄÇý¶¯³ÌÐò
           */
          error = bus_setup_intr(dev, sc->intr_r, XXX_INTR_TYPE,
              (driver_intr_t *) xxx_intr, (void *) sc, &sc->intr_cookie);
          if(error)
              goto bad;

        

¡¡¡¡Èç¹ûÇý¶¯³ÌÐòÐèÒªÓëÄÚ´æ½øÐÐDMA£¬ÔòÕâ¿éÄÚ´æÓ¦µ±°´Ç°Êö·½Ê½·ÖÅ䣺

          error=bus_dma_tag_create(NULL, /*alignment*/ 4,
              /*boundary*/ 0, /*lowaddr*/ BUS_SPACE_MAXADDR_24BIT,
              /*highaddr*/ BUS_SPACE_MAXADDR, /*filter*/ NULL, /*filterarg*/ NULL,
              /*maxsize*/ BUS_SPACE_MAXSIZE_24BIT,
              /*nsegments*/ BUS_SPACE_UNRESTRICTED,
              /*maxsegsz*/ BUS_SPACE_MAXSIZE_24BIT, /*flags*/ 0,
              &sc->parent_tag);
          if(error)
              goto bad;

          /* ºÜ¶à¶«Î÷ÊÇ´Ó¸¸±êÇ©¼Ì³Ð¶øÀ´
           * ¼ÙÉèsc->dataÖ¸Ïò´æ´¢¹²ÏíÊý¾ÝµÄ½á¹¹£¬ÀýÈçÒ»¸ö»·»º³åÇø¿ÉÄÜÊÇ£º
           * struct {
           *   u_short rd_pos;
           *   u_short wr_pos;
           *   char    bf[XXX_RING_BUFFER_SIZE]
           * } *data;
           */
          error=bus_dma_tag_create(sc->parent_tag, 1,
              0, BUS_SPACE_MAXADDR, 0, /*filter*/ NULL, /*filterarg*/ NULL,
              /*maxsize*/ sizeof(* sc->data), /*nsegments*/ 1,
              /*maxsegsz*/ sizeof(* sc->data), /*flags*/ 0,
              &sc->data_tag);
          if(error)
              goto bad;

          error = bus_dmamem_alloc(sc->data_tag, &sc->data, /* flags*/ 0,
              &sc->data_map);
          if(error)
               goto bad;

          /* ÔÚ&sc->data_pµÄÇé¿öÏ£¬xxx_alloc_callback()Ö»Êǽ«ÎïÀíµØÖ·
           * ±£´æµ½×÷ΪÆä²ÎÁ¿´«µÝ½øÈ¥µÄÖ¸ÕëÖС£
           * ²Î¿´¹ØÓÚ×ÜÏßÄÚ´æÓ³ÉäÒ»½ÚÖеÄÏêϸÄÚÈÝ¡£
           * ÆäʵÏÖ¿ÉÒÔÏñÕâÑù£º
           *
           * static void
           * xxx_alloc_callback(void *arg, bus_dma_segment_t *seg,
           *     int nseg, int error)
           * {
           *    *(bus_addr_t *)arg = seg[0].ds_addr;
           * }
           */
          bus_dmamap_load(sc->data_tag, sc->data_map, (void *)sc->data,
              sizeof (* sc->data), xxx_alloc_callback, (void *) &sc->data_p,
              /*flags*/0);

¡¡¡¡·ÖÅäÁËËùÓеÄ×ÊÔ´ºó£¬É豸Ӧµ±±»³õʼ»¯¡£³õʼ»¯¿ÉÄܰüÀ¨²âÊÔ ËùÓÐÌØÐÔ£¬È·±£ËüÃÇÆð×÷Óá£

          if(xxx_initialize(sc) < 0)
               goto bad;        

¡¡¡¡×ÜÏß×Óϵͳ½«×Ô¶¯ÔÚ¿ØÖÆÌ¨ÉÏ´òÓ¡ÓÉ̽²âÀý³ÌÉèÖõÄÉ豸ÃèÊö¡£µ« Èç¹ûÇý¶¯³ÌÐòÏë´òӡһЩ¹ØÓÚÉ豸µÄ¶îÍâÐÅÏ¢£¬Ò²ÊÇ¿ÉÄܵģ¬ÀýÈ磺

        device_printf(dev, "has on-card FIFO buffer of %d bytes\n", sc->fifosize);
        

¡¡¡¡Èç¹û³õʼ»¯Àý³ÌÓöµ½ÈκÎÎÊÌ⣬½¨Òé·µ»Ø´íÎó֮ǰ´òÓ¡ÓйØÐÅÏ¢¡£

¡¡¡¡Á¬½ÓÀý³ÌµÄ×îºóÒ»²½Êǽ«É豸Á¬½Óµ½ÄÚºËÖеŦÄÜ×Óϵͳ¡£Íê³É Õâ¸ö²½ÖèµÄ¾«È··½Ê½ÒÀÀµÓÚÇý¶¯³ÌÐòµÄÀàÐÍ£º×Ö·ûÉ豸¡¢¿éÉ豸¡¢ÍøÂç É豸¡¢CAM SCSI×ÜÏßÉ豸µÈµÈ¡£

¡¡¡¡Èç¹ûËùÓоù¹¤×÷Õý³£Ôò·µ»Ø³É¹¦¡£

          error = xxx_attach_subsystem(sc);
          if(error)
              goto bad;

          return 0;        

¡¡¡¡×îºó£¬´¦Àí¼¬ÊÖÇé¿ö¡£·µ»Ø´íÎóǰ£¬ËùÓÐ×ÊÔ´Ó¦µ±±»È¡Ïû·ÖÅä¡£ ÎÒÃÇÀûÓÃÕâÑùÒ»¸öÊÂʵ£º½á¹¹softc´«µÝ¸øÎÒÃÇ֮ǰ±»Á㻯£¬Òò´ËÎÒÃÇ ÄÜÕÒ³öÊÇ·ñ·ÖÅäÁËijЩ×ÊÔ´£ºÈç¹û·ÖÅäÔòËüÃǵÄÃèÊö·û·ÇÁã¡£

          bad:

          xxx_free_resources(sc);
          if(error)
              return error;
          else /* exact error is unknown */
              return ENXIO;

¡¡¡¡Õâ¾ÍÊÇÁ¬½ÓÀý³ÌµÄÈ«²¿¡£


10.10 xxx_isa_detach

¡¡¡¡ Èç¹ûÇý¶¯³ÌÐòÖдæÔÚÕâ¸öº¯Êý£¬ÇÒÇý¶¯³ÌÐò±»±àÒëΪ¿É¼ÓÔØÄ£¿é£¬Ôò Çý¶¯³ÌÐò¾ßÓб»Ð¶ÔصÄÄÜÁ¦¡£Èç¹ûÓ²¼þÖ§³ÖÈȲå°Î£¬ÕâÊÇÒ»¸öºÜÖØÒªµÄ ÌØÐÔ¡£µ«ISA×ÜÏß²»Ö§³ÖÈȲå°Î£¬Òò´ËÕâ¸öÌØÐÔ¶ÔÓÚISAÉ豸²»ÊÇÌØ±ð ÖØÒª¡£Ð¶ÔØÇý¶¯³ÌÐòµÄÄÜÁ¦¿ÉÄÜÔÚµ÷ÊÔʱÓÐÓ㬵«ºÜ¶àÇé¿öÏÂÖ»ÓÐÔÚ Àϰ汾µÄÇý¶¯³ÌÐòĪÃûÆäÃîµØ¿¨×¡ÏµÍ³µÄÇé¿öϲÅÐèÒª°²×°Ð°汾µÄ Çý¶¯³ÌÐò£¬²¢ÇÒÎÞÂÛÈçºÎ¶¼ÐèÒªÖØÆô£¬ÕâÑùʹµÃ»¨·Ñ¾«Á¦Ð´·ÖÀëÀý³Ì ÓÐЩ²»ÖµµÃ¡£ÁíÒ»¸öÐû³ÆÐ¶ÔØÔÊÐíÔÚÓÃÓÚÉú²úµÄ»úÆ÷ÉÏÉý¼¶Çý¶¯³ÌÐòµÄ Â۵㿴ÆðÀ´Ëƺõ¸ü¶àµÄÖ»ÊÇÀíÂÛ¶øÒÑ¡£Éý¼¶Çý¶¯³ÌÐòÊÇÒ»ÏîΣÏյIJÙ×÷£¬ ¾ö²»²»Ó¦µ±ÔÚÓÃÓÚÉú²úµÄ»úÆ÷ÉÏʵÐУ¨²¢ÇÒµ±ÏµÍ³ÔËÐÐÓÚ°²È«Ä£Ê½Ê±Õâ Ò²ÊDz»±»ÔÊÐíµÄ£©¡£È»¶ø£¬³öÓÚÍêÕûÐÔ¿¼ÂÇ£¬»¹ÊÇ»áÌṩ·ÖÀëÀý³Ì¡£

¡¡¡¡ Èç¹ûÇý¶¯³ÌÐò³É¹¦·ÖÀ룬·ÖÀëÀý³Ì·µ»Ø0£¬·ñÔò·µ»Ø´íÎóÂë¡£

¡¡¡¡ ·ÖÀëÂß¼­ÊÇÁ¬½ÓµÄ¾µÏñ¡£Òª×öµÄµÚÒ»¼þÊÂÇé¾ÍÊǽ«Çý¶¯³ÌÐò´ÓÄÚºË ×Óϵͳ·ÖÀë¡£Èç¹ûÉ豸µ±Ç°Õý´ò¿ª×Å£¬Çý¶¯³ÌÐòÓÐÁ½¸öÑ¡Ôñ£º¾Ü¾ø·ÖÀë »òÕßÇ¿ÖÆ¹Ø±Õ²¢¼ÌÐø½øÐзÖÀ롣ѡÓÃÄÄÖÖ·½Ê½È¡¾öÓÚÌØ¶¨ÄÚºË×Óϵͳ Ö´ÐÐÇ¿ÖÆ¹Ø±ÕµÄÄÜÁ¦ºÍÇý¶¯³ÌÐò×÷Õߵį«ºÃ¡£Í¨³£Ç¿ÖƹرÕËÆºõÊÇ ¸üºÃµÄÑ¡Ôñ¡£

          struct xxx_softc *sc = device_get_softc(dev);
          int error;

          error = xxx_detach_subsystem(sc);
          if(error)
              return error;

¡¡¡¡ ÏÂÒ»²½£¬Çý¶¯³ÌÐò¿ÉÄÜÏ£Íû¸´Î»Ó²¼þµ½Ä³ÖÖÒ»ÖµÄ״̬¡£°üÀ¨Í£Ö¹ÈκΠ½«Òª½øÐеĴ«Ê䣬½ûÓÃDMAͨµÀºÍÖжÏÒÔ±ÜÃâÉè±¸ÆÆ»µÄÚ´æ¡£¶ÔÓÚ´ó¶àÊý Çý¶¯³ÌÐò¶øÑÔ£¬ÕâÕýÊǹرÕÀý³ÌËù×öµÄ£¬Òò´ËÈç¹ûÇý¶¯³ÌÐòÖаüÀ¨¹Ø±Õ Àý³Ì£¬ÎÒÃÇÖ»Òªµ÷ÓÃËü¾Í¿ÉÒÔÁË¡£

¡¡¡¡xxx_isa_shutdown(dev);

¡¡¡¡ ×îºóÊÍ·ÅËùÓÐ×ÊÔ´²¢·µ»Ø³É¹¦¡£

          xxx_free_resources(sc);
          return 0;

10.11 xxx_isa_shutdown

¡¡¡¡ µ±ÏµÍ³Òª¹Ø±ÕµÄʱºòµ÷ÓôËÀý³Ì¡£Í¨¹ýËüʹӲ¼þ½øÈëijÖÖÒ»ÖµÄ״̬¡£ ¶ÔÓÚ´ó¶àÊýISAÉ豸¶øÑÔ²»ÐèÒªÌØÊ⶯×÷£¬Òò´ËÕâ¸öº¯Êý²¢·ÇÕæÕý±ØÐ裬 ÒòΪ²»¹ÜÔõÑùÖØÆô¶¯Ê±É豸»á±»ÖØÐ³õʼ»¯¡£µ«ÓÐЩÉ豸±ØÐë°´ÌØ¶¨ ²½Öè¹Ø±Õ£¬ÒÔÈ·±£ÔÚÈíÖØÆôºóÄܱ»ÕýÈ·µØ¼ì²âµ½£¨¶ÔÓںܶàʹÓÃ˽ÓРʶ±ðЭÒéµÄÉè±¸ÌØ±ðÓÐÓã©¡£ºÜ¶àÇé¿öÏ£¬ÔÚÉ豸¼Ä´æÆ÷ÖнûÓÃDMAºÍ Öжϣ¬²¢Í£Ö¹½«Òª½øÐеĴ«ÊäÊǸöºÃÖ÷Ò⡣ȷÇж¯×÷È¡¾öÓÚÓ²¼þ£¬Òò´Ë ÎÒÃÇÎÞ·¨ÔÚ´ËÏêϸÌÖÂÛ¡£


10.12 xxx_intr

¡¡¡¡ µ±ÊÕµ½À´×ÔÌØ¶¨É豸µÄÖжÏʱ¾Í»áµ÷ÓÃÖжϴ¦Àíº¯Êý¡£ISA×ÜÏß²»Ö§³Ö ÖжϹ²Ïí£¨Ä³Ð©ÌØÊâÇé¿öÀýÍ⣩£¬Òò´Ëʵ¼ÊÉÏÈç¹ûÖжϴ¦Àíº¯Êý±»µ÷Ó㬠¼¸ºõ¿ÉÒÔÈ·ÐÅÖжÏÊÇÀ´×ÔÆäÉ豸¡£È»¶ø£¬Öжϴ¦Àíº¯Êý±ØÐëÂÖѯÉ豸 ¼Ä´æÆ÷²¢È·±£ÖжÏÊÇÓÉËüµÄÉ豸²úÉúµÄ¡£Èç¹û²»ÊÇ£¬Öжϴ¦Àíº¯ÊýÓ¦µ± ·µ»Ø¡£

¡¡¡¡ ISAÇý¶¯³ÌÐòµÄ¾ÉÔ¼¶¨ÊÇÈ¡É豸µ¥ÔªºÅ×÷Ϊ²ÎÁ¿¡£ÏÖÔÚÒѾ­·ÏÆú£¬µ± µ÷ÓÃbus_setup_intr()ʱÐÂÇý¶¯³ÌÐò½ÓÊÕÈκΠÔÚÁ¬½ÓÀý³ÌÖÐΪËûÃÇÖ¸¶¨µÄ²ÎÁ¿¡£¸ù¾ÝÐÂÔ¼¶¨£¬ËüÓ¦µ±ÊÇÖ¸Ïò½á¹¹ softcµÄÖ¸Õë¡£Òò´ËÖжϴ¦Àíº¯Êýͨ³£ÏñÏÂÃæÄÇÑù¿ªÊ¼£º

          static void
          xxx_intr(struct xxx_softc *sc)
          {

        

¡¡¡¡ ËüÔËÐÐÔÚÓÉbus_setup_intr()µÄÖжÏÀàÐͲÎÊýÖ¸¶¨ µÄÖжÏÓÅÏȼ¶ÉÏ¡£ÕâÒâζ׎ûÓÃËùÓÐÆäËûͬÀàÐ͵ÄÖжϺÍËùÓÐÈí¼þÖжϡ£

¡¡¡¡ ΪÁ˱ÜÃ⾺Õù£¬Öжϴ¦ÀíÀý³Ìͨд³ÉÑ­»·ÐÎʽ£º

          while(xxx_interrupt_pending(sc)) {
              xxx_process_interrupt(sc);
              xxx_acknowledge_interrupt(sc);
          }        

¡¡¡¡ Öжϴ¦Àíº¯Êý±ØÐëÖ»ÏòÉ豸Ӧ´ðÖжϣ¬µ«²»ÄÜÏòÖжϿØÖÆÆ÷Ó¦´ð£¬ºóÕßÓÉ ÏµÍ³¸ºÔð´¦Àí¡£


µÚ11Õ ¡¡PCIÉ豸

·­Ò룺spellar @SMTH.

¡¡¡¡±¾Õ½«ÌÖÂÛFreeBSDΪÁ˸øPCI×ÜÏßÉϵÄÉ豸±àдÇý¶¯³ÌÐò¶øÌṩµÄ»úÖÆ¡£


11.1 ̽²âÓëÁ¬½Ó

¡¡¡¡Õâ¶ùµÄÐÅÏ¢ÊǹØÓÚPCI×ÜÏß´úÂëÈçºÎµü´úͨ¹ýδÁ¬½ÓµÄÉ豸£¬²¢²é¿´Ð ¼ÓÔØµÄkldÊÇ·ñ»áÁ¬½ÓÆäÖÐÒ»¸ö¡£


11.1.1 ʾÀýÇý¶¯³ÌÐòÔ´´úÂë(mypci.c)

/*
 * ÓëPCIº¯Êý½øÐн»»¥µÄ¼òµ¥KLD
 *
 * Murray Stokely
 */

#include <sys/param.h>		/* kernel.hÖÐʹÓõ͍Òå */
#include <sys/module.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/kernel.h>		/* Ä£¿é³õʼ»¯ÖÐʹÓõÄÀàÐÍ */
#include <sys/conf.h>		/* cdevsw½á¹¹ */
#include <sys/uio.h>		/* uio½á¹¹ */
#include <sys/malloc.h>
#include <sys/bus.h>		/* pci×ÜÏßÓõ½µÄ½á¹¹¡¢Ô­ÐÍ */

#include <machine/bus.h>
#include <sys/rman.h>
#include <machine/resource.h>

#include <dev/pci/pcivar.h>	/* ΪÁËʹÓÃget_pciºê! */
#include <dev/pci/pcireg.h>

/* softc±£´æÎÒÃÇÿ¸öʵÀýµÄÊý¾Ý¡£ */
struct mypci_softc {
	device_t	my_dev;
	struct cdev	*my_cdev;
};

/* º¯ÊýÔ­ÐÍ */
static d_open_t		mypci_open;
static d_close_t	mypci_close;
static d_read_t		mypci_read;
static d_write_t	mypci_write;

/* ×Ö·ûÉ豸Èë¿Úµã */

static struct cdevsw mypci_cdevsw = {
	.d_version =	D_VERSION,
	.d_open =	mypci_open,
	.d_close =	mypci_close,
	.d_read =	mypci_read,
	.d_write =	mypci_write,
	.d_name =	"mypci",
};

/*
 * ÔÚcdevswÀý³ÌÖУ¬ÎÒÃÇͨ¹ý½á¹¹ÌåcdevÖеijÉÔ±si_drv1ÕÒ³öÎÒÃǵÄsoftc¡£
 * µ±ÎÒÃǽ¨Á¢/devÏîʱ£¬ÔÚÎÒÃǵÄÒѸ½×ŵÄÀý³ÌÖУ¬
 * ÎÒÃÇÉèÖÃÕâ¸ö±äÁ¿Ö¸ÏòÎÒÃǵÄsoftc¡£
 */

int
mypci_open(struct cdev *dev, int oflags, int devtype, d_thread_t *td)
{
	struct mypci_softc *sc;

	/* Look up our softc. */
	sc = dev->si_drv1;
	device_printf(sc->my_dev, "Opened successfully.\n");
	return (0);
}

int
mypci_close(struct cdev *dev, int fflag, int devtype, d_thread_t *td)
{
	struct mypci_softc *sc;

	/* Look up our softc. */
	sc = dev->si_drv1;
	device_printf(sc->my_dev, "Closed.\n");
	return (0);
}

int
mypci_read(struct cdev *dev, struct uio *uio, int ioflag)
{
	struct mypci_softc *sc;

	/* Look up our softc. */
	sc = dev->si_drv1;
	device_printf(sc->my_dev, "Asked to read %d bytes.\n", uio->uio_resid);
	return (0);
}

int
mypci_write(struct cdev *dev, struct uio *uio, int ioflag)
{
	struct mypci_softc *sc;

	/* Look up our softc. */
	sc = dev->si_drv1;
	device_printf(sc->my_dev, "Asked to write %d bytes.\n", uio->uio_resid);
	return (0);
}

/* PCIÖ§³Öº¯Êý */

/*
 * ½«Ä³¸öÉèÖõıêʶÓëÕâ¸öÇý¶¯³ÌÐòÖ§³ÖµÄ±êʶÏà±È½Ï¡£
 * Èç¹ûÏà·û£¬ÉèÖÃÃèÊö×Ö·û²¢·µ»Ø³É¹¦¡£
 */
static int
mypci_probe(device_t dev)
{

	device_printf(dev, "MyPCI Probe\nVendor ID : 0x%x\nDevice ID : 0x%x\n",
	    pci_get_vendor(dev), pci_get_device(dev));

	if (pci_get_vendor(dev) == 0x11c1) {
		printf("We've got the Winmodem, probe successful!\n");
		device_set_desc(dev, "WinModem");
		return (BUS_PROBE_DEFAULT);
	}
	return (ENXIO);
}

/* Ö»Óе±Ì½²â³É¹¦Ê±²Åµ÷ÓÃÁ¬½Óº¯Êý */

static int
mypci_attach(device_t dev)
{
	struct mypci_softc *sc;

	printf("MyPCI Attach for : deviceID : 0x%x\n", pci_get_devid(dev));

	/* Look up our softc and initialize its fields. */
	sc = device_get_softc(dev);
	sc->my_dev = dev;

	/*
	 * Create a /dev entry for this device.  The kernel will assign us
	 * a major number automatically.  We use the unit number of this
	 * device as the minor number and name the character device
	 * "mypci<unit>".
	 */
	sc->my_cdev = make_dev(&mypci_cdevsw, device_get_unit(dev),
	    UID_ROOT, GID_WHEEL, 0600, "mypci%u", device_get_unit(dev));
	sc->my_cdev->si_drv1 = sc;
	printf("Mypci device loaded.\n");
	return (0);
}

/* ·ÖÀëÉ豸¡£ */

static int
mypci_detach(device_t dev)
{
	struct mypci_softc *sc;

	/* Teardown the state in our softc created in our attach routine. */
	sc = device_get_softc(dev);
	destroy_dev(sc->my_cdev);
	printf("Mypci detach!\n");
	return (0);
}

/* ϵͳ¹Ø±ÕÆÚ¼äÔÚsyncÖ®ºóµ÷Óᣠ*/

static int
mypci_shutdown(device_t dev)
{

	printf("Mypci shutdown!\n");
	return (0);
}

/*
 * É豸¹ÒÆðÀý³Ì¡£
 */
static int
mypci_suspend(device_t dev)
{

	printf("Mypci suspend!\n");
	return (0);
}

/*
 * É豸»Ö¸´£¨ÖØÐ¿ªÊ¼£©Àý³Ì¡£
 */
static int
mypci_resume(device_t dev)
{

	printf("Mypci resume!\n");
	return (0);
}

static device_method_t mypci_methods[] = {
	/* É豸½Ó¿Ú */
	DEVMETHOD(device_probe,		mypci_probe),
	DEVMETHOD(device_attach,	mypci_attach),
	DEVMETHOD(device_detach,	mypci_detach),
	DEVMETHOD(device_shutdown,	mypci_shutdown),
	DEVMETHOD(device_suspend,	mypci_suspend),
	DEVMETHOD(device_resume,	mypci_resume),

	{ 0, 0 }
};

static devclass_t mypci_devclass;

DEFINE_CLASS_0(mypci, mypci_driver, mypci_methods, sizeof(struct mypci_softc));
DRIVER_MODULE(mypci, pci, mypci_driver, mypci_devclass, 0, 0);

11.1.2 ʾÀýÇý¶¯³ÌÐòµÄMakefile

# Çý¶¯³ÌÐòmypciµÄMakefile

KMOD=	mypci
SRCS=	mypci.c
SRCS+=	device_if.h bus_if.h pci_if.h

.include <bsd.kmod.mk>

¡¡¡¡Èç¹ûÄ㽫ÉÏÃæµÄÔ´ÎļþºÍ Makefile·ÅÈëÒ»¸öĿ¼£¬Äã¿ÉÒÔÔËÐÐ make±àÒëʾÀýÇý¶¯³ÌÐò¡£ »¹ÓУ¬Äã¿ÉÒÔÔËÐÐmake load ½«Çý¶¯³ÌÐò×°ÔØµ½µ±Ç°ÕýÔÚÔËÐеÄÄÚºËÖУ¬¶ømake unload¿ÉÔÚ×°ÔØºóÐ¶ÔØÇý¶¯³ÌÐò¡£


11.1.3 ¸ü¶à×ÊÔ´


11.2 ×ÜÏß×ÊÔ´

¡¡¡¡FreeBSDΪ´Ó¸¸×ÜÏßÇëÇó×ÊÔ´ÌṩÁËÒ»ÖÖÃæÏò¶ÔÏóµÄ»úÖÆ¡£¼¸ºõËùÓÐÉ豸 ¶¼ÊÇijÖÖÀàÐ͵Ä×ÜÏߣ¨PCI, ISA, USB, SCSIµÈµÈ£©µÄº¢×Ó³ÉÔ±£¬²¢ÇÒÕâЩÉ豸 ÐèÒª´ÓËûÃǵĸ¸×ÜÏß»ñÈ¡×ÊÔ´£¨ÀýÈçÄÚ´æ¶Î, ÖжÏÏß, »òÕßDMAͨµÀ£©¡£


11.2.1 »ùµØÖ·¼Ä´æÆ÷

¡¡¡¡ÎªÁ˶ÔPCIÉ豸×öЩÓÐÓõÄÊÂÇ飬ÄãÐèÒª´ÓPCIÅäÖÿռä»ñÈ¡ Base Address Registers (BARs)¡£»ñÈ¡BARʱµÄ PCIÌØ¶¨µÄϸ½Ú±»³éÏóÔÚº¯Êýbus_alloc_resource()ÖС£

¡¡¡¡ÀýÈ磬һ¸öµäÐ͵ÄÇý¶¯³ÌÐò¿ÉÄÜÔÚattach() º¯ÊýÖÐÓÐЩÀàËÆÏÂÃæµÄ¶«Î÷£º

    sc->bar0id = PCIR_BAR(0);
    sc->bar0res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bar0id,
				  0, ~0, 1, RF_ACTIVE);
    if (sc->bar0res == NULL) {
        printf("Memory allocation of PCI base register 0 failed!\n");
        error = ENXIO;
        goto fail1;
    }

    sc->bar1id = PCIR_BAR(1);
    sc->bar1res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->bar1id,
				  0, ~0, 1, RF_ACTIVE);
    if (sc->bar1res == NULL) {
        printf("Memory allocation of PCI base register 1 failed!\n");
        error =  ENXIO;
        goto fail2;
    }
    sc->bar0_bt = rman_get_bustag(sc->bar0res);
    sc->bar0_bh = rman_get_bushandle(sc->bar0res);
    sc->bar1_bt = rman_get_bustag(sc->bar1res);
    sc->bar1_bh = rman_get_bushandle(sc->bar1res);

¡¡¡¡Ã¿¸ö»ùÖ·¼Ä´æÆ÷µÄ¾ä±ú±»±£´æÔÚsoftc ½á¹¹ÖУ¬ÒÔ±ãÒÔºó¿ÉÒÔʹÓÃËüÃÇÏòÉ豸дÈë¡£

¡¡¡¡È»ºó¾ÍÄÜʹÓÃÕâЩ¾ä±úÓëbus_space_*º¯ÊýÒ»Æð ¶ÁдÉ豸¼Ä´æÆ÷¡£ÀýÈ磬Çý¶¯³ÌÐò¿ÉÄܰüº¬ÈçϵĿì½Ýº¯Êý£¬ÓÃÀ´¶ÁÈ¡°å×Ó ÌØ¶¨µÄ¼Ä´æÆ÷£º

uint16_t
board_read(struct ni_softc *sc, uint16_t address)
{
    return bus_space_read_2(sc->bar1_bt, sc->bar1_bh, address);
}

¡¡¡¡ÀàËÆµÄ£¬¿ÉÒÔÓÃÏÂÃæµÄº¯Êýд¼Ä´æÆ÷£º

void
board_write(struct ni_softc *sc, uint16_t address, uint16_t value)
{
    bus_space_write_2(sc->bar1_bt, sc->bar1_bh, address, value);
}

¡¡¡¡ÕâЩº¯ÊýÒÔ8룬16λºÍ32λµÄ°æ±¾´æÔÚ£¬ÄãÓ¦µ±ÏàÓ¦µØÊ¹Óà bus_space_{read|write}_{1|2|4}¡£

×¢Òâ: ÔÚ FreeBSD 7.0 ºÍ¸ü¸ß°æ±¾ÖУ¬ ¿ÉÒÔÓà bus_* º¯ÊýÀ´´úÌæ bus_space_*¡£ bus_* º¯ÊýʹÓõIJÎÊýÊÇ struct resource * Ö¸Õ룬 ¶ø²»ÊÇ bus tag ºÍ¾ä±ú¡£ ÕâÑù£¬ Äú¾Í¿ÉÒÔ½« softc ÖÐµÄ bus tag ºÍ bus ¾ä±úÕâÁ½¸ö³ÉÔ±±äÁ¿È¥µô£¬ ²¢½« board_read() º¯Êý¸ÄдΪ£º

uint16_t
board_read(struct ni_softc *sc, uint16_t address)
{
	return (bus_read(sc->bar1res, address));
}

11.2.2 ÖжÏ

¡¡¡¡Öжϰ´ÕպͷÖÅäÄÚ´æ×ÊÔ´ÏàËÆµÄ·½Ê½´ÓÃæÏò¶ÔÏóµÄ×ÜÏß´úÂë·ÖÅä¡£Ê×ÏÈ£¬ ±ØÐë´Ó¸¸×ÜÏß·ÖÅäIRQ×ÊÔ´£¬È»ºó±ØÐëÉèÖÃÖжϴ¦Àíº¯ÊýÀ´´¦ÀíÕâ¸öIRQ¡£

¡¡¡¡ÔÙÒ»´Î£¬À´×ÔÉ豸attach()º¯ÊýµÄÀý×Ó±ÈÎÄ×Ö ¸ü¾ß˵Ã÷ÐÔ¡£

/* È¡µÃIRQ×ÊÔ´ */

    sc->irqid = 0x0;
    sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &(sc->irqid),
				  0, ~0, 1, RF_SHAREABLE | RF_ACTIVE);
    if (sc->irqres == NULL) {
	printf("IRQ allocation failed!\n");
	error = ENXIO;
	goto fail3;
    }

    /* ÏÖÔÚÎÒÃÇÓ¦µ±ÉèÖÃÖжϴ¦Àíº¯Êý */

    error = bus_setup_intr(dev, sc->irqres, INTR_TYPE_MISC,
			   my_handler, sc, &(sc->handler));
    if (error) {
	printf("Couldn't set up irq\n");
	goto fail4;
    }

¡¡¡¡ÔÚÉ豸µÄ·ÖÀëÀý³ÌÖбØÐë×¢ÒâһЩÎÊÌâ¡£Äã±ØÐëÍ£¶ÙÉ豸µÄÖжÏÁ÷£¬ ²¢ÒƳýÖжϴ¦Àíº¯Êý¡£Ò»µ©bus_teardown_intr() ·µ»Ø£¬ÄãÖªµÀÄãµÄÖжϴ¦Àíº¯Êý²»»áÔÙ±»µ÷Ó㬲¢ÇÒËùÓпÉÄÜÒѾ­Ö´ÐÐÁË Õâ¸öÖжϴ¦Àíº¯ÊýµÄÏ̶߳¼ÒѾ­·µ»Ø¡£ÓÉÓڴ˺¯Êý¿ÉÒÔ˯Ãߣ¬µ÷Óô˺¯Êýʱ Äã±ØÐë²»ÄÜÓµÓÐÈκλ¥³âÌå¡£


11.2.3 DMA

¡¡¡¡±¾½ÚÒÑ·ÏÆú£¬Ö»ÊÇÓÉÓÚÀúÊ·Ô­Òò¶ø¸ø³ö¡£´¦ÀíÕâЩÎÊÌâµÄÊʵ±·½·¨ÊÇ Ê¹ÓÃbus_space_dma*()º¯Êý¡£µ±¸üÐÂÕâÒ»½ÚÒÔ·´Ó³ ÄÇÑùÓ÷¨Ê±£¬Õâ¶Î¾Í¿ÉÄܱ»È¥µô¡£È»¶ø£¬Ä¿Ç°API»¹²»¶ÏÓÐЩ±ä¶¯£¬Òò´ËÒ»µ© ËüÃǹ̶¨ÏÂÀ´ºó£¬¸üÐÂÕâÒ»½ÚÀ´·´Ó³ÄÇЩ¸Ä¶¯¾ÍºÜºÃÁË¡£

¡¡¡¡ÔÚPCÉÏ£¬Ïë½øÐÐ×ÜÏßÖ÷¿ØDMAµÄÍâΧÉ豸±ØÐë´¦ÀíÎïÀíµØÖ·£¬ÓÉÓÚ FreeBSDʹÓÃÐéÄâÄÚ´æ²¢ÇÒÖ»´¦ÀíÐ鵨ַ£¬ÕâÈÔÊǸöÎÊÌâ¡£ÐÒÔ˵ÄÊÇ£¬Óиö º¯Êý£¬vtophys()¿ÉÒÔ°ïÖúÎÒÃÇ¡£

#include <vm/vm.h>
#include <vm/pmap.h>

#define vtophys(virtual_address) (...)

¡¡¡¡È»¶øÕâ¸ö½â¾ö°ì·¨ÔÚalphaÉÏÓе㲻һÑù£¬²¢ÇÒÎÒÃÇÕæÕýÏëÒªµÄÊÇÒ»¸ö ³ÆÎªvtobus()µÄº¯Êý¡£

#if defined(__alpha__)
#define vtobus(va)      alpha_XXX_dmamap((vm_offset_t)va)
#else
#define vtobus(va)      vtophys(va)
#endif

11.2.4 È¡Ïû·ÖÅä×ÊÔ´

¡¡¡¡È¡Ïûattach()ÆÚ¼ä·ÖÅäµÄËùÓÐ×ÊÔ´·Ç³£ÖØÒª¡£ ±ØÐëСÐĽ÷É÷£¬¼´Ê¹ÔÚʧ°ÜµÄÌõ¼þÏÂÒ²Òª±£Ö¤È¡Ïû·ÖÅäÄÇЩÕýÈ·µÄ¶«Î÷£¬ ÕâÑùµ±ÄãµÄÇý¶¯³ÌÐòÈ¥µôºóϵͳÈÔÈ»¿ÉÒÔʹÓá£


µÚ12Õ ¡¡Í¨Ó÷ÃÎÊ·½·¨SCSI¿ØÖÆÆ÷

д×÷£ºSergey Babkin. ¸Ä±àΪÊֲ᣺Murray Stokely. ·­Ò룺spellar @SMTH.

12.1 Ìá¸Ù

¡¡¡¡±¾Îĵµ¼Ù¶¨¶ÁÕß¶ÔFreeBSDµÄÉ豸Çý¶¯³ÌÐòºÍSCSIЭÒéÓдóÖÂÁ˽⣬ ±¾ÎĵµÖкܶàÐÅÏ¢ÊÇ´ÓÒÔÏÂÇý¶¯³ÌÐòÖУº

  • ncr (/sys/pci/ncr.c) ÓÉWolfgang Stanglmeier and Stefan Esser±àд

  • sym (/sys/dev/sym/sym_hipd.c) ÓÉGerard Roudier±àд

  • aic7xxx (/sys/dev/aic7xxx/aic7xxx.c) ÓÉJustin T. Gibbs±àд

¡¡¡¡ºÍ´ÓCAMµÄ´úÂë±¾Éí£¨×÷Õß Justin T. Gibbs£¬ ¼û/sys/cam/*£©ÖÐժ¼¡£µ±Ò»Ð©½â¾ö·½·¨¿´ÆðÀ´ ¼«¾ßÂß¼­ÐÔ£¬²¢ÇÒ»ù±¾ÉÏÊÇ´Ó Justin T. Gibbs µÄ´úÂëÖÐÒ»×Ö²»²îµØÕªÂ¼Ê±£¬ ÎÒ½«Æä±ê¼ÇΪ¡°recommended¡±¡£

¡¡¡¡±¾ÎĵµÒÔα´úÂëÀý×Ó½øÐÐ˵Ã÷¡£¾¡¹ÜÓÐʱÀý×ÓÖаüº¬ºÜ¶àϸ½Ú£¬²¢ÇÒ ¿´ÆðÀ´ºÜÏñÕæÕý´úÂ룬µ«ËüÈÔȻֻÊÇα´úÂë¡£ÕâÑùдÊÇΪÁËÒÔÒ»ÖÖ¿ÉÀí½â µÄ·½Ê½À´Õ¹Ê¾¸ÅÄî¡£¶ÔÓÚÕæÕýµÄÇý¶¯³ÌÐò£¬ÆäËü·½·¨¿ÉÄܸüÄ£¿é»¯£¬²¢ÇÒ ¸ü¼Ó¸ßЧ¡£ÎĵµÒ²¶ÔÓ²¼þϸ½Ú½øÐгéÏ󣬶ÔÓÚÄÇЩ»áÄ£ºýÎÒÃÇËùҪչʾµÄ ¸ÅÄîµÄÎÊÌ⣬»ò±»ÈÏΪÔÚ¿ª·¢ÕßÊÖ²áµÄÆäËûÕ½ÚÖÐÒÑÓÐÃèÊöµÄÎÊÌâÒ²×öͬÑù ´¦Àí¡£ÕâЩϸ½Úͨ³£ÒÔµ÷ÓþßÓÐÃèÊöÐÔÃû×ֵĺ¯Êý¡¢×¢ÊÍ»òαÓï¾äµÄÐÎʽչÏÖ¡£ ÐÒÔ˵ÄÊÇ£¬¾ßÓÐʵ¼Ê¼ÛÖµµÄÍêÕûÀý×Ó£¬°üÀ¨ËùÓÐϸ½Ú£¬¿ÉÒÔÔÚÕæÕýµÄÇý¶¯ ³ÌÐòÖÐÕÒµ½¡£


12.2 ͨÓûù´¡½á¹¹

¡¡¡¡CAM´ú±íͨÓ÷ÃÎÊ·½·¨£¨Common Access Method£©¡£ËüÒÔÀàSCSI·½Ê½Ñ°Ö· I/O×ÜÏß¡£Õâ¾ÍÔÊÐí½«Í¨ÓÃÉ豸Çý¶¯³ÌÐòºÍ¿ØÖÆI/O×ÜÏßµÄÇý¶¯³ÌÐò·ÖÀ뿪À´£º ÀýÈç´ÅÅÌÇý¶¯³ÌÐòÄÜͬʱ¿ØÖÆSCSI¡¢IDE¡¢ÇÒ/»òÈÎºÎÆäËû×ÜÏßÉϵĴÅÅÌ£¬ ÕâÑù´ÅÅÌÇý¶¯³ÌÐò²¿·Ö²»±ØÎªÃ¿ÖÖеÄI/O×ÜÏß¶øÖØÐ´£¨»ò¿½±´Ð޸ģ©¡£ ÕâÑù£¬Á½¸ö×îÖØÒªµÄ»î¶¯ÊµÌåÊÇ£º

  • ÍâΧÉ豸ģ¿é - ÍâΧÉ豸£¨´ÅÅÌ£¬ ´Å´ø£¬ CD-ROMµÈ£©µÄÇý¶¯³ÌÐò

  • SCSI½Ó¿ÚÄ£¿é(SIM) - Á¬½Óµ½I/O×ÜÏߣ¬ÈçSCSI»òIDE£¬µÄÖ÷»ú×ÜÏßÊÊÅäÆ÷Çý¶¯³ÌÐò¡£

¡¡¡¡ÍâΧÉ豸Çý¶¯³ÌÐò´ÓOS½ÓÊÕÇëÇ󣬽«ËüÃÇת»»ÎªSCSIÃüÁîÐòÁв¢½« ÕâЩSCSIÃüÁî´«µÝµ½SCSI½Ó¿ÚÄ£¿é¡£SCSI½Ó¿ÚÄ£¿é¸ºÔð½«ÕâЩÃüÁî´«µÝ¸ø ʵ¼ÊÓ²¼þ£¨»òÕßÈç¹ûʵ¼ÊÓ²¼þ²»ÊÇSCSI£¬¶øÊÇÀýÈçIDE£¬ÔòÒ²Òª½«ÕâЩSCSI ÃüÁîת»»ÎªÓ²¼þµÄnativeÃüÁ¡£

¡¡¡¡ÓÉÓÚÕâ¶ùÎÒÃǸÐÐËȤµÄÊDZàдSCSIÊÊÅäÆ÷Çý¶¯³ÌÐò£¬´Ó´Ë´¦¿ªÊ¼ÎÒÃÇ ½«´ÓSIMµÄ½Ç¶È¿¼ÂÇËùÓеÄÊÂÇé¡£

¡¡¡¡µäÐ͵ÄSIMÇý¶¯³ÌÐòÐèÒª°üÀ¨ÈçϵÄCAMÏà¹ØµÄÍ·Îļþ£º

#include <cam/cam.h>
#include <cam/cam_ccb.h>
#include <cam/cam_sim.h>
#include <cam/cam_xpt_sim.h>
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>

¡¡¡¡Ã¿¸öSIMÇý¶¯³ÌÐò±ØÐë×öµÄµÚÒ»¼þÊÂÇéÊÇÏòCAM×Óϵͳע²áËü×Ô¼º¡£ ÕâÔÚÇý¶¯³ÌÐòµÄxxx_attach()º¯Êý£¨´Ë´¦ºÍÒÔºóµÄ xxx_ÓÃÓÚÖ¸´øÎ¨Ò»µÄÇý¶¯³ÌÐòÃû×Öǰ׺£©ÆÚ¼äÍê³É¡£ xxx_attach()º¯Êý×ÔÉíÓÉϵͳ×ÜÏß×Ô¶¯ÅäÖôúÂë µ÷Óã¬ÎÒÃÇÔڴ˲»ÃèÊöÕⲿ·Ö´úÂë¡£

¡¡¡¡ÕâÐèÒªºÃ¼¸²½À´Íê³É£ºÊ×ÏÈÐèÒª·ÖÅäÓëSIM¹ØÁªµÄÇëÇó¶ÓÁУº

    struct cam_devq *devq;

    if(( devq = cam_simq_alloc(SIZE) )==NULL) {
        error; /* һЩ´¦Àí´íÎóµÄ´úÂë */
    }

¡¡¡¡´Ë´¦ SIZE ΪҪ·ÖÅäµÄ¶ÓÁеĴóС£¬ ËüÄܰüº¬µÄ×î´óÇëÇóÊýÄ¿¡£ ËüÊÇ SIM Çý¶¯³ÌÐòÔÚ SCSI ¿¨ÉÏÄܹ»²¢Ðд¦ÀíµÄÇëÇóµÄÊýÄ¿¡£Ò»°ã¿ÉÒÔÈçϹÀË㣺

SIZE = NUMBER_OF_SUPPORTED_TARGETS * MAX_SIMULTANEOUS_COMMANDS_PER_TARGET

¡¡¡¡ÏÂÒ»²½ÎªÎÒÃǵÄSIM´´½¨ÃèÊö·û£º

    struct cam_sim *sim;

    if(( sim = cam_sim_alloc(action_func, poll_func, driver_name,
            softc, unit, max_dev_transactions, 
            max_tagged_dev_transactions, devq) )==NULL) {
        cam_simq_free(devq);
        error; /* һЩ´íÎó´¦Àí´úÂë */
    }

¡¡¡¡×¢ÒâÈç¹ûÎÒÃDz»ÄÜ´´½¨SIMÃèÊö·û£¬ÎÒÃÇÒ²ÊÍ·Å devq£¬ÒòΪÎÒÃÇ¶ÔÆäÎÞ·¨×öÈÎºÎÆäËûÊÂÇ飬 ¶øÇÒÎÒÃÇÏë½ÚÔ¼ÄÚ´æ¡£

¡¡¡¡Èç¹ûSCSI¿¨ÉÏÓжàÌõSCSI×ÜÏߣ¬ÔòÿÌõ×ÜÏßÐèÒªËü×Ô¼ºµÄ cam_sim ½á¹¹¡£

¡¡¡¡Ò»¸öÓÐȤµÄÎÊÌâÊÇ£¬Èç¹ûSCSI¿¨Óв»Ö»Ò»ÌõSCSI×ÜÏßÎÒÃǸÃÔõô×ö£¬ ÿ¸ö¿¨ÐèÒªÒ»¸ödevq½á¹¹»¹ÊÇÿÌõSCSI×ÜÏߣ¿ ÔÚCAM´úÂëµÄ×¢ÊÍÖиø³öµÄ´ð°¸ÊÇ£ºÈÎÒ»·½Ê½¾ù¿É£¬ÓÉÇý¶¯³ÌÐòµÄ×÷Õß Ñ¡Ôñ¡£

¡¡¡¡²ÎÁ¿Îª£º

  • action_func - Ö¸ÏòÇý¶¯³ÌÐò xxx_action º¯ÊýµÄÖ¸Õë¡£

    static void xxx_action ( struct cam_sim *sim, union ccb *ccb );

  • poll_func - Ö¸ÏòÇý¶¯³ÌÐò xxx_poll()º¯ÊýµÄÖ¸Õë¡£

    static void xxx_poll ( struct cam_sim *sim );

  • driver_name - ʵ¼ÊÇý¶¯³ÌÐòµÄÃû×Ö£¬ÀýÈç ¡°ncr¡±»ò¡°wds¡±¡£

  • softc - Ö¸ÏòÕâ¸öSCSI¿¨ Çý¶¯³ÌÐòµÄÄÚ²¿ÃèÊö·ûµÄÖ¸Õë¡£Õâ¸öÖ¸ÕëÒÔºó±»Çý¶¯³ÌÐòÓÃÀ´»ñÈ¡ ˽ÓÐÊý¾Ý¡£

  • unit - ¿ØÖÆÆ÷µ¥ÔªºÅ£¬ÀýÈç¶ÔÓÚ¿ØÖÆÆ÷ ¡°wds0¡±µÄ´ËÊý×Ö½«Îª0¡£

  • max_dev_transactions - ÎÞ±êǩģʽÏÂÿ¸öSCSIÄ¿±êµÄ ×î´ó²¢·¢£¨simultaneous£©ÊÂÎñÊý¡£Õâ¸öÖµÒ»°ã¼¸ºõ×ÜÊǵÈÓÚ1£¬Ö»ÓÐ·Ç SCSI¿¨²Å¿ÉÄÜÀýÍâ¡£´ËÍ⣬Èç¹ûÇý¶¯³ÌÐòÏ£ÍûÖ´ÐÐÒ»¸öÊÂÎñµÄͬʱ׼±¸Áí Ò»¸öÊÂÎñ£¬¿ÉÒÔ½«ÆäÉèÖÃΪ2£¬µ«Ëƺõ²»ÖµµÃÔö¼ÓÕâÖÖ¸´ÔÓÐÔ¡£

  • max_tagged_dev_transactions - ͬÑùµÄ¶«Î÷£¬µ«ÊÇ ÔÚ±êǩģʽÏ¡£±êÇ©ÊÇSCSIÔÚÉ豸ÉÏ·¢Æð¶à¸öÊÂÎñµÄ·½Ê½£ºÃ¿¸öÊÂÎñ ±»¸³ÓèÒ»¸öΨһµÄ±êÇ©£¬²¢±»·¢Ë͵½É豸¡£µ±É豸Íê³ÉijЩÊÂÎñ£¬Ëü ½«½á¹ûÁ¬Í¬±êǩһÆð·¢ËÍ»ØÀ´£¬ÕâÑùSCSIÊÊÅäÆ÷£¨ºÍÇý¶¯³ÌÐò£©¾ÍÄÜÖªµÀ ÄĸöÊÂÎñÍê³ÉÁË¡£´Ë²ÎÁ¿Ò²±»ÈÏΪÊÇ×î´ó±êÇ©Éî¶È¡£ËüÈ¡¾öÓÚSCSI ÊÊÅäÆ÷µÄÄÜÁ¦¡£

¡¡¡¡×îºóÎÒÃÇ×¢²áÓëÎÒÃǵÄSCSIÊÊÅäÆ÷¹ØÁªµÄSCSI×ÜÏß¡£

    if(xpt_bus_register(sim, bus_number) != CAM_SUCCESS) {
        cam_sim_free(sim, /*free_devq*/ TRUE);
        error; /* һЩ´íÎó´¦Àí´úÂë */
    }

¡¡¡¡Èç¹ûÿÌõSCSI×ÜÏßÓÐÒ»¸ödevq½á¹¹£¨¼´£¬ ÎÒÃǽ«´øÓжàÌõ×ÜÏߵĿ¨¿´×÷¶à¸ö¿¨£¬Ã¿¸ö¿¨´øÓÐÒ»Ìõ×ÜÏߣ©£¬Ôò×ÜÏߺŠ×ÜÊÇΪ0£¬·ñÔòSCSI¿¨ÉϵÄÿÌõ×ÜÏßÓ¦µ±Óв»Í¬µÄºÅ¡£Ã¿Ìõ×ÜÏßÐèÒª Ëü×Ô¼ºµ¥¶ÀµÄcam_sim½á¹¹¡£

¡¡¡¡ÕâÖ®ºóÎÒÃǵĿØÖÆÆ÷ÍêÈ«¹Ò½Óµ½CAMϵͳ¡£ÏÖÔÚ devqµÄÖµ¿ÉÒÔ±»¶ªÆú£ºÔÚËùÓÐÒÔºó´ÓCAM·¢³öµÄ µ÷ÓÃÖн«ÒÔsimΪ²ÎÁ¿£¬devq¿ÉÒÔÓÉËüµ¼³ö¡£

¡¡¡¡CAMΪÕâЩÒ첽ʼþÌṩÁË¿ò¼Ü¡£ÓÐЩʼþÀ´×Եײ㣨SIMÇý¶¯³ÌÐò£©£¬ ÓÐЩÀ´×ÔÍâΧÉ豸Çý¶¯³ÌÐò£¬»¹ÓÐһЩÀ´×ÔCAM×Óϵͳ±¾Éí¡£ÈκÎÇý¶¯ ³ÌÐò¶¼¿ÉÒÔΪijЩÀàÐ͵ÄÒ첽ʼþ×¢²á»Øµ÷£¬ÕâÑùÄÇЩʼþ·¢ÉúʱËü¾Í »á±»Í¨Öª¡£

¡¡¡¡ÕâÖÖʼþµÄÒ»¸öµäÐÍÀý×Ó¾ÍÊÇÉ豸¸´Î»¡£Ã¿¸öÊÂÎñºÍʼþÒÔ ¡°path¡±µÄ·½Ê½Çø·ÖËüÃÇËù×÷ÓõÄÉ豸¡£Ä¿±êÌØ¶¨µÄʼþ ͨ³£ÔÚÓëÉ豸½øÐÐÊÂÎñ´¦ÀíÆÚ¼ä·¢Éú¡£Òò´ËÄǸöÊÂÎñµÄ·¾¶¿ÉÒÔ±»ÖØÓà À´±¨¸æ´Ëʼþ£¨ÕâÊǰ²È«µÄ£¬ÒòΪʼþ·¾¶µÄ¿½±´ÊÇÔÚʼþ±¨¸æÀý³ÌÖнøÐеģ¬ ¶øÇҼȲ»»á±»deallocateÒ²²»×÷½øÒ»²½´«µÝ£©¡£ÔÚÈκÎʱ¿Ì£¬°üÀ¨ÖжÏÀý³ÌÖУ¬ ¶¯Ì¬·ÖÅä·¾¶Ò²Êǰ²È«µÄ£¬¾¡¹ÜÄÇÑù»áµ¼ÖÂijЩ¶îÍ⿪Ïú£¬²¢ÇÒÕâÖÖ·½·¨ ¿ÉÄÜ´æÔÚµÄÒ»¸öÎÊÌâÊÇÅöÇÉÄÇʱ¿ÉÄÜûÓпÕÏÐÄÚ´æ¡£¶ÔÓÚ×ÜÏ߸´Î»Ê¼þ£¬ ÎÒÃÇÐèÒª¶¨Òå°üÀ¨×ÜÏßÉÏËùÓÐÉ豸ÔÚÄÚµÄͨÅä·û·¾¶¡£ÕâÑùÎÒÃǾÍÄÜÌáǰΪ ÒÔºóµÄ×ÜÏ߸´Î»Ê¼þ´´½¨Â·¾¶£¬±ÜÃâÒÔºóÄÚ´æ²»×ãµÄÎÊÌ⣺

    struct cam_path *path;

    if(xpt_create_path(&path, /*periph*/NULL,
                cam_sim_path(sim), CAM_TARGET_WILDCARD,
                CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
        xpt_bus_deregister(cam_sim_path(sim));
        cam_sim_free(sim, /*free_devq*/TRUE);
        error; /* һЩ´íÎó´¦Àí´úÂë */
    }

    softc->wpath = path;
    softc->sim = sim;

¡¡¡¡ÕýÈçÄãËù¿´µ½µÄ£¬Â·¾¶°üÀ¨£º

  • ÍâΧÉ豸Çý¶¯³ÌÐòµÄID£¨ÓÉÓÚÎÒÃÇÒ»¸öҲûÓУ¬¹Ê´Ë´¦Îª¿Õ£©

  • SIMÇý¶¯³ÌÐòµÄID £¨cam_sim_path(sim)£©

  • É豸µÄSCSIÄ¿±êºÅ£¨CAM_TARGET_WILDCARDµÄÒâ˼ָ ¡°ËùÓÐdevices¡±£©

  • ×ÓÉ豸µÄSCSI LUNºÅ£¨CAM_LUN_WILDCARDµÄÒâ˼ָ ¡°ËùÓÐLUNs¡±£©

¡¡¡¡Èç¹ûÇý¶¯³ÌÐò²»ÄÜ·ÖÅäÕâ¸ö·¾¶£¬Ëü½«²»ÄÜÕý³£¹¤×÷£¬Òò´ËÄÇÑùÇé¿öÏ ÎÒÃÇж³ý£¨dismantle£©ÄǸöSCSI×ÜÏß¡£

¡¡¡¡ÎÒÃÇÔÚsoftc½á¹¹Öб£´æÂ·¾¶Ö¸ÕëÒÔ±ãÒÔºó ʹÓá£ÕâÖ®ºóÎÒÃDZ£´æsimµÄÖµ£¨»òÕßÈç¹ûÎÒÃÇÔ¸Ò⣬Ҳ¿ÉÒÔÔÚ´Ó xxx_probe()Í˳öʱ¶ªÆúËü£©¡£

¡¡¡¡Õâ¾ÍÊÇ×îµÍÒªÇóµÄ³õʼ»¯ËùÐèÒª×öµÄÒ»ÇС£ÎªÁ˰ÑÊÂÇé×öÕýÈ·ÎÞÎó£¬ »¹Ê£ÏÂÒ»¸öÎÊÌâ¡£

¡¡¡¡¶ÔÓÚSIMÇý¶¯³ÌÐò£¬ÓÐÒ»¸öÌØÊâ¸ÐÐËȤµÄʼþ£ººÎʱĿ±êÉ豸±»ÈÏΪ ÕÒ²»µ½ÁË¡£ÕâÖÖÇé¿öϸ´Î»ÓëÕâ¸öÉ豸µÄSCSIЭÉÌ¿ÉÄÜÊǸöºÃÖ÷Òâ¡£Òò´ËÎÒÃÇ ÎªÕâ¸öʼþÏòCAM×¢²áÒ»¸ö»Øµ÷¡£Í¨¹ýΪÕâÖÖÀàÐ͵ÄÇëÇóÀ´ÇëÇóCAM¿ØÖÆ¿éÉÏ µÄCAM¶¯×÷£¬ÇëÇó¾Í±»´«µÝµ½CAM£º£¨Òë×¢£º²Î¿´ÏÂÃæÊ¾Àý´úÂëºÍÔ­ÎÄ£©

    struct ccb_setasync csa;

    xpt_setup_ccb(&csa.ccb_h, path, /*ÓÅÏȼ¶*/5);
    csa.ccb_h.func_code = XPT_SASYNC_CB;
    csa.event_enable = AC_LOST_DEVICE;
    csa.callback = xxx_async;
    csa.callback_arg = sim;
    xpt_action((union ccb *)&csa);

¡¡¡¡ÏÖÔÚÎÒÃÇ¿´Ò»ÏÂxxx_action() ºÍxxx_poll()µÄÇý¶¯³ÌÐòÈë¿Úµã¡£

¡¡¡¡

static void xxx_action ( struct cam_sim *sim, union ccb *ccb );

¡¡¡¡ÏìÓ¦CAM×ÓϵͳµÄÇëÇó²ÉȡijЩ¶¯×÷¡£SimÃèÊöÁËÇëÇóµÄSIM£¬CCBΪ ÇëÇó±¾Éí¡£CCB´ú±í¡°CAM Control Block¡±¡£ËüÊǺܶàÌØ¶¨ ʵÀýµÄÁªºÏ£¬Ã¿¸öʵÀýΪijЩÀàÐ͵ÄÊÂÎñÃèÊö²ÎÁ¿¡£ËùÓÐÕâЩʵÀý¹²Ïí ´æ´¢×ŲÎÁ¿¹«¹²²¿·ÖµÄCCBÍ·²¿¡££¨Òë×¢£ºÕâÒ»¶Î²»ºÜ׼ȷ£¬Çë×ÔÐвο¼Ô­ÎÄ£©

¡¡¡¡CAM¼ÈÖ§³ÖSCSI¿ØÖÆÆ÷¹¤×÷ÓÚ·¢ÆðÕß(initiator)(¡°normal¡±) ģʽ£¬Ò²Ö§³ÖSCSI¿ØÖÆÆ÷¹¤×÷ÓÚÄ¿±ê(target)£¨Ä£ÄâSCSIÉ豸£©Ä£Ê½¡£Õâ¶ù ÎÒÃÇÖ»¿¼ÂÇÓë·¢ÆðÕßģʽÓйصIJ¿·Ö¡£

¡¡¡¡¶¨ÒåÁ˼¸¸öº¯ÊýºÍºê£¨»»¾ä»°Ëµ£¬·½·¨£©À´·ÃÎʽṹsimÖй«¹²Êý¾Ý£º

  • cam_sim_path(sim) - ·¾¶ID £¨²Î¼ûÉÏÃæ£©

  • cam_sim_name(sim) - simµÄÃû×Ö

  • cam_sim_softc(sim) - Ö¸Ïòsoftc£¨Çý¶¯³ÌÐò˽ÓÐÊý¾Ý£©½á¹¹µÄÖ¸Õë

  • cam_sim_unit(sim) - µ¥ÔªºÅ

  • cam_sim_bus(sim) - ×ÜÏßID

¡¡¡¡ÎªÁËʶ±ðÉ豸£¬xxx_action()¿ÉÒÔʹÓÃÕâЩ º¯ÊýµÃµ½µ¥ÔªºÅºÍÖ¸ÏòËüµÄsoftc½á¹¹µÄÖ¸Õë¡£

¡¡¡¡ÇëÇóµÄÀàÐͱ»´æ´¢ÔÚ ccb->ccb_h.func_code¡£Òò´Ë£¬Í¨³£ xxx_action()ÓÉÒ»¸ö´óµÄswitch×é³É£º

    struct xxx_softc *softc = (struct xxx_softc *) cam_sim_softc(sim);
    struct ccb_hdr *ccb_h = &ccb->ccb_h;
    int unit = cam_sim_unit(sim);
    int bus = cam_sim_bus(sim);

    switch(ccb_h->func_code) {
    case ...:
        ...
    default:
        ccb_h->status = CAM_REQ_INVALID;
        xpt_done(ccb);
        break;
    }

¡¡¡¡´Ódefault caseÓï¾ä²¿·Ö¿ÉÒÔ¿´³ö£¨Èç¹ûÊÕµ½Î´ÖªÃüÁ£¬ÃüÁîµÄ·µ»ØÂë ±»ÉèÖõ½ ccb->ccb_h.status ÖУ¬²¢ÇÒͨ¹ý µ÷ÓÃxpt_done(ccb)½«Õû¸öCCB·µ»Øµ½CAMÖС£

¡¡¡¡xpt_done()²»±Ø´Ó xxx_action()Öе÷ÓãºÀýÈçI/OÇëÇó¿ÉÒÔÔÚSIMÇý¶¯³ÌÐò ºÍ/»òËüµÄSCSI¿ØÖÆÆ÷ÖÐÅŶӡ££¨Òë×¢£ºËüÖ¸I/OÇëÇ󣿣© È»ºó£¬µ±É豸´«µÝ(post)Ò»¸öÖжÏÐźţ¬Ö¸Ê¾¶Ô´ËÇëÇóµÄ´¦ÀíÒѽáÊøÊ±£¬ xpt_done()¿ÉÒÔ´ÓÖжϴ¦ÀíÀý³ÌÖб»µ÷Óá£

¡¡¡¡Êµ¼ÊÉÏ£¬CCB״̬²»Êǽö½ö±»¸³ÖµÎªÒ»¸ö·µ»ØÂ룬¶øÊÇʼÖÕÓÐijÖÖ״̬¡£ CCB±»´«µÝ¸øxxx_action()Àý³Ìǰ£¬ÆäÈ¡µÃ״̬ CCB_REQ_INPROG£¬±íʾÆäÕýÔÚ½øÐÐÖС£/sys/cam/cam.h Öж¨ÒåÁËÊýÁ¿¾ªÈ˵Ä״ֵ̬£¬ËüÃÇÓ¦¸ÃÄܷdz£Ï꾡µØ±íʾÇëÇóµÄ״̬¡£ ¸üÓÐȤµÄÊÇ£¬×´Ì¬Êµ¼ÊÉÏÊÇÒ»¸öö¾Ù״ֵ̬£¨µÍ6룩ºÍһЩ¿ÉÄܳöÏֵĸ½¼Ó Àà(ËÆ)Æì±ê루¸ß룩µÄ¡°Î»»ò(bitwise or)¡±¡£Ã¶¾ÙÖµ»áÔÚÒÔºó ¸üÏêϸµØÌÖÂÛ¡£¶ÔËüÃǵĻã×Ü¿ÉÒÔÔÚ´íÎó¸ÅÀÀ½Ú(Errors Summary section) ÕÒµ½¡£¿ÉÄܵÄ״̬Æì±êΪ£º

  • CAM_DEV_QFRZN - µ±´¦ÀíCCBʱ£¬ Èç¹ûSIMÇý¶¯³ÌÐòµÃµ½Ò»¸öÑÏÖØ´íÎó£¨ÀýÈ磬Çý¶¯³ÌÐò²»ÄÜÏìӦѡÔñ»òÎ¥·´ ÁËSCSIЭÒ飩£¬ËüÓ¦µ±µ÷ÓÃxpt_freeze_simq()¶³½á ÇëÇó¶ÓÁУ¬°Ñ´ËÉ豸µÄÆäËûÒÑÈë¶Óµ«ÉÐδ±»´¦ÀíµÄCCB·µ»Øµ½CAM¶ÓÁУ¬ È»ºóΪÓÐÎÊÌâµÄCCBÉèÖÃÕâ¸öÆì±ê²¢µ÷Óà xpt_done()¡£Õâ¸öÆì±ê»áʹµÃCAM×Óϵͳ´¦Àí´íÎóºó ½â¶³¶ÓÁС£

  • CAM_AUTOSNS_VALID - Èç¹ûÉ豸 ·µ»Ø´íÎóÌõ¼þ£¬ÇÒCCBÖÐδÉèÖÃÆì±êCAM_DIS_AUTOSENSE£¬SIMÇý¶¯³ÌÐò ±ØÐë×Ô¶¯Ö´ÐÐREQUEST SENSEÃüÁîÀ´´ÓÉ豸³éÈ¡sense£¨À©Õ¹´íÎóÐÅÏ¢£© Êý¾Ý¡£Èç¹ûÕâ¸ö³¢ÊԳɹ¦£¬senseÊý¾ÝÓ¦µ±±»±£´æÔÚCCBÖÐÇÒÉèÖÃ´ËÆì±ê¡£

  • CAM_RELEASE_SIMQ - ÀàËÆÓÚ CAM_DEV_QFRZN£¬µ«ÓÃÓÚSCSI¿ØÖÆÆ÷×ÔÉí³öÎÊÌâ(»ò×ÊÔ´¶Ìȱ)µÄÇé¿ö¡£ ´Ëºó¶Ô¿ØÖÆÆ÷µÄËùÓÐÇëÇó»á±»xpt_freeze_simq() Í£Ö¹¡£SIMÇý¶¯³ÌÐò¿Ë·þÕâÖÖ¶ÌȱÇé¿ö£¬²¢Í¨¹ý·µ»ØÉèÖÃÁË´ËÆì±êµÄCCB ֪ͨCAMºó£¬¿ØÖÆÆ÷¶ÓÁн«»á±»ÖØÐÂÆô¶¯¡£

  • CAM_SIM_QUEUED - µ±SIM½«Ò»¸ö CCB·ÅÈëÆäÇëÇó¶ÓÁÐʱӦµ±ÉèÖÃ´ËÆì±ê£¨»òµ±CCB³ö¶Óµ«ÉÐδ·µ»Ø¸øCAMʱ È¥µô£©¡£ÏÖÔÚ´ËÆì±ê»¹Ã»ÓÐÔÚCAM´úÂëµÄÈκεط½Ê¹Óùý£¬Òò´ËÆäÄ¿µÄ ´¿´âÓÃÓÚÕï¶Ï£©¡£

¡¡¡¡º¯Êýxxx_action()²»ÔÊÐí˯Ãߣ¬Òò´Ë¶Ô×ÊÔ´ ·ÃÎʵÄËùÓÐͬ²½±ØÐëͨ¹ý¶³½áSIM»òÉ豸¶ÓÁÐÀ´Íê³É¡£³ýÁËǰÊöµÄÆì±êÍ⣬ CAM×ÓϵͳÌṩÁ˺¯Êýxpt_release_simq()ºÍ xpt_release_devq()À´Ö±½Ó½â¶³¶ÓÁУ¬¶ø²»±Ø½« CCB´«µÝµ½CAM¡£

¡¡¡¡CCBÍ·²¿°üº¬ÈçÏÂ×ֶΣº

  • path - ÇëÇóµÄ·¾¶ID

  • target_id - ÇëÇóµÄÄ¿±êÉ豸ID

  • target_lun - Ä¿±êÉ豸µÄLUN ID

  • timeout - Õâ¸öÃüÁîµÄ³¬Ê±¼ä¸ô£¬ÒÔºÁÃë¼Æ

  • timeout_ch - Ò»¸öΪSIMÇý¶¯ ³ÌÐò´æ´¢³¬Ê±´¦Àíº¯ÊýµÄ·½±ãÖ®Ëù£¨CAM×Óϵͳ×ÔÉí²¢²»¶Ô´Ë×÷ÈκμÙÉ裩

  • flags - ÓйØÇëÇóµÄ¸÷¸ö ÐÅϢλ

  • spriv_ptr0£¬spriv_ptr1 - SIMÇý¶¯³ÌÐò±£Áô˽ÓõÄ×Ö¶Î £¨ÀýÈçÁ´½Óµ½SIM¶ÓÁлòSIM˽ÓпØÖƿ飩£»Êµ¼ÊÉÏ£¬ËüÃÇ×÷ΪÁªºÏ´æÔÚ£º spriv_ptr0ºÍspriv_ptr1¾ßÓÐÀàÐÍ(void *)£¬spriv_field0ºÍ spriv_field1¾ßÓÐÀàÐÍunsigned long£¬sim_priv.entries[0].bytesºÍ sim_priv.entries[1].bytesΪÓëÁªºÏµÄÆäËûÐÎʽ´óСһÖµÄ×Ö½ÚÊý×飬 sim_priv.bytesΪһ¸öÁ½±¶´óСµÄÊý×é

¡¡¡¡Ê¹ÓÃCCBµÄSIM˽ÓÐ×ֶεĽ¨Òé·½·¨ÊÇΪËüÃǶ¨ÒåһЩÓÐÒâÒåµÄÃû×Ö£¬ ²¢ÇÒÔÚÇý¶¯³ÌÐòÖÐʹÓÃÕâЩÓÐÒâÒåµÄÃû×Ö£¬¾ÍÏñÏÂÃæÕâÑù£º

#define ccb_some_meaningful_name    sim_priv.entries[0].bytes
#define ccb_hcb spriv_ptr1 /* ÓÃÓÚÓ²¼þ¿ØÖÆ¿é */

¡¡¡¡×î³£¼ûµÄ·¢ÆðÕßģʽµÄÇëÇóÊÇ£º

  • XPT_SCSI_IO - Ö´ÐÐI/OÊÂÎñ

    ÁªºÏccbµÄ¡°struct ccb_scsiio csio¡±ÊµÀýÓÃÓÚ´«µÝ²ÎÁ¿¡£ ËüÃÇÊÇ£º

    • cdb_io - Ö¸ÏòSCSIÃüÁ³åÇøµÄÖ¸Õë»ò»º³åÇø±¾Éí

    • cdb_len - SCSIÃüÁ¶È

    • data_ptr - Ö¸ÏòÊý¾Ý»º³åÇøµÄÖ¸Õ루Èç¹ûʹÓ÷ÖÉ¢/¼¯ÖлḴÔÓÒ»µã£©

    • dxfer_len - ´ý´«ÊäÊý¾ÝµÄ³¤¶È

    • sglist_cnt - ·ÖÉ¢/¼¯ÖжεļÆÊý

    • scsi_status - ·µ»ØSCSI״̬µÄµØ·½

    • sense_data - ÃüÁî·µ»Ø´íÎóʱ±£´æSCSI senseÐÅÏ¢µÄ»º³åÇø£¨ÕâÖÖÇé¿öÏ£¬Èç¹ûûÓÐ ÉèÖÃCCBµÄÆì±êCAM_DIS_AUTOSENSE£¬Ôò¼Ù¶¨SIMÇý¶¯³ÌÐò»á×Ô¶¯ÔËÐÐ REQUEST SENSEÃüÁ

    • sense_len - »º³åÇøµÄ³¤¶È£¨Èç¹ûÅöÇÉ´óÓÚsense_dataµÄ´óС£¬SIMÇý¶¯³ÌÐò±ØÐë ÇÄÇĵزÉÓýÏСֵ£©£¨Òë×¢£ºÒ»µã¸Ä¶¯£¬²Î¿¼Ô­Îļ°´úÂ룩

    • resid, sense_resid - Èç¹ûÊý¾Ý´«Êä»òSCSI sense·µ»Ø´íÎó£¬ÔòËüÃÇ ¾ÍÊÇ·µ»ØµÄÊ£Óࣨδ´«Ê䣩Êý¾ÝµÄ¼ÆÊý¡£ËüÃÇ¿´ÆðÀ´²¢²»ÊÇÌØ±ðÓÐÒâÒ壬 Òò´Ëµ±ºÜÄѼÆËãµÄÇé¿öÏ£¨ÀýÈ磬¼ÆÊýSCSI¿ØÖÆÆ÷FIFO»º³åÇøÖеÄ×Ö½Ú Êý£©£¬Ê¹ÓýüËÆÖµÒ²Í¬Ñù¿ÉÒÔ¡£¶ÔÓڳɹ¦Íê³ÉµÄ´«Ê䣬ËüÃDZØÐë±»ÉèÖà Ϊ0¡£

    • tag_action - ʹÓõıêÇ©µÄÖÖÀàÓУº

      • CAM_TAG_ACTION_NONE - ÊÂÎñ²»Ê¹ÓñêÇ©

      • MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG, MSG_ORDERED_Q_TAG - ÖµµÈÓÚÊʵ±µÄ±êÇ©ÐÅÏ¢ £¨¼û/sys/cam/scsi/scsi_message.h£©£»½ö¸ø³ö±êÇ©ÀàÐÍ£¬SIMÇý¶¯³ÌÐò ±ØÐë×Ô¼º¸³±êǩֵ

    ´¦ÀíÇëÇóµÄͨ³£Âß¼­ÈçÏ£º

    Òª×öµÄµÚÒ»¼þÊÂÇéÊǼì²é¿ÉÄܵľºÕùÌõ¼þ£¬È·±£ÃüÁîλÓÚ¶ÓÁÐÖÐʱ ²»»á±»ÖÐÖ¹£º

        struct ccb_scsiio *csio = &ccb->csio;
    
        if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
            xpt_done(ccb);
            return;
        }
    

    ÎÒÃÇÒ²¼ì²éÎÒÃǵĿØÖÆÆ÷Íêȫ֧³ÖÉ豸£º

        if(ccb_h->target_id > OUR_MAX_SUPPORTED_TARGET_ID
        || cch_h->target_id == OUR_SCSI_CONTROLLERS_OWN_ID) {
            ccb_h->status = CAM_TID_INVALID;
            xpt_done(ccb);
            return;
        }
        if(ccb_h->target_lun > OUR_MAX_SUPPORTED_LUN) {
            ccb_h->status = CAM_LUN_INVALID;
            xpt_done(ccb);
            return;
        }
    

    È»ºó·ÖÅäÎÒÃÇ´¦ÀíÇëÇóËùÐèµÄÊý¾Ý½á¹¹£¨È翨Ïà¹ØµÄÓ²¼þ¿ØÖÆ¿éµÈ£©¡£ Èç¹ûÎÒÃDz»ÄÜ·ÖÅäÔò¶³½áSIM¶ÓÁУ¬¼Ç¼ÏÂÎÒÃÇÓÐÒ»¸ö¹ÒÆðµÄ²Ù×÷£¬·µ»Ø CCB£¬ÇëÇóCAM½«CCBÖØÐÂÈë¶Ó¡£ÒÔºóµ±×ÊÔ´¿ÉÓÃʱ£¬±ØÐëͨ¹ý·µ»ØÆä ״̬ÖÐÉèÖà CAM_SIMQ_RELEASE λµÄccbÀ´½â¶³SIM¶ÓÁС£·ñÔò£¬Èç¹ûËùÓÐ Õý³££¬Ôò½«CCBÓëÓ²¼þ¿ØÖƿ飨HCB£©Á´½Ó£¬²¢½«Æä±ê־ΪÒÑÈë¶Ó¡£

        struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);
    
        if(hcb == NULL) {
            softc->flags |= RESOURCE_SHORTAGE;
            xpt_freeze_simq(sim, /*count*/1);
            ccb_h->status = CAM_REQUEUE_REQ;
            xpt_done(ccb);
            return;
        }
    
        hcb->ccb = ccb; ccb_h->ccb_hcb = (void *)hcb;
        ccb_h->status |= CAM_SIM_QUEUED;
    

    ´ÓCCBÖÐÌáȡĿ±êÊý¾Ýµ½Ó²¼þ¿ØÖƿ顣¼ì²éÊÇ·ñÒªÇóÎÒÃÇ·ÖÅäÒ»¸ö ±êÇ©£¬Èç¹ûÊÇÔò²úÉúÒ»¸öΨһµÄ±êÇ©²¢¹¹ÔìSCSI±êÇ©ÐÅÏ¢¡£SIMÇý¶¯³ÌÐò Ò²¸ºÔðÓëÉ豸ЭÉÌÉ趨±Ë´ËÖ§³ÖµÄ×î´ó×ÜÏß¿í¶È¡¢Í¬²½ËÙÂÊºÍÆ«ÒÆ¡£

        hcb->target = ccb_h->target_id; hcb->lun = ccb_h->target_lun;
        generate_identify_message(hcb);
        if( ccb_h->tag_action != CAM_TAG_ACTION_NONE )
            generate_unique_tag_message(hcb, ccb_h->tag_action);
        if( !target_negotiated(hcb) )
            generate_negotiation_messages(hcb);
    

    È»ºóÉèÖÃSCSIÃüÁî¡£¿ÉÒÔÔÚCCBÖÐÒÔ¶àÖÖÓÐȤµÄ·½Ê½Ö¸¶¨ÃüÁîµÄ´æ´¢£¬ ÕâЩ·½Ê½ÓÉCCBÖÐµÄÆì±êÖ¸¶¨¡£ÃüÁ³åÇø¿ÉÒÔ°üº¬ÔÚCCBÖлòÕßÓÃÖ¸Õë Ö¸Ïò£¬ºóÕßÇé¿öÏÂÖ¸Õë¿ÉÒÔÖ¸ÏòÎïÀíµØÖ·»òÐ鵨ַ¡£ÓÉÓÚÓ²¼þͨ³£ÐèÒª ÎïÀíµØÖ·£¬Òò´ËÎÒÃÇ×ÜÊǽ«µØÖ·×ª»»ÎªÎïÀíµØÖ·¡£

    ²»Ì«Ïà¹ØµÄÌáʾ£ºÍ¨³£ÕâÊÇͨ¹ýµ÷ÓÃvtophys()À´Íê³ÉµÄ£¬µ«ÓÉÓÚ ÌØÊâµÄAlpha¹ÖÒìÖ®´¦£¬ÎªÁËPCIÉ豸£¨ËüÃÇÏÖÔÚÕ¼SCSI¿ØÖÆÆ÷µÄ´ó¶àÊý£© Çý¶¯³ÌÐòÏòAlpha¼Ü¹¹µÄ¿ÉÒÆÖ²ÐÔ£¬×ª»»±ØÐëÌæ´úÒÔ vtobus() À´Íê³É¡£ [IMHO ÌṩÁ½¸öµ¥¶ÀµÄº¯Êý vtop() ºÍ ptobus()£¬¶ø vtobus() Ö»ÊÇËüÃÇµÄ ¼òµ¥µþ´ú£¬ÕâÑù×öÒªºÃµÃ¶à¡£] ÔÚÇëÇóÎïÀíµØÖ·µÄÇé¿öÏ£¬·µ»Ø´øÓÐ״̬ ¡°CAM_REQ_INVALID¡± µÄCCBÊÇ¿ÉÒԵ쬵±Ç°µÄÇý¶¯³ÌÐò¾ÍÊÇÄÇÑù×öµÄ¡£µ«Ò² ¿ÉÄÜÏñÕâ¸öÀý×Ó£¨Çý¶¯³ÌÐòÖÐÓ¦µ±Óв»´øÌõ¼þ±àÒëµÄ¸üÖ±½Ó×ö·¨£©ÖÐÄÇÑù ±àÒëAlphaÌØ¶¨µÄ´úÂëÆ¬¶Ï¡£Èç¹ûÐèÒªÎïÀíµØÖ·Ò²ÄÜת»»»òÓ³É仨Ð鵨ַ£¬ µ«ÄÇÑù´ú¼ÛºÜ´ó£¬Òò´ËÎÒÃDz»ÄÇÑù×ö¡£

        if(ccb_h->flags & CAM_CDB_POINTER) {
            /* CDB is a pointer */
            if(!(ccb_h->flags & CAM_CDB_PHYS)) {
                /* CDBÖ¸ÕëÊÇÐéÄâµÄ */
                hcb->cmd = vtobus(csio->cdb_io.cdb_ptr);
            } else {
                /* CDBÖ¸ÕëÊÇÎïÀíµÄ */
    #if defined(__alpha__)
                hcb->cmd = csio->cdb_io.cdb_ptr | alpha_XXX_dmamap_or ;
    #else
                hcb->cmd = csio->cdb_io.cdb_ptr ;
    #endif
            }
        } else {
            /* CDBÔÚccb(»º³åÇø)ÖÐ */
            hcb->cmd = vtobus(csio->cdb_io.cdb_bytes);
        }
        hcb->cmdlen = csio->cdb_len;
    

    ÏÖÔÚÊÇÉèÖÃÊý¾ÝµÄʱºòÁË£¬ÓÖÒ»´Î£¬¿ÉÒÔÔÚCCBÖÐÒÔ¶àÖÖÓÐȤµÄ·½Ê½ Ö¸¶¨Êý¾Ý´æ´¢£¬ÕâЩ·½Ê½ÓÉCCBÖÐµÄÆì±êÖ¸¶¨¡£Ê×ÏÈÎÒÃǵõ½Êý¾Ý´«ÊäµÄ ·½Ïò¡£×î¼òµ¥µÄÇé¿öÊÇûÓÐÊý¾ÝÐèÒª´«ÊäµÄÇé¿ö£º

        int dir = (ccb_h->flags & CAM_DIR_MASK);
    
        if (dir == CAM_DIR_NONE)
            goto end_data;
    

    È»ºóÎÒÃǼì²éÊý¾ÝÔÚÒ»¸öchunkÖл¹ÊÇÔÚ·ÖÉ¢/¼¯ÖÐÁбíÖУ¬²¢ÇÒÊÇ ÎïÀíµØÖ·»¹ÊÇÐ鵨ַ¡£SCSI¿ØÖÆÆ÷¿ÉÄÜÖ»ÄÜ´¦ÀíÓÐÏÞÊýÄ¿ÓÐÏÞ³¤¶ÈµÄ ´ó¿é¡£Èç¹ûÇëÇóµ½´ïµ½Õâ¸öÏÞÖÆÎÒÃǾͷµ»Ø´íÎó¡£ÎÒÃÇʹÓÃÒ»¸öÌØÊâ º¯Êý·µ»ØCCB£¬²¢ÔÚÒ»¸öµØ·½´¦ÀíHCB×ÊÔ´¶Ìȱ¡£Ôö¼ÓchunkµÄº¯ÊýÊÇ Çý¶¯³ÌÐòÏà¹ØµÄ£¬´Ë´¦ÎÒÃDz»½øÈëËüÃǵÄÏêϸʵÏÖ¡£¶ÔÓÚµØÖ··­ÒëÎÊÌâ µÄϸ½Ú¿ÉÒԲο´SCSIÃüÁî(CDB)´¦ÀíµÄÃèÊö¡£Èç¹ûijЩ±äÌå¶ÔÓÚÌØ¶¨µÄ¿¨ Ì«À§ÄÑ»ò²»¿ÉÄÜʵÏÖ£¬·µ»Ø×´Ì¬ ¡°CAM_REQ_INVALID¡± ÊÇ¿ÉÒԵġ£Êµ¼ÊÉÏ£¬ ÏÖÔÚµÄCAM´úÂëÖÐËÆºõÄĶùҲûÓÐʹÓ÷ÖÉ¢/¼¯ÖÐÄÜÁ¦¡£µ«ÖÁÉÙ±ØÐëʵÏÖ µ¥¸ö·Ç·ÖÉ¢ÐéÄ⻺³åÇøµÄÇé¿ö£¬CAMÖÐÕâÖÖÇé¿öÓõúܶࡣ

        int rv;
        
        initialize_hcb_for_data(hcb);
    
        if((!(ccb_h->flags & CAM_SCATTER_VALID)) { 
            /* µ¥¸ö»º³åÇø */
            if(!(ccb_h->flags & CAM_DATA_PHYS)) {
                rv = add_virtual_chunk(hcb, csio->data_ptr, csio->dxfer_len, dir);
                }
            } else {
                rv = add_physical_chunk(hcb, csio->data_ptr, csio->dxfer_len, dir);
            }
        } else {
            int i;
            struct bus_dma_segment *segs;
            segs = (struct bus_dma_segment *)csio->data_ptr;
    
            if ((ccb_h->flags & CAM_SG_LIST_PHYS) != 0) {
                /* SGÁбíÖ¸ÕëÊÇÎïÀíµÄ */
                rv = setup_hcb_for_physical_sg_list(hcb, segs, csio->sglist_cnt);
            } else if (!(ccb_h->flags & CAM_DATA_PHYS)) {
                /* SG»º³åÇøÖ¸ÕëÊÇÐéÄâµÄ */
                for (i = 0; i < csio->sglist_cnt; i++) {
                    rv = add_virtual_chunk(hcb, segs[i].ds_addr, 
                        segs[i].ds_len, dir);
                    if (rv != CAM_REQ_CMP)
                        break;
                }
            } else {
                /* SG»º³åÇøÖ¸ÕëÊÇÎïÀíµÄ */
                for (i = 0; i < csio->sglist_cnt; i++) {
                    rv = add_physical_chunk(hcb, segs[i].ds_addr, 
                        segs[i].ds_len, dir);
                    if (rv != CAM_REQ_CMP)
                        break;
                }
            }
        }
        if(rv != CAM_REQ_CMP) {
            /* Èç¹û³É¹¦Ìí¼ÓÁËÒ»chunk£¬ÎÒÃÇÏ£Íûadd_*_chunk()º¯Êý·µ»Ø
             * CAM_REQ_CMP£¬Èç¹ûÇëÇóÌ«´ó£¨Ì«¶à×Ö½Ú»òÌ«¶àchunks£©
             * Ôò·µ»ØCAM_REQ_TOO_BIG, ÆäËûÇé¿öÏ·µ»Ø¡°CAM_REQ_INVALID¡±¡£
             */
            free_hcb_and_ccb_done(hcb, ccb, rv);
            return;
        }
        end_data:
    

    Èç¹ûÕâ¸öCCB²»ÔÊÐí¶Ï¿ªÁ¬½Ó£¬ÎÒÃǾʹ«µÝÕâ¸öÐÅÏ¢µ½hcb£º

        if(ccb_h->flags & CAM_DIS_DISCONNECT)
            hcb_disable_disconnect(hcb);
    

    Èç¹û¿ØÖÆÆ÷Äܹ»ÍêÈ«×Ô¼ºÔËÐÐREQUEST SENSEÃüÁÔòÒ²Ó¦µ±½«Æì±ê CAM_DIS_AUTOSENSEµÄÖµ´«µÝ¸øËü£¬ÕâÑù¿ÉÒÔÔÚCAM×Óϵͳ²»ÏëREQUEST SENSE ʱ×èÖ¹×Ô¶¯REQUEST SENSE¡£

    ʣϵÄΨһÊÂÇéÊÇÉèÖó¬Ê±£¬½«ÎÒÃǵÄhcb´«µÝ¸øÓ²¼þ²¢·µ»Ø£¬ÓàÏ嵀 ÓÉÖжϴ¦Àíº¯Êý£¨»ò³¬Ê±´¦Àíº¯Êý£©Íê³É¡£

        ccb_h->timeout_ch = timeout(xxx_timeout, (caddr_t) hcb, 
            (ccb_h->timeout * hz) / 1000); /* ½«ºÁÃëת»»ÎªµÎ´ðÊý */
        put_hcb_into_hardware_queue(hcb);
        return;
    

    Õâ¶ùÊÇ·µ»ØCCBµÄº¯ÊýµÄÒ»¸ö¿ÉÄÜʵÏÖ£º

        static void
        free_hcb_and_ccb_done(struct xxx_hcb *hcb, union ccb *ccb, u_int32_t status)
        {
            struct xxx_softc *softc = hcb->softc;
    
            ccb->ccb_h.ccb_hcb = 0;
            if(hcb != NULL) {
                untimeout(xxx_timeout, (caddr_t) hcb, ccb->ccb_h.timeout_ch);
                /* ÎÒÃÇÒªÊÍ·Åhcb£¬Òò´Ë×ÊÔ´¶ÌȱÎÊÌâÒ²¾Í²»´æÔÚÁË */
                if(softc->flags & RESOURCE_SHORTAGE)  {
                    softc->flags &= ~RESOURCE_SHORTAGE;
                    status |= CAM_RELEASE_SIMQ;
                }
                free_hcb(hcb); /* ͬʱ´ÓÈκÎÄÚ²¿ÁбíÖÐÒÆ³ýhcb */
            }
            ccb->ccb_h.status = status | 
                (ccb->ccb_h.status & ~(CAM_STATUS_MASK|CAM_SIM_QUEUED));
            xpt_done(ccb);
        }
    
  • XPT_RESET_DEV - ·¢ËÍSCSI ¡°BUS DEVICE RESET¡±ÏûÏ¢µ½É豸

    ³ýÁËÍ·²¿ÍâCCBÖÐûÓÐÊý¾Ý´«Ê䣬ÆäÖÐ×îÈÃÈ˸ÐÐËȤµÄ²ÎÁ¿Îªtarget_id¡£ ÒÀÀµÓÚ¿ØÖÆÆ÷Ó²¼þ£¬Ó²¼þ¿ØÖÆ¿é¾ÍÏñXPT_SCSI_IOÇëÇóÖÐÄÇÑù±»´´½¨ £¨²Î¿´XPT_SCSI_IOÇëÇóµÄÃèÊö£©²¢±»·¢Ë͵½¿ØÖÆÆ÷£¬»òÕßÁ¢¼´±à³ÌÈÃSCSI ¿ØÖÆÆ÷·¢ËÍRESETÏûÏ¢µ½É豸£¬»òÕßÕâ¸öÇëÇó¿ÉÄÜÖ»ÊDz»±»Ö§³Ö £¨²¢·µ»Ø×´Ì¬ ¡°CAM_REQ_INVALID¡±£©¡£¶øÇÒÇëÇóÍê³Éʱ£¬Ä¿±êµÄËùÓÐÒѶϿª Á¬½Ó(disconnected)µÄÊÂÎñ±ØÐë±»ÖÐÖ¹£¨¿ÉÄÜÔÚÖжÏÀý³ÌÖУ©¡£

    ¶øÇÒÄ¿±êµÄËùÓе±Ç°Ð­ÉÌÔÚ¸´Î»Ê±»á¶ªÊ§£¬Òò´ËËüÃÇÒ²¿ÉÄܱ»Çå³ý¡£ »òÕßÇå³ý¿ÉÄܱ»ÑÓ³Ù£¬ÒòΪ²»¹ÜÔõÑùÄ¿±ê½«»áÔÚÏÂÒ»´ÎÊÂÎñʱÇëÇóÖØÐÂЭÉÌ¡£

  • XPT_RESET_BUS - ·¢ËÍRESETÐźŵ½SCSI×ÜÏß

    CCBÖв¢²»´«µÝ²ÎÁ¿£¬Î¨Ò»¸ÐÐËȤµÄ²ÎÁ¿ÊÇÓÉÖ¸Ïò½á¹¹simµÄÖ¸Õë±êʶ µÄSCSI×ÜÏß¡£

    ×îСʵÏÖ»áÍü¼Ç×ÜÏßÉÏËùÓÐÉ豸µÄSCSIЭÉÌ£¬²¢·µ»Ø×´Ì¬ CAM_REQ_CMP¡£

    Ç¡µ±µÄʵÏÖʵ¼ÊÉÏ»áÁíÍ⸴λSCSI×ÜÏߣ¨¿ÉÄÜÒ²¸´Î»SCSI¿ØÖÆÆ÷£©²¢ ½«ËùÓÐÔÚÓ²¼þ¶ÓÁÐÖеĺͶϿªÁ¬½ÓµÄÄÇЩÕý±»´¦ÀíµÄCCBµÄÍê³É״̬±ê¼ÇΪ CAM_SCSI_BUS_RESET¡£ÏñÕâÑù£º

        int targ, lun;
        struct xxx_hcb *h, *hh;
        struct ccb_trans_settings neg;
        struct cam_path *path;
    
        /* SCSI×ÜÏ߸´Î»¿ÉÄܻỨ·ÑºÜ³¤Ê±¼ä£¬ÕâÖÖÇé¿öÏÂÓ¦µ±Ê¹ÓÃÖжϻò³¬Ê±À´¼ì²é
         * ¸´Î»ÊÇ·ñÍê³É¡£µ«ÎªÁ˼òµ¥£¬ÎÒÃÇÕâ¶ù¼ÙÉ踴λºÜ¿ì¡£
         */
        reset_scsi_bus(softc);
    
        /* ¶ªÆúËùÓÐÈë¶ÓµÄCCB */
        for(h = softc->first_queued_hcb; h != NULL; h = hh) {
            hh = h->next;
            free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);
        }
    
        /* ЭÉ̵ģ¨Çå³ý²Ù×÷ºóµÄ£©¸É¾»Öµ£¬ÎÒÃDZ¨¸æÕâ¸öÖµ */
        neg.bus_width = 8;
        neg.sync_period = neg.sync_offset = 0;
        neg.valid = (CCB_TRANS_BUS_WIDTH_VALID
            | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);
    
        /* ¶ªÆúËùÓжϿªÁ¬½ÓµÄCCBºÍ¸É¾»µÄЭÉÌ£¨Òë×¢£º¸É¾»£½clean£© */
        for(targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {
            clean_negotiations(softc, targ);
    
            /* Èç¹û¿ÉÄܱ¨¸æÊ¼þ */
            if(xpt_create_path(&path, /*periph*/NULL,
                    cam_sim_path(sim), targ,
                    CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
                xpt_async(AC_TRANSFER_NEG, path, &neg);
                xpt_free_path(path);
            }
    
            for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++) 
                for(h = softc->first_discon_hcb[targ][lun]; h != NULL; h = hh) {
                    hh=h->next;
                    free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);
                }
        }
    
        ccb->ccb_h.status = CAM_REQ_CMP;
        xpt_done(ccb);
    
        /* ±¨¸æÊ¼þ */
        xpt_async(AC_BUS_RESET, softc->wpath, NULL);
        return;
    

    ½«SCSI×ÜÏ߸´Î»×÷Ϊº¯ÊýÀ´ÊµÏÖ¿ÉÄÜÊǸöºÃÖ÷Ò⣬ÒòΪÈç¹ûÊÂÇé³öÁ˲î´í£¬ Ëü»á±»³¬Ê±º¯Êý×÷Ϊ×îºóµÄ±¨¸æÀ´ÖØÓá£

  • XPT_ABORT - ÖÐÖ¹Ö¸¶¨µÄCCB

    ²ÎÁ¿ÔÚÁªºÏccbµÄʵÀý¡°struct ccb_abort cab¡± Öд«Êä¡£ÆäÖÐΨһµÄ²ÎÁ¿×Ö¶ÎΪ£º

    abort_ccb - Ö¸Ïò±»ÖÐÖ¹µÄccbµÄÖ¸Õë

    Èç¹û²»Ö§³ÖÖжϾͷµ»ØCAM_UA_ABORT¡£ÕâÒ²ÊÇ×îС»¯ÊµÏÖÕâ¸öµ÷ÓÃµÄ ¼òÒ×·½Ê½£¬ÈκÎÇé¿ö϶¼·µ»ØCAM_UA_ABORT¡£

    À§ÄÑ·½Ê½ÔòÊÇÕæÕýµØÊµÏÖÕâ¸öÇëÇó¡£Ê×Ïȼì²éÓ¦Óõ½SCSIÊÂÎñµÄÖÐÖ¹£º

        struct ccb *abort_ccb;
        abort_ccb = ccb->cab.abort_ccb;
    
        if(abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {
            ccb->ccb_h.status = CAM_UA_ABORT;
            xpt_done(ccb);
            return;
        }
    

    È»ºóÐèÒªÔÚÎÒÃǵĶÓÁÐÖÐÕÒµ½Õâ¸öCCB¡£Õâ¿ÉÒÔͨ¹ý±éÀúÎÒÃÇËùÓÐÓ²¼þ ¿ØÖÆ¿éÁÐ±í£¬²éÕÒÓëÕâ¸öCCB¹ØÁªµÄ¿ØÖÆ¿éÀ´Íê³É£º

        struct xxx_hcb *hcb, *h;
    
        hcb = NULL;
    
        /* ÎÒÃǼÙÉèsoftc->first_hcbÊÇÓë´Ë×ÜÏß¹ØÁªµÄËùÓÐHCBµÄÁбíÍ·ÔªËØ£¬
         * °üÀ¨ÄÇЩÈë¶Ó´ý´¦ÀíµÄ¡¢Ó²¼þÕýÔÚ´¦ÀíµÄºÍ¶Ï¿ªÁ¬½ÓµÄÄÇЩ¡£
         */
        for(h = softc->first_hcb; h != NULL; h = h->next) {
            if(h->ccb == abort_ccb) {
                hcb = h;
                break;
            }
        }
    
        if(hcb == NULL) {
            /* ÎÒÃǵĶÓÁÐÖÐûÓÐÕâÑùµÄCCB */
            ccb->ccb_h.status = CAM_PATH_INVALID; 
            xpt_done(ccb);
            return;
        }
    
        hcb=found_hcb;
    

    ÏÖÔÚÎÒÃÇÀ´¿´Ò»ÏÂHCBµ±Ç°µÄ´¦Àí״̬¡£Ëü¿ÉÄÜ»ò´ôÔÚ¶ÓÁÐÖÐÕýµÈ´ý ±»·¢Ë͵½SCSI×ÜÏߣ¬»ò´ËʱÕýÔÚ´«ÊäÖУ¬»òÒѶϿªÁ¬½Ó²¢µÈ´ýÃüÁî½á¹û£¬ »òÕßʵ¼ÊÉÏÒÑÓÉÓ²¼þÍê³Éµ«ÉÐδ±»Èí¼þ±ê¼ÇΪÍê³É¡£ÎªÁËÈ·±£ÎÒÃDz»»á ÓëÓ²¼þ²úÉú¾ºÕùÌõ¼þ£¬ÎÒÃǽ«HCB±ê¼ÇΪÖÐÖ¹(aborted)£¬ÕâÑùÈç¹ûÕâ¸ö HCBÒª±»·¢Ë͵½SCSI×ÜÏߵϰ£¬SCSI¿ØÖÆÆ÷½«»á¿´µ½Õâ¸öÆì±ê²¢Ìø¹ýËü¡£

        int hstatus;
    
        /* ´Ë´¦ÏÔʾΪһ¸öº¯Êý£¬ÓÐʱÐèÒªÌØÊ⶯×÷²ÅÄÜʹµÃÕâ¸öÆì±ê¶ÔÓ²¼þ¿É¼û
         */
        set_hcb_flags(hcb, HCB_BEING_ABORTED);
    
        abort_again:
    
        hstatus = get_hcb_status(hcb);
        switch(hstatus) {
        case HCB_SITTING_IN_QUEUE:
            remove_hcb_from_hardware_queue(hcb);
            /* ¼ÌÐøÖ´ÐÐ */
        case HCB_COMPLETED:
            /* ÕâÊÇÒ»ÖÖ¼òµ¥µÄÇé¿ö */
            free_hcb_and_ccb_done(hcb, abort_ccb, CAM_REQ_ABORTED);
            break;
    

    Èç¹ûCCB´ËʱÕýÔÚ´«ÊäÖУ¬ÎÒÃÇÒ»°ã»áÒÔijÖÖÓ²¼þÏà¹ØµÄ·½Ê½·¢ÐźŠ¸øSCSI¿ØÖÆÆ÷£¬Í¨ÖªËüÎÒÃÇÏ£ÍûÖÐÖ¹µ±Ç°µÄ´«Êä¡£SCSI¿ØÖÆÆ÷»áÉèÖà SCSI ATTENTIONÐźţ¬²¢µ±Ä¿±ê¶ÔÆä½øÐÐÏìÓ¦ºó·¢ËÍABORTÏûÏ¢¡£ÎÒÃÇÒ²¸´Î» ³¬Ê±£¬ÒÔÈ·±£Ä¿±ê²»»áÓÀԶ˯Ãß¡£Èç¹ûÃüÁî²»ÄÜÔÚij¸öºÏÀíµÄʱ¼ä£¬Èç 10ÃëÄÚÖÐÖ¹£¬³¬Ê±Àý³Ì¾Í»áÔËÐв¢¸´Î»Õû¸öSCSI×ÜÏß¡£ÓÉÓÚÃüÁî»áÔÚij¸ö ºÏÀíµÄʱ¼äºó±»ÖÐÖ¹£¬Òò´ËÎÒÃÇÏÖÔÚ¿ÉÒÔÖ»½«ÖÐÖ¹ÇëÇ󷵻أ¬µ±×÷³É¹¦Íê³É£¬ ²¢½«±»ÖÐÖ¹µÄCCB±ê¼ÇΪÖÐÖ¹£¨µ«»¹Ã»Óн«Ëü±ê¼ÇΪÍê³É£©¡£

        case HCB_BEING_TRANSFERRED:
            untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h.timeout_ch);
            abort_ccb->ccb_h.timeout_ch = 
                timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);
            abort_ccb->ccb_h.status = CAM_REQ_ABORTED;
            /* ÒªÇó¿ØÖÆÆ÷ÖÐÖ¹CCB£¬È»ºó²úÉúÒ»¸öÖжϲ¢Í£Ö¹
             */
            if(signal_hardware_to_abort_hcb_and_stop(hcb) < 0) {
                /* °¥Ñ½£¬ÎÒÃÇûÓлñµÃÓëÓ²¼þµÄ¾ºÕùÌõ¼þ£¬ÔÚÎÒÃÇÖÐÖ¹
                 * Õâ¸öÊÂÎñ֮ǰËü¾ÍÍÑÀë×ÜÏߣ¬ÔÙ³¢ÊÔÒ»´Î 
    	     * £¨Òë×¢£ºÍÑÀ룽getoff£©*/
                goto abort_again;
            }
    
            break;
    

    Èç¹ûCCBλÓÚ¶Ï¿ªÁ¬½ÓµÄÁбíÖУ¬Ôò½«ËüÉèÖÃΪÖÐÖ¹ÇëÇ󣬲¢ÔÚÓ²¼þ ¶ÓÁеÄǰ¶Ë½«ËüÖØÐÂÈë¶Ó¡£¸´Î»³¬Ê±£¬²¢±¨¸æÖÐÖ¹ÇëÇóÍê³É¡£

        case HCB_DISCONNECTED:
            untimeout(xxx_timeout, (caddr_t) hcb, abort_ccb->ccb_h.timeout_ch);
            abort_ccb->ccb_h.timeout_ch = 
                timeout(xxx_timeout, (caddr_t) hcb, 10 * hz);
            put_abort_message_into_hcb(hcb);
            put_hcb_at_the_front_of_hardware_queue(hcb);
            break;
        }
        ccb->ccb_h.status = CAM_REQ_CMP;
        xpt_done(ccb);
        return;
    

    Õâ¾ÍÊǹØÓÚABORTÇëÇóµÄÈ«²¿£¬¾¡¹Ü»¹ÓÐÒ»¸öÎÊÌâ¡£ÓÉÓÚABORTÏûÏ¢ Çå³ýLUNÉÏËùÓÐÕýÔÚ½øÐÐÖеÄÊÂÎñ£¬ÎÒÃDZØÐ뽫LUNÉÏËùÓÐÆäËû»î¶¯ÊÂÎñ ±ê¼ÇΪÖÐÖ¹¡£ÄÇÓ¦µ±ÔÚÖжÏÀý³ÌÖÐÍê³É£¬ÇÒÔÚÖÐÖ¹ÊÂÎñÖ®ºó¡£

    ½«CCBÖÐÖ¹×÷Ϊº¯ÊýÀ´ÊµÏÖ¿ÉÄÜÊǸöºÜºÃµÄÖ÷Ò⣬ÒòΪÈç¹ûI/OÊÂÎñ³¬Ê± Õâ¸öº¯ÊýÄܹ»±»ÖØÓá£Î¨Ò»µÄ²»Í¬Êdz¬Ê±ÊÂÎñ½«Îª³¬Ê±ÇëÇó·µ»Ø×´Ì¬ CAM_CMD_TIMEOUT¡£ÓÚÊÇXPT_ABORTµÄcaseÓï¾ä¾Í»áºÜС£¬ÏñÏÂÃæÕâÑù£º

        case XPT_ABORT:
            struct ccb *abort_ccb;
            abort_ccb = ccb->cab.abort_ccb;
    
            if(abort_ccb->ccb_h.func_code != XPT_SCSI_IO) {
                ccb->ccb_h.status = CAM_UA_ABORT;
                xpt_done(ccb);
                return;
            }
            if(xxx_abort_ccb(abort_ccb, CAM_REQ_ABORTED) < 0)
                /* no such CCB in our queue */
                ccb->ccb_h.status = CAM_PATH_INVALID; 
            else
                ccb->ccb_h.status = CAM_REQ_CMP;
            xpt_done(ccb);
            return;
    
  • XPT_SET_TRAN_SETTINGS - ÏÔʽÉèÖÃSCSI´«ÊäÉèÖõÄÖµ

    ÔÚÁªºÏccbµÄʵÀý¡°struct ccb_trans_setting cts¡± Öд«ÊäµÄ²ÎÁ¿£º

    • valid - λÑÚÂ룬ÏÔʾӦµ±¸üÐÂÄÇЩÉèÖãº

    • CCB_TRANS_SYNC_RATE_VALID - ͬ²½´«ÊäËÙÂÊ

    • CCB_TRANS_SYNC_OFFSET_VALID - ͬ²½Î»ÒÆ

    • CCB_TRANS_BUS_WIDTH_VALID - ×ÜÏß¿í¶È

    • CCB_TRANS_DISC_VALID - ÉèÖÃÆôÓÃ/½ûÓöϿªÁ¬½Ó

    • CCB_TRANS_TQ_VALID - ÉèÖÃÆôÓÃ/½ûÓôø±êÇ©µÄÅŶÓ

    • flags - ÓÉÁ½²¿·Ö×é³É£¬Á½Ôª²ÎÁ¿ºÍ×Ó²Ù×÷±êʶ¡£Á½Ôª²ÎÁ¿Îª£º

      • CCB_TRANS_DISC_ENB - ÆôÓöϿªÁ¬½Ó

      • CCB_TRANS_TAG_ENB - ÆôÓôø±êÇ©µÄÅŶÓ

    • ×Ó²Ù×÷Ϊ£º

      • CCB_TRANS_CURRENT_SETTINGS - ¸Ä±äµ±Ç°µÄЭÉÌ

      • CCB_TRANS_USER_SETTINGS - ¼ÇסϣÍûµÄÓû§Öµ

      • sync_period, sync_offset - ×Ô½âÊ͵ģ¬Èç¹ûsync_offset==0ÔòÇëÇóͬ²½Ä£Ê½

      • bus_width - ×ÜÏß´ø¿í£¬ÒÔλ¼Æ£¨¶ø²»ÊÇ×Ö½Ú£©

        Òë×¢: ²Î¿¼Ô­ÎĺÍÔ´Âë

    Ö§³ÖÁ½×éЭÉ̲ÎÊý£¬Óû§ÉèÖú͵±Ç°ÉèÖá£Óû§ÉèÖÃÔÚSIMÇý¶¯³ÌÐòÖРʵ¼ÊÉÏÓõò»¶à£¬Õâͨ³£Ö»ÊÇһƬÄڴ棬¹©ÉÏ²ã´æ´¢£¨²¢ÔÚÒÔºó»Ö¸´£©Æä¹ØÓÚ ²ÎÊýµÄһЩÖ÷ÕÅ¡£ÉèÖÃÓû§²ÎÊý²¢²»»áµ¼ÖÂÖØÐÂЭÉÌ´«ÊäËÙÂÊ¡£µ«µ±SCSI ¿ØÖÆÆ÷ЭÉÌʱ£¬Ëü±ØÐëÓÀÔ¶²»ÄÜÉèÖøßÓÚÓû§²ÎÊýµÄÖµ£¬Òò´ËËüʵÖÊÉÏÊÇ ÉÏÏÞ¡£

    µ±Ç°ÉèÖã¬ÕýÈçÆäÃû×ÖËùʾ£¬Ö¸µ±Ç°µÄ¡£¸Ä±äËüÃÇÒâζ×ÅÏÂÒ»´Î´«Êäʱ ±ØÐëÖØÐÂЭÉ̲ÎÊý¡£ÓÖÒ»´Î£¬ÕâЩ¡°new current settings¡± ²¢Ã»Óб»¼Ù¶¨ÎªÇ¿ÖÆÓÃÓÚÉ豸ÉÏ£¬ËüÃÇÖ»ÊÇÓÃ×÷ЭÉÌµÄÆðʼ²½Öè¡£´ËÍ⣬ ËüÃDZØÐëÊÜSCSI¿ØÖÆÆ÷µÄʵ¼ÊÄÜÁ¦ÏÞÖÆ£ºÀýÈ磬Èç¹ûSCSI¿ØÖÆÆ÷ÓÐ8λ×ÜÏߣ¬ ¶øÇëÇóÒªÇóÉèÖÃ16λ´«Ê䣬ÔòÔÚ·¢Ë͸øÉ豸ǰ²ÎÊý±ØÐë±»ÇÄÇĵؽØÈ¡Îª8λ¡£

    Ò»¸öÐèҪעÒâµÄÎÊÌâ¾ÍÊÇ×ÜÏß¿í¶ÈºÍͬ²½Á½¸ö²ÎÊýÊÇÕë¶ÔÿĿ±êµÄ¶øÑԵģ¬ ¶ø¶Ï¿ªÁ¬½ÓºÍÆôÓñêÇ©Á½¸ö²ÎÊýÊÇÕë¶Ôÿlun¶øÑԵġ£

    ½¨ÒéµÄʵÏÖÊDZ£³Ö3×éЭÉ̲ÎÊý£¨×ÜÏß¿í¶ÈºÍͬ²½´«Ê䣩£º

    • user - Óû§µÄÒ»×飬ÈçÉÏ

    • current - ʵ¼ÊÉúЧµÄÄÇЩ

    • goal - ͨ¹ýÉèÖá°current¡±²ÎÊýËùÇëÇóµÄÄÇЩ

    ´úÂë¿´ÆðÀ´Ïñ£º

        struct ccb_trans_settings *cts;
        int targ, lun;
        int flags;
    
        cts = &ccb->cts;
        targ = ccb_h->target_id;
        lun = ccb_h->target_lun;
        flags = cts->flags;
        if(flags & CCB_TRANS_USER_SETTINGS) {
            if(flags & CCB_TRANS_SYNC_RATE_VALID)
                softc->user_sync_period[targ] = cts->sync_period;
            if(flags & CCB_TRANS_SYNC_OFFSET_VALID)
                softc->user_sync_offset[targ] = cts->sync_offset;
            if(flags & CCB_TRANS_BUS_WIDTH_VALID)
                softc->user_bus_width[targ] = cts->bus_width;
    
            if(flags & CCB_TRANS_DISC_VALID) {
                softc->user_tflags[targ][lun] &= ~CCB_TRANS_DISC_ENB;
                softc->user_tflags[targ][lun] |= flags & CCB_TRANS_DISC_ENB;
            }
            if(flags & CCB_TRANS_TQ_VALID) {
                softc->user_tflags[targ][lun] &= ~CCB_TRANS_TQ_ENB;
                softc->user_tflags[targ][lun] |= flags & CCB_TRANS_TQ_ENB;
            }
        }
        if(flags & CCB_TRANS_CURRENT_SETTINGS) {
            if(flags & CCB_TRANS_SYNC_RATE_VALID)
                softc->goal_sync_period[targ] = 
                    max(cts->sync_period, OUR_MIN_SUPPORTED_PERIOD);
            if(flags & CCB_TRANS_SYNC_OFFSET_VALID)
                softc->goal_sync_offset[targ] = 
                    min(cts->sync_offset, OUR_MAX_SUPPORTED_OFFSET);
            if(flags & CCB_TRANS_BUS_WIDTH_VALID)
                softc->goal_bus_width[targ] = min(cts->bus_width, OUR_BUS_WIDTH);
    
            if(flags & CCB_TRANS_DISC_VALID) {
                softc->current_tflags[targ][lun] &= ~CCB_TRANS_DISC_ENB;
                softc->current_tflags[targ][lun] |= flags & CCB_TRANS_DISC_ENB;
            }
            if(flags & CCB_TRANS_TQ_VALID) {
                softc->current_tflags[targ][lun] &= ~CCB_TRANS_TQ_ENB;
                softc->current_tflags[targ][lun] |= flags & CCB_TRANS_TQ_ENB;
            }
        }
        ccb->ccb_h.status = CAM_REQ_CMP;
        xpt_done(ccb);
        return;
    

    ´Ëºóµ±ÏÂÒ»´ÎÒª´¦ÀíI/OÇëÇóʱ£¬Ëü»á¼ì²éÆäÊÇ·ñÐèÒªÖØÐÂЭÉÌ£¬ ÀýÈçͨ¹ýµ÷Óú¯Êýtarget_negotiated(hcb)¡£Ëü¿ÉÒÔÈçÏÂʵÏÖ£º

        int
        target_negotiated(struct xxx_hcb *hcb)
        {
            struct softc *softc = hcb->softc;
            int targ = hcb->targ;
    
            if( softc->current_sync_period[targ] != softc->goal_sync_period[targ]
            || softc->current_sync_offset[targ] != softc->goal_sync_offset[targ]
            || softc->current_bus_width[targ] != softc->goal_bus_width[targ] )
                return 0; /* FALSE */
            else
                return 1; /* TRUE */
        }
    

    ÖØÐÂЭÉÌÕâЩֵºó£¬½á¹ûÖµ±ØÐëͬʱ¸³¸øµ±Ç°ºÍÄ¿µÄ(goal)²ÎÊý£¬ ÕâÑù¶ÔÓÚÒÔºóµÄI/OÊÂÎñµ±Ç°ºÍÄ¿µÄ²ÎÊý½«Ïàͬ£¬ÇÒ target_negotiated()»á·µ»ØTRUE¡£µ±³õʼ»¯¿¨ £¨ÔÚxxx_attach()ÖУ©µ±Ç°Ð­ÉÌÖµ±ØÐë±»³õʼ»¯Îª ×îխͬ²½Ä£Ê½£¬Ä¿µÄºÍµ±Ç°Öµ±ØÐë±»³õʼ»¯Îª¿ØÖÆÆ÷ËùÖ§³ÖµÄ×î´óÖµ¡£ £¨Òë×¢£ºÔ­ÎÄ¿ÉÄÜÓÐÎ󣬴˴¦Î´¸Ä£©

  • XPT_GET_TRAN_SETTINGS - »ñµÃSCSI´«ÊäÉèÖõÄÖµ

    ´Ë²Ù×÷ΪXPT_SET_TRAN_SETTINGSµÄÄæ²Ù×÷¡£ÓÃͨ¹ýÆì±ê CCB_TRANS_CURRENT_SETTINGS»òCCB_TRANS_USER_SETTINGS£¨Èç¹ûͬʱÉèÖÃÔò ÏÖÓÐÇý¶¯³ÌÐò·µ»Øµ±Ç°ÉèÖã©ËùÇëÇó¶øµÃµÄÊý¾ÝÌî³äCCBʵÀý ¡°struct ccb_trans_setting cts¡±.

  • XPT_CALC_GEOMETRY - ¼ÆËã´ÅÅ̵ÄÂß¼­£¨BIOS£©½á¹¹(geometry)

    ²ÎÁ¿ÔÚÁªºÏccbµÄʵÀý¡°struct ccb_calc_geometry ccg¡± Öд«Ê䣺

    • block_size - ÊäÈ룬ÒÔ×ֽڼƵĿé´óС£¨Ò²³ÆÎªÉÈÇø£©

    • volume_size - ÊäÈ룬ÒÔ×ֽڼƵľí´óС

    • cylinders - Êä³ö£¬Âß¼­ÖùÃæ

    • heads - Êä³ö£¬Âß¼­´ÅÍ·

    • secs_per_track - Êä³ö£¬Ã¿´ÅµÀµÄÂß¼­ÉÈÇø

    Èç¹û·µ»ØµÄ½á¹¹ÓëSCSI¿ØÖÆÆ÷BIOSËùÏëÏóµÄ²î±ðºÜ´ó£¬²¢ÇÒSCSI ¿ØÖÆÆ÷ÉϵĴÅÅ̱»×÷Ϊ¿ÉÒýµ¼µÄ£¬Ôòϵͳ¿ÉÄÜÎÞ·¨Æô¶¯¡£´Óaic7xxx Çý¶¯³ÌÐòÖÐժȡµÄµäÐͼÆËãʾÀý£º

        struct    ccb_calc_geometry *ccg;
        u_int32_t size_mb;
        u_int32_t secs_per_cylinder;
        int   extended;
    
        ccg = &ccb->ccg;
        size_mb = ccg->volume_size
            / ((1024L * 1024L) / ccg->block_size);
        extended = check_cards_EEPROM_for_extended_geometry(softc);
    
        if (size_mb > 1024 && extended) {
            ccg->heads = 255;
            ccg->secs_per_track = 63;
        } else {
            ccg->heads = 64;
            ccg->secs_per_track = 32;
        }
        secs_per_cylinder = ccg->heads * ccg->secs_per_track;
        ccg->cylinders = ccg->volume_size / secs_per_cylinder;
        ccb->ccb_h.status = CAM_REQ_CMP;
        xpt_done(ccb);
        return;
    

    Õâ¸ø³öÁËÒ»°ã˼·£¬¾«È·¼ÆËãÒÀÀµÓÚÌØ¶¨BIOSµÄñ±ºÃ(quirk)¡£Èç¹û BIOSûÓÐÌṩ·½·¨ÉèÖÃEEPROMÖеġ°extended translation¡± Æì±ê£¬Ôò´ËÆì±êͨ³£Ó¦µ±¼Ù¶¨µÈÓÚ1¡£ÆäËûÁ÷ÐнṹÓУº

        128 heads, 63 sectors - Symbios¿ØÖÆÆ÷
        16 heads, 63 sectors - ÀÏʽ¿ØÖÆÆ÷
    

    һЩϵͳBIOSºÍSCSI BIOS»áÏ໥¾ºÕù£¬Ê¤¸º²»¶¨£¬ÀýÈçSymbios 875/895 SCSIºÍPhoenix BIOSµÄ½áºÏÔÚϵͳ¼Óµçʱ»á¸ø³ö½á¹¹128/63£¬ ¶øµ±ÀäÆô¶¯»òÈíÆô¶¯ºó»áÊÇ255/63¡£

  • XPT_PATH_INQ - ·¾¶ÎÊѯ£¬ »»¾ä»°Ëµ£¬»ñµÃSIMÇý¶¯³ÌÐòºÍSCSI¿ØÖÆÆ÷£¨Ò²³ÆÎªHBA - Ö÷»ú×ÜÏßÊÊÅäÆ÷£© µÄÌØÐÔ¡£

    ÌØÐÔÔÚÁªºÏccbµÄʵÀý¡°struct ccb_pathinq cpi¡± Öзµ»Ø£º

    • version_num - SIMÇý¶¯³ÌÐòºÅ£¬µ±Ç°ËùÓÐÇý¶¯³ÌÐòʹÓÃ1

    • hba_inquiry - ¿ØÖÆÆ÷ËùÖ§³ÖÌØÐÔµÄλÑÚÂ룺

    • PI_MDP_ABLE - Ö§³ÖMDPÏûÏ¢£¨À´×ÔSCSI3µÄһЩ¶«Î÷?£©

    • PI_WIDE_32 - Ö§³Ö32λ¿íSCSI

    • PI_WIDE_16 - Ö§³Ö16λ¿íSCSI

    • PI_SDTR_ABLE - ¿ÉÒÔЭÉÌͬ²½´«ÊäËÙÂÊ

    • PI_LINKED_CDB - Ö§³ÖÁ´½ÓµÄÃüÁî

    • PI_TAG_ABLE - Ö§³Ö´ø±êÇ©µÄÃüÁî

    • PI_SOFT_RST - Ö§³ÖÈí¸´Î»Ñ¡Ôñ £¨Ó²¸´Î»ºÍÈí¸´Î»ÔÚSCSI×ÜÏßÖÐÊÇ»¥³âµÄ£©

    • target_sprt - Ä¿±êģʽ֧³ÖµÄÆì±ê£¬Èç¹û²»Ö§³ÖÔòΪ0

    • hba_misc - ¿ØÖÆÆ÷ÌØÐÔÔÓÏ

    • PIM_SCANHILO - ´Ó¸ßIDµ½µÍIDµÄ×ÜÏßɨÃè

    • PIM_NOREMOVE - ¿ÉÒÆ³ýÉ豸²»°üÀ¨ÔÚɨÃèÖ®ÁÐ

    • PIM_NOINITIATOR - ²»Ö§³Ö·¢ÆðÕß½ÇÉ«

    • PIM_NOBUSRESET - Óû§½ûÓóõʼBUS RESET

    • hba_eng_cnt - ÉñÃØµÄHBAÒýÇæ¼ÆÊý£¬ÓëѹËõÓйصÄһЩ ¶«Î÷£¬µ±Ç°×ÜÊÇÖÃΪ0

    • vuhba_flags - ¹©Ó¦ÉÌΨһµÄÆì±ê£¬µ±Ç°Î´ÓÃ

    • max_target - ×î´óÖ§³ÖµÄÄ¿±êID£¨¶Ô8λ×ÜÏßΪ7£¬ 16λ×ÜÏßΪ15£¬¹âÏËͨµÀΪ127£©

    • max_lun - ×î´óÖ§³ÖµÄLUN ID£¨¶Ô½ÏÀϵÄSCSI¿ØÖÆÆ÷ Ϊ7£¬½ÏеÄΪ63£©

    • async_flags - °²×°µÄÒì²½´¦Àíº¯ÊýµÄλÑÚÂ룬µ±Ç°Î´ÓÃ

    • hpath_id - ×ÓϵͳÖÐ×î¸ßµÄ·¾¶ID£¬µ±Ç°Î´ÓÃ

    • unit_number - ¿ØÖÆÆ÷µ¥ÔªºÅ£¬cam_sim_unit(sim)

    • bus_id - ×ÜÏߺţ¬cam_sim_bus(sim)

    • initiator_id - ¿ØÖÆÆ÷×Ô¼ºµÄSCSI ID

    • base_transfer_speed - Òì²½Õ­´«ÊäµÄÃûÒå´«ÊäËÙÂÊ£¬ ÒÔKB/s¼Æ£¬¶ÔÓÚSCSIµÈÓÚ3300

    • sim_vid - SIMÇý¶¯³ÌÐòµÄ¹©Ó¦ÉÌID£¬ÒÔ0½áÊøµÄ×Ö·û´®£¬ °üº¬½áβ0ÔÚÄÚµÄ×î´ó³¤¶ÈΪSIM_IDLEN

    • hba_vid - SCSI¿ØÖÆÆ÷µÄ¹©Ó¦ÉÌID£¬ÒÔ0½áÊøµÄ×Ö·û´®£¬ °üº¬½áβ0ÔÚÄÚµÄ×î´ó³¤¶ÈΪHBA_IDLEN

    • dev_name - É豸Çý¶¯³ÌÐòÃû×Ö£¬ÒÔ0½áβµÄ×Ö·û´®£¬ °üº¬½áβ0ÔÚÄÚµÄ×î´ó³¤¶ÈΪDEV_IDLEN£¬µÈÓÚcam_sim_name(sim)

    ÉèÖÃ×Ö·û´®×ֶεĽ¨Òé·½·¨ÊÇʹÓÃstrncpy£¬È磺

        strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
    

    ÉèÖÃÕâЩֵºó½«×´Ì¬ÉèÖÃΪCAM_REQ_CMP£¬²¢½«CCB±ê¼ÇΪÍê³É¡£


12.3 ÂÖѯ

static void xxx_poll ( struct cam_sim *sim );

¡¡¡¡ÂÖѯº¯ÊýÓÃÓÚµ±ÖжÏ×Óϵͳ²»Æð×÷ÓÃʱ£¨ÀýÈ磬ϵͳ±ÀÀ£»òÕýÔÚ´´½¨ ϵͳת´¢£©Ä£ÄâÖжϡ£CAM×ÓϵͳÔÚµ÷ÓÃÂÖѯº¯ÊýǰÉèÖÃÊʵ±µÄÖжϼ¶±ð¡£ Òò´ËËüËùÐè×öÈ«²¿µÄÖ»Êǵ÷ÓÃÖжÏÀý³Ì£¨»òÆäËû·½·¨£¬ÂÖѯÀý³ÌÀ´ ½øÐÐʵ¼Ê¶¯×÷, ¶øÖжÏÀý³ÌÖ»Êǵ÷ÓÃÂÖѯÀý³Ì£©¡£ÄÇôΪʲôҪÕÒÂé·³ Ū³öÒ»¸öµ¥¶ÀµÄº¯ÊýÀ´ÄØ£¿ÕâÊÇÓÉÓÚ²»Í¬µÄµ÷ÓÃÔ¼¶¨¡£ xxx_pollÀý³ÌÈ¡½á¹¹cam_simµÄÖ¸Õë×÷Ϊ²ÎÁ¿£¬ ¶øPCIÖжÏÀý³Ì°´ÕÕÆÕͨԼ¶¨È¡µÄÊÇÖ¸Ïò½á¹¹ xxx_softcµÄÖ¸Õ룬ISAÖжÏÀý³ÌÖ»ÊÇÈ¡É豸ºÅ£¬ Òò´ËÂÖѯÀý³ÌÒ»°ã¿´ÆðÀ´Ïñ£º

static void 
xxx_poll(struct cam_sim *sim)
{
    xxx_intr((struct xxx_softc *)cam_sim_softc(sim)); /* for PCI device */
}

¡¡¡¡or

static void 
xxx_poll(struct cam_sim *sim)
{
    xxx_intr(cam_sim_unit(sim)); /* for ISA device */
}

12.4 Ò첽ʼþ

¡¡¡¡Èç¹û½¨Á¢ÁËÒ첽ʼþ»Øµ÷£¬ÔòÓ¦µ±¶¨Ò廨µ÷º¯Êý¡£

static void
ahc_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
  • callback_arg - ×¢²á»Øµ÷ʱÌṩµÄÖµ

  • code - ±êʶʼþÀàÐÍ

  • path - ±êʶʼþ×÷ÓÃÓÚÆäÉϵÄÉ豸

  • arg - ʼþÌØ¶¨µÄ²ÎÁ¿

¡¡¡¡µ¥Ò»ÀàÐÍʼþµÄʵÏÖ£¬AC_LOST_DEVICE£¬¿´ÆðÀ´ÈçÏ£º

    struct xxx_softc *softc;
    struct cam_sim *sim;
    int targ;
    struct ccb_trans_settings neg;

    sim = (struct cam_sim *)callback_arg;
    softc = (struct xxx_softc *)cam_sim_softc(sim);
    switch (code) {
    case AC_LOST_DEVICE:
        targ = xpt_path_target_id(path);
        if(targ <= OUR_MAX_SUPPORTED_TARGET) {
            clean_negotiations(softc, targ);
            /* send indication to CAM */
            neg.bus_width = 8;
            neg.sync_period = neg.sync_offset = 0;
            neg.valid = (CCB_TRANS_BUS_WIDTH_VALID
                | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);
            xpt_async(AC_TRANSFER_NEG, path, &neg);
        }
        break;
    default:
        break;
    }

12.5 ÖжÏ

¡¡¡¡ÖжÏÀý³ÌµÄÈ·ÇÐÀàÐÍÒÀÀµÓÚSCSI¿ØÖÆÆ÷ËùÁ¬½Óµ½µÄÍâΧ×ÜÏßµÄÀàÐÍ£¨PCI£¬ ISAµÈµÈ£©¡£

¡¡¡¡SIMÇý¶¯³ÌÐòµÄÖжÏÀý³ÌÔËÐÐÔÚÖжϼ¶±ðsplcamÉÏ¡£Òò´ËÓ¦µ±ÔÚÇý¶¯ ³ÌÐòÖÐʹÓÃsplcam()À´Í¬²½ÖжÏÀý³ÌÓëÇý¶¯³ÌÐò Ê£Óಿ·ÖµÄ»î¶¯£¨¶ÔÓÚÄܲì¾õ¶à´¦ÀíÆ÷µÄÇý¶¯³ÌÐò£¬ÊÂÇé¸üÒªÓÐȤ£¬µ« ´Ë´¦ÎÒÃǺöÂÔÕâÖÖÇé¿ö£©¡£±¾ÎĵµÖеÄα´úÂë¼òµ¥µØºöÂÔÁËͬ²½ÎÊÌâ¡£ ʵ¼Ê´úÂëÒ»¶¨²»ÄܺöÂÔËüÃÇ¡£Ò»¸ö½Ï±¿µÄ°ì·¨¾ÍÊÇÔÚ½øÈëÆäËûÀý³ÌµÄ Èë¿Úµã´¦Éèsplcam()£¬²¢ÔÚ·µ»ØÊ±½«Ëü¸´Î»£¬´Ó¶ø ÓÃÒ»¸ö´óµÄÁÙ½çÇø±£»¤ËüÃÇ¡£ÎªÁËÈ·±£Öжϼ¶±ð×ÜÊǻᱻ»Ö¸´£¬¿ÉÒÔ¶¨Òå Ò»¸ö°ü×°º¯Êý£¬È磺

    static void 
    xxx_action(struct cam_sim *sim, union ccb *ccb)
    {
        int s;
        s = splcam();
        xxx_action1(sim, ccb);
        splx(s);
    }

    static void 
    xxx_action1(struct cam_sim *sim, union ccb *ccb)
    {
        ... process the request ...
    }

¡¡¡¡ÕâÖÖ·½·¨¼òµ¥¶øÇÒ½¡×³£¬µ«Ëü´æÔÚµÄÎÊÌâÊÇÖжϿÉÄܻᱻ×èÈûÏà¶Ô ºÜ³¤µÄʼþ£¬Õâ»á¶ÔϵͳÐÔÄܲúÉú¸ºÃæÓ°Ïì¡£ÁíÒ»·½Ã棬 spl()º¯Êý×åÓÐÏ൱¸ßµÄ¶îÍ⿪Ïú£¬Òò´Ë´óÁ¿ ºÜСµÄÁÙ½çÇø¿ÉÄÜÒ²²»ºÃ¡£

¡¡¡¡ÖжÏÀý³Ì´¦ÀíµÄÇé¿öºÍÆäÖÐϸ½ÚÑÏÖØÒÀÀµÓÚÓ²¼þ¡£ÎÒÃÇ¿¼ÂÇ ¡°µäÐÍ(typical)¡±Çé¿ö¡£

¡¡¡¡Ê×ÏÈ£¬ÎÒÃǼì²é×ÜÏßÉÏÊÇ·ñÓöµ½ÁËSCSI¸´Î»£¨¿ÉÄÜÓÉͬһSCSI×ÜÏßÉÏ µÄÁíÒ»SCSI¿ØÖÆÆ÷ÒýÆð£©¡£Èç¹ûÕâÑùÎÒÃǶªÆúËùÓÐÈë¶ÓµÄºÍ¶Ï¿ªÁ¬½ÓµÄ ÇëÇ󣬱¨¸æÊ¼þ²¢ÖØÐ³õʼ»¯ÎÒÃǵÄSCSI¿ØÖÆÆ÷¡£³õʼ»¯ÆÚ¼ä¿ØÖÆÆ÷ ²»»á·¢³öÁíÒ»¸ö¸´Î»£¬Õâ¶ÔÎÒÃÇÊ®·ÖÖØÒª£¬·ñÔòͬһSCSI×ÜÏßÉϵÄÁ½¸ö¿ØÖÆÆ÷ ¿ÉÄÜ»áÒ»Ö±À´»ØµØ¸´Î»ÏÂÈ¥¡£¿ØÖÆÆ÷ÖÂÃü´íÎó/¹ÒÆðµÄÇé¿ö¿ÉÒÔÔÚͬһ µØ·½½øÐд¦Àí£¬µ«Õâ¿ÉÄÜÐèÒª·¢ËÍRESETÐźŵ½SCSI×ÜÏßÀ´¸´Î»ÓëSCSI É豸µÄÁ¬½Ó״̬¡£

    int fatal=0;
    struct ccb_trans_settings neg;
    struct cam_path *path;

    if( detected_scsi_reset(softc)
    || (fatal = detected_fatal_controller_error(softc)) ) {
        int targ, lun;
        struct xxx_hcb *h, *hh;

        /* ¶ªÆúËùÓÐÈë¶ÓµÄCCB */
        for(h = softc->first_queued_hcb; h != NULL; h = hh) {
            hh = h->next;
            free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);
        }

        /* Òª±¨¸æµÄЭÉ̵ĸɾ»Öµ */
        neg.bus_width = 8;
        neg.sync_period = neg.sync_offset = 0;
        neg.valid = (CCB_TRANS_BUS_WIDTH_VALID
            | CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID);

        /* ¶ªÆúËùÓжϿªÁ¬½ÓµÄCCBºÍ¸É¾»Ð­ÉÌ */
        for(targ=0; targ <= OUR_MAX_SUPPORTED_TARGET; targ++) {
            clean_negotiations(softc, targ);

            /* report the event if possible */
            if(xpt_create_path(&path, /*periph*/NULL,
                    cam_sim_path(sim), targ,
                    CAM_LUN_WILDCARD) == CAM_REQ_CMP) {
                xpt_async(AC_TRANSFER_NEG, path, &neg);
                xpt_free_path(path);
            }

            for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++) 
                for(h = softc->first_discon_hcb[targ][lun]; h != NULL; h = hh) {
                    hh=h->next;
                    if(fatal)
                        free_hcb_and_ccb_done(h, h->ccb, CAM_UNREC_HBA_ERROR);
                    else
                        free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);
                }
        }

        /* ±¨¸æÊ¼þ */
        xpt_async(AC_BUS_RESET, softc->wpath, NULL);

        /* ÖØÐ³õʼ»¯¿ÉÄÜ»¨ºÜ¶àʱ¼ä£¬ÕâÖÖÇé¿öÏÂÓ¦µ±ÓÉÁíÒ»ÖжϷ¢ÐźÅ
         * ָʾ³õʼ»¯·ñÍê³É£¬»òÔÚ³¬Ê±Ê±¼ì²é - µ«ÎªÁ˼òµ¥ÎÒÃǼÙÉè
         * ³õʼ»¯ÕæµÄºÜ¿ì
         */
        if(!fatal) {
            reinitialize_controller_without_scsi_reset(softc); 
        } else {
            reinitialize_controller_with_scsi_reset(softc); 
        }
        schedule_next_hcb(softc);
        return;
    }

¡¡¡¡Èç¹ûÖжϲ»ÊÇÓÉ¿ØÖÆÆ÷·¶Î§µÄÌõ¼þÒýÆðµÄ£¬ÔòºÜ¿ÉÄܵ±Ç°Ó²¼þ¿ØÖÆ¿é ³öÏÖÁËÎÊÌâ¡£ÒÀÀµÓÚÓ²¼þ£¬¿ÉÄÜÓзÇHCBÏà¹ØµÄʼþ£¬´Ë´¦ÎÒÃÇָʾ²»¿¼ÂÇ ËüÃÇ¡£È»ºóÎÒÃÇ·ÖÎöÕâ¸öHCB·¢ÉúÁËʲô£º

    struct xxx_hcb *hcb, *h, *hh;
    int hcb_status, scsi_status;
    int ccb_status;
    int targ;
    int lun_to_freeze;

    hcb = get_current_hcb(softc);
    if(hcb == NULL) {
        /* »òÕß¶ªÊ§(stray)µÄÖжϣ¬»òÕßijЩ¶«Î÷ÑÏÖØ´íÎó£¬
         * »òÕßÕâÊÇÓ²¼þÏà¹ØµÄijЩ¶«Î÷
         */
        ½øÐбØÒªµÄ´¦Àí;
        return;
    }

    targ = hcb->target;
    hcb_status = get_status_of_current_hcb(softc);

¡¡¡¡Ê×ÏÈÎÒÃǼì²éHCBÊÇ·ñÍê³É£¬Èç¹ûÍê³ÉÎÒÃǾͼì²é·µ»ØµÄSCSI״̬¡£

    if(hcb_status == COMPLETED) {
        scsi_status = get_completion_status(hcb);

¡¡¡¡È»ºó¿´Õâ¸ö״̬ÊÇ·ñÓëREQUEST SENSEÃüÁîÓйأ¬Èç¹ûÓйØÔò¼òµ¥ µØ´¦ÀíÒ»ÏÂËü¡£

        if(hcb->flags & DOING_AUTOSENSE) {
            if(scsi_status == GOOD) { /* autosense³É¹¦ */
                hcb->ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
                free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);
            } else {
        autosense_failed:
                free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_AUTOSENSE_FAIL);
            }
            schedule_next_hcb(softc);
            return;
        }

¡¡¡¡·ñÔòÃüÁî×ÔÉíÒѾ­Íê³É£¬°Ñ¸ü¶à×¢ÒâÁ¦·ÅÔÚϸ½ÚÉÏ¡£Èç¹ûÕâ¸öCCB ûÓнûÓÃauto-sense²¢ÇÒÃüÁîÁ¬Í¬senseÊý¾Ýʧ°Ü£¬ÔòÔËÐÐREQUEST SENSE ÃüÁî½ÓÊÕÄÇЩÊý¾Ý¡£

        hcb->ccb->csio.scsi_status = scsi_status;
        calculate_residue(hcb);

        if( (hcb->ccb->ccb_h.flags & CAM_DIS_AUTOSENSE)==0
        && ( scsi_status == CHECK_CONDITION 
                || scsi_status == COMMAND_TERMINATED) ) {
            /* Æô¶¯auto-SENSE */
            hcb->flags |= DOING_AUTOSENSE;
            setup_autosense_command_in_hcb(hcb);
            restart_current_hcb(softc);
            return;
        }
        if(scsi_status == GOOD)
            free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_REQ_CMP);
        else
            free_hcb_and_ccb_done(hcb, hcb->ccb, CAM_SCSI_STATUS_ERROR);
        schedule_next_hcb(softc);
        return;
    }

¡¡¡¡ÊôÓÚЭÉÌʼþµÄÒ»¸öµäÐÍÊÂÇ飺´ÓSCSIÄ¿±ê£¨»Ø´ðÎÒÃǵÄЭÉÌÆóͼ»ò ÓÉÄ¿±ê·¢ÆðµÄ£©½ÓÊÕµ½µÄЭÉÌÏûÏ¢£¬»òÄ¿±êÎÞ·¨Ð­ÉÌ£¨¾Ü¾øÎÒÃǵÄЭÉÌÏûÏ¢ »ò²»»Ø´ðËüÃÇ£©¡£

    switch(hcb_status) {
    case TARGET_REJECTED_WIDE_NEG:
        /* »Ö¸´µ½8-bit×ÜÏß */
        softc->current_bus_width[targ] = softc->goal_bus_width[targ] = 8;
        /* ±¨¸æÊ¼þ */
        neg.bus_width = 8; 
        neg.valid = CCB_TRANS_BUS_WIDTH_VALID;
        xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);
        continue_current_hcb(softc);
        return;
    case TARGET_ANSWERED_WIDE_NEG:
        {
            int wd;

            wd = get_target_bus_width_request(softc);
            if(wd <= softc->goal_bus_width[targ]) { 
                /* ¿É½ÓÊܵĻشð */
                softc->current_bus_width[targ] = 
                softc->goal_bus_width[targ] = neg.bus_width = wd;

                /* ±¨¸æÊ¼þ */
                neg.valid = CCB_TRANS_BUS_WIDTH_VALID;
                xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);
            } else {
                prepare_reject_message(hcb);
            }
        }
        continue_current_hcb(softc);
        return;
    case TARGET_REQUESTED_WIDE_NEG:
        {
            int wd;

            wd = get_target_bus_width_request(softc);
            wd = min (wd, OUR_BUS_WIDTH);
            wd = min (wd, softc->user_bus_width[targ]);

            if(wd != softc->current_bus_width[targ]) {
                /* ×ÜÏß¿í¶È¸Ä±äÁË */
                softc->current_bus_width[targ] = 
                softc->goal_bus_width[targ] = neg.bus_width = wd;

                /* ±¨¸æÊ¼þ */
                neg.valid = CCB_TRANS_BUS_WIDTH_VALID;
                xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);
            }
            prepare_width_nego_rsponse(hcb, wd);
        }
        continue_current_hcb(softc);
        return;
    }

¡¡¡¡È»ºóÎÒÃÇÓÃÓëÇ°ÃæÏàͬµÄ±¿°ì·¨´¦Àíauto-senseÆÚ¼ä¿ÉÄܳöÏÖµÄÈκΠ´íÎó¡£·ñÔò£¬ÎÒÃÇÔÙÒ»´Î½øÈëϸ½Ú¡£

    if(hcb->flags & DOING_AUTOSENSE)
        goto autosense_failed;

    switch(hcb_status) {

¡¡¡¡ÎÒÃÇ¿¼ÂǵÄÏÂһʼþÊÇδԤÆÚµÄÁ¬½Ó¶Ï¿ª£¬Õâ¸öʼþÔÚABORT»ò BUS DEVICE RESETÏûÏ¢Ö®ºó±»¿´×÷ÊÇÕý³£µÄ£¬ÆäËûÇé¿öÏÂÊÇ·ÇÕý³£µÄ¡£

    case UNEXPECTED_DISCONNECT:
        if(requested_abort(hcb)) {
            /* ÖÐÖ¹Ó°ÏìÄ¿±êºÍLUNÉϵÄËùÓÐÃüÁÒò´Ë½«ÄǸöÄ¿±êºÍLUNÉ쵀 
             * ËùÓжϿªÁ¬½ÓµÄHCBÒ²±ê¼ÇΪÖÐÖ¹
             */
            for(h = softc->first_discon_hcb[hcb->target][hcb->lun]; 
                    h != NULL; h = hh) {
                hh=h->next;
                free_hcb_and_ccb_done(h, h->ccb, CAM_REQ_ABORTED);
            }
            ccb_status = CAM_REQ_ABORTED;
        } else if(requested_bus_device_reset(hcb)) {
            int lun;

            /* ¸´Î»Ó°ÏìÄǸöÄ¿±êÉϵÄËùÓÐÃüÁÒò´Ë½«ÄǸöÄ¿±êºÍLUNÉ쵀 
             * ËùÓжϿªÁ¬½ÓµÄHCB±ê¼ÇΪ¸´Î»
             */

            for(lun=0; lun <= OUR_MAX_SUPPORTED_LUN; lun++) 
                for(h = softc->first_discon_hcb[hcb->target][lun]; 
                        h != NULL; h = hh) {
                    hh=h->next;
                    free_hcb_and_ccb_done(h, h->ccb, CAM_SCSI_BUS_RESET);
                }

            /* ·¢ËÍʼþ */
            xpt_async(AC_SENT_BDR, hcb->ccb->ccb_h.path_id, NULL);

            /* ÕâÊÇCAM_RESET_DEVÇëÇó±¾Éí£¬ËüÍê³ÉÁË */
            ccb_status = CAM_REQ_CMP; 
        } else {
            calculate_residue(hcb);
            ccb_status = CAM_UNEXP_BUSFREE; 
            /* request the further code to freeze the queue */
            hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;
            lun_to_freeze = hcb->lun;
        }
        break;

¡¡¡¡Èç¹ûÄ¿±ê¾Ü¾ø½ÓÊܱêÇ©£¬ÎÒÃǾÍ֪ͨCAM£¬²¢·µ»Ø´ËLUNµÄËùÓÐÃüÁ

    case TAGS_REJECTED:
        /* ±¨¸æÊ¼þ */
        neg.flags = 0 & ~CCB_TRANS_TAG_ENB; 
        neg.valid = CCB_TRANS_TQ_VALID;
        xpt_async(AC_TRANSFER_NEG, hcb->ccb.ccb_h.path_id, &neg);

        ccb_status = CAM_MSG_REJECT_REC; 
        /* ÇëÇóºóÃæµÄ´úÂë¶³½á¶ÓÁÐ */
        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;
        lun_to_freeze = hcb->lun;
        break;

¡¡¡¡È»ºóÎÒÃǼì²éһЩÆäËûÇé¿ö£¬´¦Àí(processing)»ù±¾ÉϽöÏÞÓÚÉèÖÃCCB״̬£º

    case SELECTION_TIMEOUT:
        ccb_status = CAM_SEL_TIMEOUT; 
        /* request the further code to freeze the queue */
        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;
        lun_to_freeze = CAM_LUN_WILDCARD;
        break;
    case PARITY_ERROR:
        ccb_status = CAM_UNCOR_PARITY; 
        break;
    case DATA_OVERRUN:
    case ODD_WIDE_TRANSFER:
        ccb_status = CAM_DATA_RUN_ERR; 
        break;
    default:
        /*ÒÔͨÓ÷½·¨´¦ÀíËùÓÐÆäËû´íÎó */
        ccb_status = CAM_REQ_CMP_ERR; 
        /* ÇëÇóºóÃæµÄ´úÂë¶³½á¶ÓÁÐ */
        hcb->ccb->ccb_h.status |= CAM_DEV_QFRZN;
        lun_to_freeze = CAM_LUN_WILDCARD;
        break;
    }

¡¡¡¡È»ºóÎÒÃǼì²éÊÇ·ñ´íÎóÑÏÖØµ½ÐèÒª¶³½áÊäÈë¶ÓÁУ¬Ö±µ½ËüµÃµ½´¦Àí·½¿É ½â¶³£¬Èç¹ûÊÇÕâÑùÄÇô¾ÍÕâÑùÀ´´¦Àí£º

    if(hcb->ccb->ccb_h.status & CAM_DEV_QFRZN) {
        /* ¶³½á¶ÓÁÐ */
        xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);

*        /* ÖØÐÂÈë¶ÓÕâ¸öÄ¿±ê/LUNµÄËùÓÐÃüÁ½«ËüÃÇ·µ»ØCAM */

        for(h = softc->first_queued_hcb; h != NULL; h = hh) {
            hh = h->next;

            if(targ == h->targ 
            && (lun_to_freeze == CAM_LUN_WILDCARD || lun_to_freeze == h->lun) )
                free_hcb_and_ccb_done(h, h->ccb, CAM_REQUEUE_REQ);
        }
    }
    free_hcb_and_ccb_done(hcb, hcb->ccb, ccb_status);
    schedule_next_hcb(softc);
    return;

¡¡¡¡Õâ°üÀ¨Í¨ÓÃÖжϴ¦Àí£¬¾¡¹ÜÌØ¶¨´¦ÀíÆ÷¿ÉÄÜÐèҪijЩ¸½¼Ó´¦Àí¡£


12.6 ´íÎó×ÜÀÀ

¡¡¡¡µ±Ö´ÐÐI/OÇëÇóʱºÜ¶àÊÂÇé¿ÉÄܳö´í¡£¿ÉÒÔÔÚCCB״̬Öзdz£Ï꾡µØ ±¨¸æ´íÎóÔ­Òò¡£Ê¹ÓõÄÀý×ÓÉ¢²¼ÓÚ±¾ÎĵµÖС£ÎªÁËÍêÕûÆð¼û´Ë´¦¸ø³ö ¶ÔµäÐÍ´íÎóÌõ¼þµÄ½¨ÒéÏìÓ¦µÄÒ»¸ö×ÜÀÀ£º

  • CAM_RESRC_UNAVAIL - ijЩ×ÊÔ´ ÔÝʱ²»¿ÉÓ㬲¢ÇÒµ±Æä±äΪ¿ÉÓÃʱSIMÇý¶¯³ÌÐò²»ÄܲúÉúʼþ¡£ÕâÖÖ×ÊÔ´ µÄÒ»¸öÀý×Ó¾ÍÊÇijЩ¿ØÖÆÆ÷ÄÚ²¿Ó²¼þ×ÊÔ´£¬µ±Æä¿ÉÓÃʱ¿ØÖÆÆ÷²»»áΪÆä ²úÉúÖжϡ£

  • CAM_UNCOR_PARITY - ·¢Éú²»¿É»Ö¸´µÄÆæÅ¼Ð£Ñé´íÎó

  • CAM_DATA_RUN_ERR - Êý¾ÝÍâÒç»òδԤÆÚµÄÊý¾Ý״̬(phase)£¨ÅÜÔÚÁíÒ»¸ö·½ÏòÉ϶ø²»ÊÇ CAM_DIR_MASKÖ¸¶¨µÄ·½Ïò£©£¬»ò¶ÔÓÚ¿í´«Êä³öÏÖÆæÊý´«Ê䳤¶È

  • CAM_SEL_TIMEOUT - ·¢ÉúÑ¡Ôñ³¬Ê±£¨Ä¿±ê²»ÏìÓ¦£©

  • CAM_CMD_TIMEOUT - ·¢ÉúÃüÁʱ£¨³¬Ê±º¯ÊýÔËÐУ©

  • CAM_SCSI_STATUS_ERROR - É豸·µ»ØµÄ´íÎó

  • CAM_AUTOSENSE_FAIL - É豸·µ»ØµÄ´íÎóÇÒREQUEST SENSEÃüÁîʧ°Ü

  • CAM_MSG_REJECT_REC - ÊÕµ½MESSAGE REJECTÏûÏ¢

  • CAM_SCSI_BUS_RESET - ÊÕµ½SCSI×ÜÏ߸´Î»

  • CAM_REQ_CMP_ERR - ³öÏÖ¡°²»¿ÉÄÜ(impossible)¡±SCSI״̬(phase) »òÕ߯äËû¹ÖÒìÊÂÇ飬»òÕßÈç¹û½øÒ»²½µÄÐÅÏ¢²»¿ÉÓÃÔòÖ»ÊÇͨÓôíÎó

  • CAM_UNEXP_BUSFREE - ³öÏÖδԤÆÚµÄ¶Ï¿ªÁ¬½Ó

  • CAM_BDR_SENT - BUS DEVICE RESETÏûÏ¢±»·¢Ë͵½Ä¿±ê

  • CAM_UNREC_HBA_ERROR - ²»¿É»Ö¸´µÄÖ÷»ú×ÜÏßÊÊÅäÆ÷´íÎó

  • CAM_REQ_TOO_BIG - ÇëÇó¶ÔÓÚ¿ØÖÆÆ÷Ì«´ó

  • CAM_REQUEUE_REQ - ´ËÇëÇóÓ¦µ±±»ÖØÐÂÈë¶ÓÒÔ±£³ÖÊÂÎñµÄ´ÎÐòÐÔ¡£ÕâµäÐ͵سöÏÖÔÚÏÂÁРʱ¿Ì£ºSIMʶ±ð³öÁËÓ¦µ±¶³½á¶ÓÁеĴíÎ󣬲¢ÇÒ±ØÐëÔÚsim¼¶±ðÉϽ«Ä¿±êµÄ ÆäËûÈë¶ÓÇëÇó·Å»Øµ½XPT¶ÓÁС£ÕâЩ´íÎóµÄµäÐÍÇé¿öÓÐÑ¡Ôñ³¬Ê±¡¢ÃüÁî ³¬Ê±ºÍÆäËûÀàËÆÇé¿ö¡£ÕâЩÇé¿öϳöÎÊÌâµÄÃüÁî·µ»Ø×´Ì¬À´Ö¸Ê¾´íÎó£¬ ´ËÃüÁîºÍÆäËû»¹Ã»Óб»·¢Ë͵½×ÜÏßµÄÃüÁî±»ÖØÐÂÈë¶Ó¡£

  • CAM_LUN_INVALID - SCSI¿ØÖÆÆ÷²»Ö§³ÖÇëÇóÖеÄLUN ID

  • CAM_TID_INVALID - SCSI¿ØÖÆÆ÷²»Ö§³ÖÇëÇóÖеÄÄ¿±êID


12.7 ³¬Ê±´¦Àí

¡¡¡¡µ±HCBµÄ³¬Ê±ÆÚÂúʱ£¬ÇëÇó¾ÍÓ¦µ±±»ÖÐÖ¹£¬¾ÍÏñ´¦ÀíXPT_ABORTÇëÇó Ò»Ñù¡£Î¨Ò»Çø±ðÔÚÓÚ±»ÖÐÖ¹µÄÇëÇóµÄ·µ»Ø×´Ì¬Ó¦µ±ÎªCAM_CMD_TIMEOUT ¶ø²»ÊÇCAM_REQ_ABORTED£¨Õâ¾ÍÊÇΪʲôÖÐÖ¹µÄʵÏÖ×îºÃÓɺ¯ÊýÀ´Íê³É£©¡£ µ«»¹ÓÐÒ»¸ö¿ÉÄܵÄÎÊÌ⣺Èç¹ûÖÐÖ¹ÇëÇó×Ô¼º³öÁËÂé·³Ôõô°ì£¿ÕâÖÖÇé¿öÏ Ӧµ±¸´Î»SCSI×ÜÏߣ¬¾ÍÏñ´¦ÀíXPT_RESET_BUSÇëÇóÒ»Ñù£¨²¢ÇÒ½«ÆäʵÏÖΪ º¯Êý£¬´ÓÁ½¸öµØ·½µ÷ÓõÄÏë·¨Ò²ÊÊÓÃÓÚÕâ¶ù£©¡£¶øÇÒÈç¹ûÉ豸¸´Î»ÇëÇó³öÁË ÎÊÌ⣬ÎÒÃÇÓ¦µ±¸´Î»Õû¸öSCSI×ÜÏß¡£Òò´Ë×îÖÕ³¬Ê±º¯Êý¿´ÆðÀ´ÏñÏÂÃæÑù×Ó£º

static void
xxx_timeout(void *arg)
{
    struct xxx_hcb *hcb = (struct xxx_hcb *)arg;
    struct xxx_softc *softc;
    struct ccb_hdr *ccb_h;

    softc = hcb->softc;
    ccb_h = &hcb->ccb->ccb_h;

    if(hcb->flags & HCB_BEING_ABORTED
    || ccb_h->func_code == XPT_RESET_DEV) {
        xxx_reset_bus(softc);
    } else {
        xxx_abort_ccb(hcb->ccb, CAM_CMD_TIMEOUT);
    }
}

¡¡¡¡µ±ÎÒÃÇÖÐÖ¹Ò»¸öÇëÇóʱ£¬Í¬Ò»Ä¿±ê/LUNµÄËùÓÐÆäËû¶Ï¿ªÁ¬½ÓµÄÇëÇó Ò²»á±»ÖÐÖ¹¡£Òò´Ë³öÏÖÁËÒ»¸öÎÊÌ⣬ÎÒÃÇÓ¦µ±·µ»ØËüÃǵÄ״̬ CAM_REQ_ABORTED»¹ÊÇCAM_CMD_TIMEOUT£¿µ±Ç°µÄÇý¶¯³ÌÐòʹÓà CAM_CMD_TIMEOUT¡£Õâ¿´ÆðÀ´·ûºÏÂß¼­£¬ÒòΪÈç¹ûÒ»¸öÇëÇó³¬Ê±£¬Ôò¿ÉÄÜ É豸³öÏÖÁËijЩµÄÈ·ºÜÔãµÄÊÂÇ飬Òò´ËÈç¹ûËüÃÇûÓб»ÈÅÂÒÔòËüÃÇ×Ô¼º Ó¦µ±³¬Ê±¡£


µÚ13Õ ¡¡USBÉ豸

д×÷£ºNick Hibma. ¸Ä±àΪÊֲ᣺Murray Stokely. ·­Ò룺spellar @SMTH.

13.1 ¼ò½é

¡¡¡¡Í¨Óô®ÐÐ×ÜÏß(USB)Êǽ«É豸Á¬½Óµ½¸öÈ˼ÆËã»úµÄÒ»ÖÖз½·¨¡£×ÜÏß ½á¹¹Í»³öÁËË«ÏòͨÐŵÄÌØÉ«£¬²¢ÇÒÆä¿ª·¢³ä·Ö¿¼Âǵ½ÁËÉ豸ÕýÖð½¥ÖÇÄÜ»¯ ºÍÐèÒªÓëhost½øÐиü¶à½»»¥µÄÏÖʵ¡£¶ÔUSBµÄÖ§³Ö°üº¬ÔÚµ±Ç°ËùÓÐоƬÖÐ, Òò´ËÔÚнüÖÆÔìµÄPCÖж¼¿ÉÓá£Æ»¹û(Apple)ÒýÈë½ö´øUSBµÄiMac¶ÔÓ²¼þ ÖÆÔìÉÌÉú²úËûÃÇUSB°æ±¾µÄÉ豸ÊÇÒ»¸öºÜ´óµÄ¼¤Àø¡£Î´À´µÄPC¹æ·¶Ö¸¶¨ PCÉϵÄËùÓÐÀÏÁ¬½ÓÆ÷Ó¦µ±ÓÉÒ»¸ö»ò¶à¸öUSBÁ¬½ÓÆ÷È¡´ú£¬ÌṩͨÓÃµÄ ¼´²å¼´ÓÃÄÜÁ¦¡£¶ÔUSBÓ²¼þµÄÖ§³ÖÔÚNetBSDµÄÏ൱ÔçÆÚ¾ÍÓÐÁË£¬ËüÊÇÓÉ Lennart AugustssonΪNetBSDÏîÄ¿¿ª·¢µÄ¡£´úÂëÒѾ­±»ÒÆÖ²µ½FreeBSDÉÏ£¬ ÎÒÃÇĿǰά»¤×ÅÒ»¸öµ×²ã¹²Ïí´úÂë¡£¶ÔUSB×ÓϵͳµÄʵÏÖÀ´Ëµ£¬Ðí¶àUSBµÄ ÌØÐÔºÜÖØÒª¡£

¡¡¡¡Lennart AugustssonÒѾ­Íê³ÉÁËNetBSDÏîÄ¿ÖÐUSBÖ§³ÖµÄ ´ó²¿·ÖʵÏÖ¡£Ê®·Ö¸ÐлÕâÏ×÷Á¿¾ªÈ˵Ť×÷¡£Ò²Ê®·Ö¸ÐлArdyºÍDirk ¶Ô±¾ÎĸåµÄÆÀÂÛºÍУ¶Ô¡£

  • É豸ֱ½ÓÁ¬½Óµ½¼ÆËã»úÉϵĶ˿ڣ¬»òÕßÁ¬½Óµ½³ÆÎª ¼¯ÖÐÆ÷µÄÉ豸£¬ÐγÉÊ÷ÐÍÉ豸½á¹¹¡£

  • É豸¿ÉÔÚÔËÐÐʱÁ¬½Ó»ò¶Ï¿ª¡£

  • É豸¿ÉÒÔ¹ÒÆð×ÔÉí²¢´¥·¢hostϵͳµÄÖØÐÂͶÈëÔËÐС£

  • ÓÉÓÚÉ豸¿ÉÓÉ×ÜÏß¹©µç£¬Òò´ËhostÈí¼þ±ØÐë¸ú×Ùÿ¸ö ¼¯ÖÐÆ÷µÄµçÔ´Ô¤Ëã¡£

  • ²»Í¬É豸ÀàÐÍÐèÒª²»Í¬µÄ·þÎñÖÊÁ¿£¬²¢ÇÒͬһ×ÜÏß ¿ÉÒÔÁ¬½Ó×î¶à126¸öÉ豸£¬Õâ¾ÍÐèҪǡµ±µØµ÷¶È×ÜÏßÉϵĴ«ÊäÒÔ³ä·Ö ÀûÓÃ12MbpsµÄ¿ÉÓôø¿í¡££¨USB 2.0³¬¹ý400Mbps£©

  • É豸ÖÇÄÜ»¯²¢°üº¬ºÜÈÝÒ×·ÃÎʵ½µÄ¹ØÓÚ×ÔÉíµÄÐÅÏ¢¡£

¡¡¡¡ÎªUSB×ÓϵͳÒÔ¼°Á¬½Óµ½ËüµÄÉ豸¿ª·¢Çý¶¯³ÌÐòÊÜÒÑ¿ª·¢»ò½«Òª¿ª·¢µÄ ¹æ·¶µÄÖ§³Ö¡£ÕâЩ¹æ·¶¿ÉÒÔ´ÓUSBÖ÷Ò³¹«¿ª»ñµÃ¡£Æ»¹û(Apple)ͨ¹ýʹµÃ ͨÓÃÀàÇý¶¯³ÌÐò¿É´ÓÆä²Ù×÷ϵͳMacOSÖлñµÃ£¬¶øÇÒ²»¹ÄÀøÎªÃ¿ÖÖÐÂÉ豸 ʹÓõ¥¶ÀµÄÇý¶¯³ÌÐòÀ´Ç¿ÁÒÍÆÐлùÓÚ±ê×¼µÄÇý¶¯³ÌÐò¡£±¾ÕÂÊÔͼÕûÀí»ù±¾ ÐÅÏ¢ÒÔ±ã¶ÔFreeBSD/NetBSDÖÐUSBÕ»µÄµ±Ç°ÊµÏÖÓиö»ù±¾µÄÁ˽⡣Ȼ¶ø£¬ ½¨Ò齫ÏÂÃæ²Î¿¼ÖÐÌá¼°µÄÏà¹Ø¹æ·¶Óë±¾ÕÂͬʱÔĶÁ¡£


13.1.1 USBÕ»µÄ½á¹¹

¡¡¡¡FreeBSDÖеÄUSBÖ§³Ö¿É±»·ÖΪÈý²ã¡£×îµ×²ã°üº¬Ö÷¿ØÆ÷£¬ÏòÓ²¼þ ¼°Æäµ÷¶ÈÉèÊ©Ìṩһ¸öͨÓýӿڡ£ËüÖ§³ÖÓ²¼þ³õʼ»¯£¬¶Ô´«Êä½øÐе÷¶È£¬ ´¦ÀíÒÑÍê³É/ʧ°ÜµÄ´«Ê䡣ÿ¸öÖ÷¿ØÆ÷Çý¶¯³ÌÐòʵÏÖÒ»¸öÐéÄâhub£¬ ÒÔÓ²¼þÎ޹ط½Ê½Ìṩ¶Ô¿ØÖÆ»úÆ÷±³Ãæ¸ù¶Ë¿ÚµÄ¼Ä´æÆ÷µÄ·ÃÎÊ¡£

¡¡¡¡Öмä²ã´¦ÀíÉ豸Á¬½ÓºÍ¶Ï¿ª£¬É豸µÄ»ù±¾³õʼ»¯£¬Çý¶¯³ÌÐòµÄÑ¡Ôñ£¬ ͨÐÅͨµÀ£¨¹ÜµÀ£©ºÍ×ÊÔ´¹ÜÀí¡£Õâ¸ö·þÎñ²ãÒ²¿ØÖÆÄ¬ÈϹܵÀºÍÆäÉÏ´«ÊäµÄ É豸ÇëÇó¡£

¡¡¡¡¶¥²ã°üº¬Ö§³ÖÌØ¶¨£¨ÀࣩÉ豸µÄ¸÷¸öÇý¶¯³ÌÐò¡£ÕâЩÇý¶¯³ÌÐòʵÏÖ ³ýĬÈϹܵÀÍâµÄÆäËû¹ÜµÀÉÏʹÓõÄЭÒé¡£ËûÃÇҲʵÏÖ¶îÍ⹦ÄÜ£¬Ê¹µÃÉ豸 ¶ÔÄں˻òÓû§¿Õ¼äÊǿɼûµÄ¡£ËûÃÇʹÓ÷þÎñ²ã±©Â¶³öµÄUSBÇý¶¯³ÌÐò½Ó¿Ú (USBDI)¡£


13.2 Ö÷¿ØÆ÷

¡¡¡¡Ö÷¿ØÆ÷£¨HC£©¿ØÖÆ×ÜÏßÉϰüµÄ´«Ê䡣ʹÓÃ1ºÁÃëµÄÖ¡¡£ÔÚÿ֡¿ªÊ¼ ʱ£¬Ö÷¿ØÆ÷²úÉúÒ»¸öÖ¡¿ªÊ¼£¨SOF, Start of Frame£©°ü¡£

¡¡¡¡SOF°üÓÃÓÚͬ²½Ö¡µÄ¿ªÊ¼ºÍ¸ú×ÙÖ¡µÄÊýÄ¿¡£°üÔÚÖ¡Öб»´«Ê䣬»òÓÉhost µ½É豸£¨out£©£¬»òÓÉÉ豸µ½host£¨in£©¡£´«Êä×ÜÊÇÓÉhost·¢Æð£¨ÂÖѯ´«Ê䣩¡£ Òò´ËÿÌõUSB×ÜÏßÖ»ÄÜÓÐÒ»¸öhost¡£Ã¿¸ö°üµÄ´«Êä¶¼ÓÐÒ»¸ö״̬½×¶Î£¬ Êý¾Ý½ÓÊÕÕß¿ÉÒÔÔÚÆäÖзµ»ØACK£¨Ó¦´ð½ÓÊÕ£©£¬NAK£¨ÖØÊÔ£©£¬STALL£¨´íÎó Ìõ¼þ£©»òʲôҲûÓУ¨»ìÂÒÊý¾Ý½×¶Î£¬É豸²»¿ÉÓûòÒѶϿª£©¡£USB¹æ·¶ USB specificationµÄµÚ8.5½Ú¸üÏêϸµØ½âÊÍÁ˰üµÄϸ½Ú¡£USB×ÜÏß ÉÏ¿ÉÒÔ³öÏÖËÄÖв»Í¬ÀàÐ͵Ĵ«Ê䣺¿ØÖÆ(control)£¬ ´ó¿é(bulk)£¬ ÖÐ¶Ï (interrupt)ºÍͬ²½(isochronous)¡£´«ÊäµÄÀàÐͺÍËûÃǵÄÌØÐÔÔÚÏÂÃæ ÃèÊö£¨`¹ÜµÀ'×Ó½ÚÖУ©¡£

¡¡¡¡USB×ÜÏßÉϵÄÉ豸ºÍÉ豸Çý¶¯³ÌÐò¼äµÄ´óÐÍ´«Êä±»Ö÷¿ØÆ÷»òHC Çý¶¯³ÌÐò·Ö¸îΪ¶à¸ö°ü¡£

¡¡¡¡µ½Ä¬È϶˵ãµÄÉ豸ÇëÇ󣨿ØÖÆ´«Ê䣩ÓÐÐ©ÌØÊâ¡£ËüÃÇÓÉÁ½»òÈý¸ö½×¶Î ×é³É£ºÆô¶¯£¨SETUP£©£¬Êý¾Ý£¨DATA£¬¿ÉÑ¡£©ºÍ״̬£¨STATUS£©¡£ÉèÖã¨set-up£© °ü±»·¢Ë͵½É豸¡£Èç¹û´æÔÚÊý¾Ý½×¶Î£¬Êý¾Ý°üµÄ·½ÏòÔÚÉèÖðüÖиø³ö¡£ ״̬½×¶ÎÖеķ½ÏòÓëÊý¾Ý½×¶ÎÆÚ¼äµÄ·½ÏòÏà·´£¬»òÕßµ±Ã»ÓÐÊý¾Ý½×¶Îʱ ΪIN¡£Ö÷¿ØÆ÷Ó²¼þÒ²Ìṩ¼Ä´æÆ÷£¬ÓÃÓÚ±£´æ¸ù¶Ë¿ÚµÄµ±Ç°×´Ì¬ºÍ×Ô´Ó ×´Ì¬¸Ä±ä¼Ä´æÆ÷×îºóÒ»´Î¸´Î»ÒÔÀ´Ëù·¢ÉúµÄ¸Ä±ä¡£USB¹æ·¶[2]½¨ÒéʹÓÃÒ»¸ö ÐéÄâhubÀ´Ìṩ¶ÔÕâЩ¼Ä´æÆ÷µÄ·ÃÎÊ¡£ÐéÄâhub±ØÐë·ûºÏ¹æ·¶µÚ11ÕÂÖиø³öµÄ hubÉ豸Àà¡£Ëü±ØÐëÌṩһ¸öĬÈϹܵÀʹµÃÉ豸ÇëÇó¿ÉÒÔ·¢Ë͸øËü¡£Ëü·µ»Ø ±ê×¼ºÍhubÀàÌØ¶¨µÄÒ»×éÃèÊö·û¡£ËüÒ²Ó¦µ±Ìṩһ¸öÖжϹܵÀÓÃÀ´±¨¸æÆä ¶Ë¿Ú·¢ÉúµÄ±ä»¯¡£µ±Ç°¿ÉÓõÄÖ÷¿ØÆ÷¹æ·¶ÓÐÁ½¸ö£º ͨÓÃÖ÷¿ØÆ÷½Ó¿Ú£¨UHCI£»Ó¢Ìضû£©ºÍ ¿ª·ÅÖ÷¿ØÆ÷½Ó¿Ú£¨OHCI£»¿µ°Ø£¬Î¢Èí£¬¹ú¼Ò°ëµ¼Ì壩¡£ UHCI¹æ·¶µÄÉè¼ÆÍ¨¹ýÒªÇóÖ÷¿ØÆ÷Çý¶¯³ÌÐòΪÿ֡µÄ´«ÊäÌṩÍêÕûµÄµ÷¶È£¬ ´Ó¶ø¼õÉÙÁËÓ²¼þ¸´ÔÓÐÔ¡£OHCIÀàÐ͵ĿØÖÆÆ÷×ÔÉíÌṩһ¸ö¸ü³éÏóµÄ½Ó¿ÚÀ´ Íê³ÉºÜ¶à¹¤×÷£¬´Ó¶ø¸ü¼Ó¶ÀÁ¢¡£


13.2.1 UHCI

¡¡¡¡UHCIÖ÷¿ØÆ÷ά»¤×Å´øÓÐ1024¸öÖ¸Ïòÿ֡Êý¾Ý½á¹¹µÄÖ¡ÁÐ±í¡£ ËüÀí½âÁ½ÖÖ²»Í¬µÄÊý¾ÝÀàÐÍ£º´«ÊäÃèÊö·û£¨TD£©ºÍ¶ÓÁÐÍ·£¨QH£©¡£Ã¿¸ö TD±íʾ±íʾÓëÉ豸¶Ëµã½øÐÐͨÐŵÄÒ»¸ö°ü¡£QHÊǽ«Ò»Ð©TD£¨ºÍQH£©»®·Ö ³É×éµÄÒ»ÖÖ·½·¨¡£

¡¡¡¡Ã¿¸ö´«ÊäÓÉÒ»¸ö»ò¶à¸ö°ü×é³É¡£UHCIÇý¶¯³ÌÐò½«´óµÄ´«Êä·Ö¸î³É ¶à¸ö°ü¡£³ýͬ²½´«ÊäÍ⣬ÿ¸ö´«Êä¶¼»á·ÖÅäÒ»¸öQH¡£¶ÔÓÚÿÖÖÀàÐ굀 ´«Ê䣬¶¼ÓÐÒ»¸öÓë´ËÀàÐͶÔÓ¦µÄQH£¬ËùÓÐÕâЩQH¶¼»á±»¼¯Öе½Õâ¸öQHÉÏ¡£ ÓÉÓÚÓй̶¨µÄʱÑÓÐèÇó£¬Í¬²½´«Ê䱨ÐëÊ×ÏÈÖ´ÐУ¬ËüÊÇͨ¹ýÖ¡ÁбíÖÐµÄ Ö¸ÕëÖ±½ÓÒýÓõġ£×îºóµÄͬ²½TD´«ÊäÒýÓÃÄÇÒ»Ö¡µÄÖжϴ«ÊäµÄQH¡£ÖÐ¶Ï ´«ÊäµÄËùÓÐQHÖ¸Ïò¿ØÖÆ´«ÊäµÄQH£¬¿ØÖÆ´«ÊäµÄQHÓÖÖ¸Ïò´ó¿é´«ÊäµÄQH¡£ ÏÂÃæµÄͼ±í¸ø³öÁËÒ»¸öͼÐθÅÀÀ£º

¡¡¡¡Õâµ¼ÖÂÏÂÃæµÄµ÷¶È»áÔÚÿ֡ÖÐÔËÐС£¿ØÖÆÆ÷´ÓÖ¡ÁбíÖÐÈ¡µÃµ±Ç°Ö¡ µÄÖ¸Õëºó£¬Ê×ÏÈΪÄÇÒ»Ö¡ÖеÄËùÓеÄͬ²½(isochronous)°üÖ´ÐÐTD¡£ ÕâЩTDµÄ×îºóÒ»¸ö ÒýÓÃÄÇÒ»Ö¡µÄÖжϴ«ÊäµÄQH¡£È»ºóÖ÷¿ØÆ÷½«´ÓÄǸöQHÏÂÐе½¸÷¸ö Öжϴ«ÊäµÄQH¡£Íê³ÉÄÇÒ»¶ÓÁкó£¬Öжϴ«ÊäµÄQH»á½«¿ØÖÆÆ÷Ö¸Ïòµ½ËùÓÐ ¿ØÖÆ´«ÊäµÄQH¡£Ëü½«Ö´ÐÐÔÚÄǶùµÈ´ýµ÷¶ÈµÄËùÓÐ×Ó¶ÓÁУ¬È»ºóÊÇÔÚ´ó¿éQHÖÐ ÅŶӵÄËùÓд«Ê䡣ΪÁË·½±ã´¦ÀíÒÑÍê³É»òʧ°ÜµÄ´«Ê䣬Ӳ¼þ»áÔÚÿ֡ĩβ ²úÉú²»Í¬ÀàÐ͵ÄÖжϡ£ÔÚ´«ÊäµÄ×îºóÒ»¸öTDÖУ¬HCÇý¶¯³ÌÐòÉèÖà Interrupt-On-CompletionλÀ´±ê¼Ç´«ÊäÍê³ÉʱµÄÒ»¸öÖжϡ£Èç¹ûTD´ïµ½ÁË Æä×î´ó´íÎóÊý£¬¾Í±ê¼Ç´íÎóÖжϡ£Èç¹ûÔÚTDÖÐÉèÖö̰üÕì²â룬ÇÒ´«ÊäÁË Ð¡ÓÚËùÉèÖõİü³¤¶È£¨µÄ°ü£©£¬¾Í»á±ê¼Ç´ËÖжÏÒÔ֪ͨ¿ØÖÆÆ÷Çý¶¯³ÌÐò´«Êä ÒÑÍê³É¡£ÕÒ³öÄĸö´«ÊäÒÑÍê³É»ò²úÉú´íÎóÊÇÖ÷¿ØÆ÷Çý¶¯³ÌÐòµÄÈÎÎñ¡£ µ±ÖжϷþÎñÀý³Ì±»µ÷ÓÃʱ£¬Ëü½«¶¨Î»ËùÓÐÒÑÍê³ÉµÄ´«Êä²¢µ÷ÓÃËüÃǵĻص÷¡£

¡¡¡¡¸üÏ꾡µÄÃèÊöÇë¿´ UHCI specification¡£


13.2.2 OHCI

¡¡¡¡¶ÔOHCIÖ÷¿ØÆ÷½øÐбà³ÌÒªÈÝÒ׵öࡣ¿ØÖÆÆ÷¼ÙÉèÓÐÒ»×é¶Ëµã(endpoint)¿ÉÓ㬠²¢ÖªµÀÖ¡Öв»Í¬´«ÊäÀàÐ͵ĵ÷¶ÈÓÅÏȼ¶ºÍÅÅÐò¡£Ö÷¿ØÆ÷ʹÓõÄÖ÷Òª Êý¾Ý½á¹¹ÊǶ˵ãÃèÊö·û£¨ED£©£¬ËüÉÏÃæÁ¬½Ó×ÅÒ»¸ö´«ÊäÃèÊö·û£¨TD£©µÄ¶ÓÁС£ ED°üº¬¶ËµãËùÔÊÐíµÄ×î´óµÄ°ü´óС£¬¿ØÖÆÆ÷Ó²¼þÍê³É°üµÄ·Ö¸î¡£Ã¿´Î´«Êä ºó¶¼»á¸üÐÂÖ¸ÏòÊý¾Ý»º³åÇøµÄÖ¸Õ룬µ±ÆðʼºÍÖÕÖ¹Ö¸ÕëÏàµÈʱ£¬TD¾ÍÍË¹é µ½Íê³É¶ÓÁÐ(done-queue)¡£ËÄÖÖÀàÐ͵Ķ˵ã¸÷ÓÐÆä×Ô¼ºµÄ¶ÓÁС£¿ØÖÆºÍ ´ó¿é(bulk)¶Ëµã·Ö±ðÔÚËüÃÇ×Ô¼ºµÄ¶ÓÁÐÅŶӡ£ÖжÏEDÔÚÊ÷ÖÐÅŶӣ¬ÔÚÊ÷ÖеÄÉî¶È ¶¨ÒåÁËËüÃÇÔËÐÐµÄÆµ¶È¡£

¡¡¡¡Ö¡Áбí ÖÐ¶Ï Í¬²½(isochronous) ¿ØÖÆ ´ó¿é(bulk)

¡¡¡¡Ö÷¿ØÆ÷ÔÚÿ֡ÖÐÔËÐеĵ÷¶È¿´ÆðÀ´ÈçÏ¡£¿ØÖÆÆ÷Ê×ÏÈÔËÐÐ·Ç ÖÜÆÚÐÔ¿ØÖƺʹó¿é¶ÓÁУ¬×¿Éµ½HCÇý¶¯³ÌÐòÉèÖõÄÒ»¸öʱ¼äÏÞÖÆ¡£ È»ºóÒÔÖ¡±àºÅµÍ5λ×÷ΪÖжÏEDÊ÷ÉÏÉî¶ÈΪ0µÄÄÇÒ»²ãÖеÄË÷Òý£¬ÔËÐÐ ÄǸöÖ¡±àºÅµÄÖжϴ«Êä¡£ÔÚÕâ¸öÊ÷µÄĩβ£¬Í¬²½ED±»Á¬½Ó£¬²¢Ëæºó±» ±éÀú¡£Í¬²½TD°üº¬ÁË´«ÊäÓ¦µ±ÔËÐÐÆäÖеĵÚÒ»¸öÖ¡µÄÖ¡±àºÅ¡£ËùÓÐÖÜÆÚ ÐԵĴ«ÊäÔËÐйýÒԺ󣬿ØÖƺʹó¿é¶ÓÁÐÔٴα»±éÀú¡£ÖжϷþÎñÀý³Ì»á±» ÖÜÆÚÐԵص÷Óã¬À´´¦ÀíÍê³ÉµÄ¶ÓÁУ¬ÎªÃ¿¸ö´«Êäµ÷Óûص÷£¬²¢ÖØÐµ÷¶È ÖжϺÍͬ²½¶Ëµã¡£

¡¡¡¡¸üÏ꾡µÄÃèÊöÇë¿´ OHCI specification¡£·þÎñ²ã£¬¼´Öмä²ã£¬ÌṩÁËÒԿɿصķ½Ê½ ¶ÔÉ豸½øÐзÃÎÊ£¬²¢Î¬»¤×ÅÓɲ»Í¬Çý¶¯³ÌÐòºÍ·þÎñ²ãËùʹÓõÄ×ÊÔ´¡£ ´Ë²ã´¦ÀíÏÂÃæ¼¸·½Ã棺

  • É豸ÅäÖÃÐÅÏ¢

  • ÓëÉ豸½øÐÐͨÐŵĹܵÀ

  • ̽²âºÍÁ¬½ÓÉ豸£¬ÒÔ¼°´ÓÉ豸·ÖÀë(detach)¡£


13.3 USBÉ豸ÐÅÏ¢

13.3.1 É豸ÅäÖÃÐÅÏ¢

¡¡¡¡Ã¿¸öÉ豸ÌṩÁ˲»Í¬¼¶±ðµÄÅäÖÃÐÅÏ¢¡£Ã¿¸öÉ豸¾ßÓÐÒ»¸ö»ò¶à¸ö ÅäÖã¬Ì½²â/Á¬½ÓÆÚ¼ä´ÓÆäÖÐÑ¡¶¨Ò»¸ö¡£ÅäÖÃÌṩ¹¦Âʺʹø¿íÒªÇó¡£ Ã¿¸öÅäÖÃÖпÉÒÔÓжà¸ö½Ó¿Ú¡£É豸½Ó¿ÚÊǶ˵ãµÄ»ã¼¯(collection)¡£ ÀýÈ磬USBÑïÉùÆ÷¿ÉÒÔÓÐÒ»¸öÒôƵ½Ó¿Ú£¨ÒôƵÀࣩ£¬ºÍ¶ÔÐýÅ¥(knob)¡¢ ²¦ºÅÅÌ(dial)ºÍ°´Å¥µÄ½Ó¿Ú£¨HIDÀࣩ¡£ Ò»¸öÅäÖÃÖеÄËùÓнӿڿÉÒÔͬʱÓÐЧ£¬²¢¿É±»²»Í¬µÄ Çý¶¯³ÌÐòÁ¬½Ó¡£Ã¿¸ö½Ó¿Ú¿ÉÒÔÓб¸Óýӿڣ¬ÒÔÌṩ²»Í¬ÖÊÁ¿µÄ·þÎñ²ÎÊý¡£ ÀýÈ磬ÔÚÕÕÏà»úÖУ¬ÕâÓÃÀ´Ìṩ²»Í¬µÄÖ¡´óСÒÔ¼°Ã¿ÃëÖ¡Êý¡£

¡¡¡¡Ã¿¸ö½Ó¿ÚÖпÉÒÔÖ¸¶¨0»ò¶à¸ö¶Ëµã¡£¶ËµãÊÇÓëÉ豸½øÐÐͨÐŵĵ¥Ïò ·ÃÎʵ㡣ËüÃÇÌṩ»º³åÇøÀ´ÁÙʱ´æ´¢´ÓÉ豸¶øÀ´µÄ£¬»òÍâ³öµ½É豸µÄÊý¾Ý¡£ ÿ¸ö¶ËµãÔÚÅäÖÃÖÐÓÐΨһµØÖ·£¬¼´¶ËµãºÅ¼ÓÉÏÆä·½Ïò¡£Ä¬È϶˵㣬¼´ ¶Ëµã0£¬²»ÊÇÈκνӿڵÄÒ»²¿·Ö£¬²¢ÇÒÔÚËùÓÐÅäÖÃÖпÉÓá£ËüÓÉ·þÎñ²ã ¹ÜÀí£¬²¢ÇÒÉ豸Çý¶¯³ÌÐò²»ÄÜÖ±½ÓʹÓá£

¡¡¡¡Level 0 Level 1 Level 2 Slot 0

¡¡¡¡Slot 3 Slot 2 Slot 1

¡¡¡¡(Ö»ÏÔʾÁË32¸ö²ÛÖеÄ4¸ö)

¡¡¡¡ÕâÖÖ²ã´Î»¯ÅäÖÃÐÅÏ¢ÔÚÉ豸ÖÐͨ¹ý±ê×¼µÄÒ»×éÃèÊö·ûÀ´ÃèÊö£¨²Î¿´ USB¹æ·¶[2]µÚ9.6½Ú£©¡£ËüÃÇ¿ÉÒÔͨ¹ýGet Descriptor RequestÀ´ÇëÇó¡£ ·þÎñ²ã»º´æÕâЩÃèÊö·ûÒÔ±ÜÃâÔÚUSB×ÜÏßÉϽøÐв»±ØÒªµÄ´«Êä¡£¶ÔÕâЩ ÃèÊö·ûµÄ·ÃÎÊÊÇͨ¹ýº¯Êýµ÷ÓÃÀ´ÌṩµÄ¡£

  • É豸ÃèÊö·û£º¹ØÓÚÉ豸µÄͨÓÃÐÅÏ¢£¬È繩ӦÉÌ£¬²úÆ· ºÍÐÞ¶©ID£¬Ö§³ÖµÄÉ豸Àà¡¢×ÓÀàºÍÊÊÓõÄЭÒ飬ĬÈ϶˵ãµÄ×î´ó°ü´óС µÈ¡£

  • ÅäÖÃÃèÊö·û£º´ËÅäÖÃÖеĽӿÚÊý£¬Ö§³ÖµÄ¹ÒÆðºÍ »Ö¸´ÄÜÁ¦£¬ÒÔ¼°¹¦ÂÊÒªÇó¡£

  • ½Ó¿ÚÃèÊö·û£º½Ó¿ÚÀà¡¢×ÓÀàºÍÊÊÓõÄЭÒ飬½Ó¿Ú±¸Óà ÅäÖõÄÊýÄ¿ºÍ¶ËµãÊýÄ¿¡£

  • ¶ËµãÃèÊö·û£º¶ËµãµØÖ·¡¢·½ÏòºÍÀàÐÍ£¬Ö§³ÖµÄ×î´ó°ü ´óС£¬Èç¹ûÊÇÖжÏÀàÐ͵Ķ˵ãÔò»¹°üÀ¨ÂÖѯƵÂÊ¡£Ä¬È϶˵㣨¶Ëµã0£© ûÓÐÃèÊö·û£¬¶øÇÒ´Ó²»±»¼ÆÈë½Ó¿ÚÃèÊö·ûÖС£

  • ×Ö·û´®ÃèÊö·û£ºÔÚÆäËûÃèÊö·ûÖлáΪijЩ×Ö¶ÎÌṩ ×Ö·û´®Ë÷Òý¡£ËüÃǿɱ»ÓÃÀ´¼ìÈ¡ÃèÊöÐÔ×Ö·û´®£¬¿ÉÄÜÒÔ¶àÖÖÓïÑÔ µÄÐÎʽÌṩ¡£

¡¡¡¡Àà˵Ã÷(specification)¿ÉÒÔÌí¼ÓËüÃÇ×Ô¼ºµÄÃèÊö·ûÀàÐÍ£¬ÕâЩÃèÊö·û Ò²¿ÉÒÔͨ¹ýGetDescriptor RequestÀ´»ñµÃ¡£

¡¡¡¡¹ÜµÀÓëÉ豸É϶˵ãµÄͨÐÅ£¬Á÷¾­ËùνµÄ¹ÜµÀ¡£Çý¶¯³ÌÐò½«µ½¶ËµãµÄ ´«ÊäÌá½»µ½¹ÜµÀ£¬²¢Ìṩ´«Ê䣨Òì²½´«Ê䣩ʧ°Ü»òÍê³Éʱµ÷ÓõĻص÷£¬ »òµÈ´ýÍê³É£¨Í¬²½´«Ê䣩¡£µ½¶ËµãµÄ´«ÊäÔڹܵÀÖб»´®Ðл¯¡£´«Êä»òÕßÍê³É£¬ »òÕßʧ°Ü£¬»òÕß³¬Ê±£¨Èç¹ûÉèÖÃÁ˳¬Ê±£©¡£¶ÔÓÚ´«ÊäÓÐÁ½ÖÖÀàÐ͵ij¬Ê±¡£ ³¬Ê±µÄ·¢Éú¿ÉÄÜÓÉÓÚUSB×ÜÏßÉϵij¬Ê±£¨ºÁÃ룩¡£ÕâЩ³¬Ê±±»ÊÓΪʧ°Ü£¬ ¿ÉÄÜÊÇÓÉÓÚÉ豸¶Ï¿ªÁ¬½ÓÒýÆðµÄ¡£ÁíÒ»ÖÖ³¬Ê±ÔÚÈí¼þÖÐʵÏÖ£¬µ±´«ÊäûÓÐ ÔÚÖ¸¶¨µÄʱ¼ä£¨Ã룩ÄÚÍê³Éʱ´¥·¢¡£ÕâÊÇÓÉÓÚÉ豸¶Ô´«ÊäµÄ°ü·ñ¶¨Ó¦´ðÒýÆðµÄ¡£ ÆäÔ­ÒòÊÇÓÉÓÚÉ豸»¹Ã»ÓÐ×¼±¸ºÃ½ÓÊÕÊý¾Ý£¬»º³åÇøÇ·ÔØ»ò³¬ÔØ£¬»òЭÒé´íÎó¡£

¡¡¡¡Èç¹û¹ÜµÀÉϵĴ«Êä´óÓÚ¹ØÁªµÄ¶ËµãÃèÊö·ûÖÐÖ¸¶¨µÄ×î´ó°ü´óС£¬Ö÷ ¿ØÆ÷£¨OHCI£©»òHCÇý¶¯³ÌÐò£¨UHCI£©½«°´×î´ó°ü´óС·Ö¸î´«Ê䣬²¢ÇÒ×îºó Ò»¸ö°ü¿ÉÄÜСÓÚ×î´ó°üµÄ´óС¡£

¡¡¡¡ÓÐʱºò¶ÔÉ豸À´Ëµ·µ»ØÉÙÓÚËùÇëÇóµÄÊý¾Ý²¢²»ÊǸöÎÊÌâ¡£ÀýÈ磬 µ½µ÷ÖÆ½âµ÷Æ÷µÄ´ó¿éin´«Êä¿ÉÄÜÇëÇó200×Ö½ÚµÄÊý¾Ý£¬µ«µ÷ÖÆ½âµ÷Æ÷ ÄÇʱֻÓÐ5¸ö×Ö½Ú¿ÉÓá£Çý¶¯³ÌÐò¿ÉÒÔÉèÖö̰ü(SPD)±êÖ¾¡£ËüÔÊÐíÖ÷ ¿ØÆ÷¼´Ê¹ÔÚ´«ÊäµÄÊý¾ÝÁ¿ÉÙÓÚËùÇëÇóµÄÊý¾ÝÁ¿µÄÇé¿öÏÂÒ²½ÓÊܰü¡£ Õâ¸ö±êÖ¾Ö»ÔÚin´«ÊäÖÐÓÐЧ£¬ÒòΪ½«Òª±»·¢Ë͵½É豸µÄÊý¾ÝÁ¿×ÜÊÇÊÂÏÈ ÖªµÀµÄ¡£Èç¹û´«Êä¹ý³ÌÖÐÉ豸³öÏÖ²»¿É»Ö¸´µÄ´íÎ󣬹ܵÀ»á±»Í£¶Ù¡£ ½ÓÊÜ»ò·¢Ë͸ü¶àÊý¾ÝÒÔǰ£¬Çý¶¯³ÌÐòÐèҪȷ¶¨Í£¶ÙµÄÔ­Òò£¬²¢Í¨¹ýÔÚ Ä¬ÈϹܵÀÉÏ·¢ËÍÇå³ý¶Ëµã¹ÒÆðÉ豸ÇëÇó(clear endpoint halt device request)À´Çå³ý¶ËµãÍ£¶ÙÌõ¼þ¡£

¡¡¡¡ÓÐËÄÖÖ²»Í¬ÀàÐ͵Ķ˵ãºÍ¶ÔÓ¦µÄ¹ÜµÀ£º -

  • ¿ØÖƹܵÀ/ĬÈϹܵÀ£º ÿ¸öÉ豸ÓÐÒ»¸ö¿ØÖƹܵÀ£¬Á¬½Óµ½Ä¬È϶˵㣨¶Ëµã0£©¡£´Ë¹ÜµÀÔËÔØÉ豸 ÇëÇóºÍ¹ØÁªµÄÊý¾Ý¡£Ä¬ÈϹܵÀºÍÆäËû¹ÜµÀÉϵĴ«ÊäµÄÇø±ðÔÚÓÚ´«ÊäËù ʹÓõÄЭÒ飬ЭÒéÔÚUSB¹æ·¶[2]ÖÐÃèÊö¡£ÕâЩÇëÇóÓÃÓÚ¸´Î»ºÍÅäÖÃÉ豸¡£ ÿ¸öÉ豸±ØÐëÖ§³ÖUSB¹æ·¶[2]µÄµÚ9ÕÂÖÐÌṩµÄÒ»×é»ù±¾ÃüÁî¡£¹ÜµÀÉÏ Ö§³ÖµÄÃüÁî¿ÉÒÔͨ¹ýÉ豸Àà¹æ·¶À©Õ¹£¬ÒÔÖ§³Ö¶îÍâµÄ¹¦ÄÜ¡£

  • ´ó¿é(bulk)¹ÜµÀ£ºÕâÊÇUSBÓëԭʼ´«ÊäýÌå¶ÔÓ¦µÄµÈ¼ÛÎï¡£

  • ÖжϹܵÀ£ºhostÏòÉ豸·¢ËÍÊý¾ÝÇëÇó£¬Èç¹ûÉ豸ûÓÐ ¶«Î÷·¢ËÍ£¬Ôò½«NAK£¨·ñ¶¨Ó¦´ð£©Êý¾Ý°ü¡£Öжϴ«Êä°´´´½¨¹ÜµÀʱָ¶¨µÄ ƵÂʱ»µ÷¶È¡£

  • ͬ²½¹ÜµÀ£ºÕâЩ¹ÜµÀÓÃÓÚ¾ßÓй̶¨Ê±ÑÓµÄͬ²½Êý¾Ý£¬ ÀýÈçÊÓÆµ»òÒôƵÁ÷£¬µ«²»±£Ö¤Ò»¶¨´«Êä¡£µ±Ç°ÊµÏÖÖÐÒѾ­ÓжÔÕâÖÖÀàÐÍ ¹ÜµÀµÄijЩ֧³Ö¡£µ±´«ÊäÆÚ¼ä³öÏÖ´íÎ󣬻òÕßÓÉÓÚ£¬ÀýÈçȱ·¦»º³åÇø¿Õ¼ä À´´æ´¢½øÈëµÄÊý¾Ý¶øÒýÆðµÄÉ豸·ñ¶¨Ó¦´ð°ü£¨NAK£©Ê±£¬¿ØÖÆ¡¢´ó¿éºÍÖÐ¶Ï ¹ÜµÀÖеİü»á±»ÖØÊÔ¡£¶øÍ¬²½°üÔÚ´«µÝʧ°Ü»ò¶Ô°üNAKʱ²»»áÖØÊÔ£¬ÒòΪ ÄÇÑù¿ÉÄÜÎ¥·´Í¬²½Ô¼Êø¡£

¡¡¡¡ËùÐè´ø¿íµÄ¿ÉÓÃÐÔÔڹܵÀµÄ´´½¨ÆÚ¼ä±»¼ÆËã¡£´«ÊäÔÚ1ºÁÃëµÄÖ¡ÄÚ ½øÐе÷¶È¡£Ö¡ÖеĴø¿í·ÖÅäÓÉUSB¹æ·¶µÄµÚ5.6½Ú¹æ¶¨¡£Í¬²½ºÍÖжϴ«Êä±» ÔÊÐíÏûºÄÖ¡Öжà´ï90%µÄ´ø¿í¡£¿ØÖƺʹó¿é´«ÊäµÄ°üÔÚËùÓÐͬ²½ºÍÖжϰü Ö®ºó½øÐе÷¶È£¬²¢½«ÏûºÄËùÓÐÊ£Óà´ø¿í¡£

¡¡¡¡¹ØÓÚ´«Êäµ÷¶ÈºÍ´ø¿í»ØÊյĸü¶àÐÅÏ¢¿ÉÒÔÔÚUSB¹æ·¶[2]µÄµÚ5Õ£¬ UHCI¹æ·¶[3]µÄµÄµÚ1.3½Ú£¬OHCI¹æ·¶[4]µÄ3.4.2½ÚÖÐÕÒµ½¡£


13.4 É豸µÄ̽²âºÍÁ¬½Ó

¡¡¡¡¼¯ÖÐÆ÷(hub)֪ͨÐÂÉ豸ÒÑÁ¬½Óºó£¬·þÎñ²ã¸ø¶Ë¿Ú¼Óµç(switch on)£¬ ΪÉ豸Ìṩ100mAµÄµçÁ÷¡£ ´ËʱÉ豸´¦ÓÚÆäĬÈÏ״̬£¬²¢¼àÌýÉ豸µØÖ·0¡£·þÎñ²ã»áͨ¹ýĬÈÏ ¹ÜµÀ¼ÌÐø¼ìÈ¡¸÷ÖÖÃèÊö·û¡£´ËºóËü½«ÏòÉ豸·¢ËÍSet AddressÇëÇ󣬽«É豸 ´ÓĬÈÏÉ豸µØÖ·(µØÖ·0)ÒÆ¿ª¡£¿ÉÄÜÓжà¸öÉ豸Çý¶¯³ÌÐòÖ§³Ö´ËÉ豸¡£ÀýÈ磬 Ò»¸öµ÷ÖÆ½âµ÷Æ÷¿ÉÄÜͨ¹ýAT¼æÈݽӿÚÖ§³ÖISDN TA¡£È»¶ø£¬Ìض¨ÐͺŵÄISDN ÊÊÅäÆ÷µÄÇý¶¯³ÌÐò¿ÉÄÜÌṩ¶Ô´ËÉ豸µÄ¸üºÃÖ§³Ö¡£ÎªÁËÖ§³ÖÕâÑùµÄÁé»îÐÔ£¬ ̽²â»á·µ»ØÓÅÏȼ¶£¬Ö¸Ê¾ËûÃǵÄÖ§³Ö¼¶±ð¡£Ö§³Ö²úÆ·µÄÌØ¶¨°æ±¾»á¾ßÓÐ×î¸ß ÓÅÏȼ¶£¬Í¨ÓÃÇý¶¯³ÌÐò¾ßÓÐ×îµÍÓÅÏȼ¶¡£Èç¹ûÒ»¸öÅäÖÃÄÚÓжà¸ö½Ó¿Ú£¬Ò²¿ÉÄÜ ¶à¸öÇý¶¯³ÌÐò»áÁ¬½Óµ½Ò»¸öÉ豸¡£Ã¿¸öÇý¶¯³ÌÐòÖ»ÐèÖ§³ÖËùÓнӿڵÄÒ»¸ö×Ó¼¯¡£

¡¡¡¡ÎªÐÂÁ¬½ÓµÄÉ豸̽²âÇý¶¯³ÌÐòʱ£¬Ê×ÏÈ̽²âÉè±¸ÌØ¶¨µÄÇý¶¯³ÌÐò¡£ Èç¹ûûÓз¢ÏÖ£¬Ôò̽²â´úÂëÔÚËùÓÐÖ§³ÖµÄÅäÖÃÉÏÖØ¸´Ì½²â¹ý³Ì£¬Ö±µ½ ÔÚÒ»¸öÅäÖÃÖÐÁ¬½Óµ½Ò»¸öÇý¶¯³ÌÐò¡£ÎªÁËÖ§³Ö²»Í¬½Ó¿ÚÉÏʹÓöà¸öÇý¶¯ ³ÌÐòµÄÉ豸£¬Ì½²â»áÔÚÒ»¸öÅäÖÃÖеÄËùÓÐÉÐδ±»Çý¶¯³ÌÐòÉùÃ÷(claim)µÄ ½Ó¿ÚÉÏÖØ¸´½øÐС£³¬³ö¼¯ÖÐÆ÷¹¦ÂÊÔ¤ËãµÄÅäÖûᱻºöÂÔ¡£Á¬½ÓÆÚ¼ä£¬Çý¶¯ ³ÌÐòÓ¦µ±°ÑÉ豸³õʼ»¯µ½Êʵ±×´Ì¬£¬µ«²»Äܸ´Î»£¬ÒòΪÄÇÑù»áʹµÃÉ豸½« Ëü×Ô¼º´Ó×ÜÏßÉ϶Ͽª£¬²¢ÖØÐÂÆô¶¯Ì½²â¹ý³Ì¡£ÎªÁ˱ÜÃâÏûºÄ²»±ØÒªµÄ´ø¿í£¬ ²»Ó¦µ±ÔÚÁ¬½ÓʱÉùÃ÷ÖжϹܵÀ£¬¶øÓ¦µ±ÑÓ³Ù·ÖÅä¹ÜµÀ£¬Ö±µ½´ò¿ªÎļþ²¢ÕæµÄ ʹÓÃÊý¾Ý¡£µ±¹Ø±ÕÎļþʱ£¬¹ÜµÀÒ²Ó¦µ±±»Ôٴιرգ¬¾¡¹ÜÉ豸¿ÉÄÜÈÔÈ» Á¬½Ó×Å¡£


13.4.1 É豸¶Ï¿ªÁ¬½Ó(disconnect)ºÍ·ÖÀë(detach)

¡¡¡¡É豸Çý¶¯³ÌÐòÓëÉ豸½øÐÐÈκÎÊÂÎñÆÚ¼ä£¬Ó¦µ±Ô¤ÆÚ»á½ÓÊÕµ½´íÎó¡£ USBµÄÉè¼ÆÖ§³Ö²¢¹ÄÀøÉ豸ÔÚÈκε㼰ʱ¶Ï¿ªÁ¬½Ó¡£Çý¶¯³ÌÐòÓ¦µ±È·±£ µ±É豸²»ÔÚʱ×öÕýÈ·µÄÊÂÇé¡£

¡¡¡¡´ËÍ⣬¶Ï¿ªÁ¬½Ó(disconnect)ºóÓÖÖØÐÂÁ¬½Ó(reconnect)µÄÉ豸²»»á ±»ÖØÐÂÁ¬½Ó(reattach)ΪÏàͬµÄÉ豸ʵÀý¡£ ½«À´µ±¸ü¶àµÄÉ豸֧³ÖÐòÁкţ¨²Î¿´É豸ÃèÊö·û£©£¬ »ò¿ª·¢³öÆäËû¶¨ÒåÉ豸±êʶµÄ·½·¨µÄʱºò£¬ÕâÖÖÇé¿ö¿ÉÄÜ»á¸Ä±ä¡£

¡¡¡¡É豸¶Ï¿ªÁ¬½ÓÊÇÓɼ¯ÖÐÆ÷ÔÚ´«µÝµ½¼¯ÖÐÆ÷Çý¶¯³ÌÐòµÄÖжϰüÖз¢ ÐźÅ֪ͨ(signal)µÄ¡£×´Ì¬¸Ä±äÐÅϢָʾÄĸö¶Ë¿Ú·¢ÏÖÁËÁ¬½Ó¸Ä±ä¡£ Á¬½Óµ½ÄǸö¶Ë¿ÚÉϵÄÉ豸µÄËùÓÐÉ豸Çý¶¯³ÌÐò¹²ÓõÄÉ豸·ÖÀë·½·¨±»µ÷Ó㬠½á¹¹±»³¹µ×ÇåÀí¡£Èç¹û¶Ë¿Ú״ָ̬ʾͬʱһ¸öÉ豸ÒѾ­Á¬½Ó(connect)µ½ÄǸö ¶Ë¿Ú£¬Ôò̽²âºÍÁ¬½ÓÉ豸µÄ¹ý³Ì½«±»Æô¶¯¡£É豸¸´Î»½«ÔÚ¼¯ÖÐÆ÷ÉϲúÉú Ò»¸ö¶Ï¿ª-Á¬½ÓÐòÁУ¬²¢½«°´ÉÏÃæËùÊö½øÐд¦Àí¡£


13.5 USBÇý¶¯³ÌÐòµÄЭÒéÐÅÏ¢

¡¡¡¡USB¹æ·¶Ã»Óж¨Òå³ýĬÈϹܵÀÍâÆäËû¹ÜµÀÉÏʹÓõÄЭÒé¡£Õâ·½ÃæµÄÐÅÏ¢ ¿ÉÒÔ´Ó¸÷ÖÖÀ´Ô´»ñµÃ¡£×î׼ȷµÄÀ´Ô´ÊÇUSBÖ÷Ò³[1]ÉϵĿª·¢Õß²¿·Ö¡£´ÓÕâЩ Ò³ÃæÉÏ¿ÉÒԵõ½ÊýÄ¿²»¶ÏÔö³¤µÄÉ豸ÀàµÄ¹æ·¶¡£ÕâЩ¹æ·¶Ö¸¶¨´ÓÇý¶¯³ÌÐò ½Ç¶È¿´ÆðÀ´¼æÈÝÉ豸Ӧµ±ÔõÑù£¬ËüÐèÒªÌṩµÄ»ù±¾¹¦ÄܺÍͨÐÅͨµÀÉÏʹÓÃµÄ Ð­Òé¡£USB¹æ·¶[2]°üÀ¨Á˼¯ÖÐÆ÷ÀàµÄÃèÊö¡£ÈË»ú½çÃæÉ豸(HID)µÄÀà¹æ·¶ÒѾ­ ´´½¨³öÀ´£¬ÒÔÓ­ºÏ¶Ô¼üÅÌ¡¢Êý×ÖÊäÈë°å¡¢ÌõÐÎÂëÔĶÁÆ÷¡¢°´Å¥¡¢ÐýÅ¥(ÊÖ±úknob)¡¢ ¿ª¹ØµÈµÄÒªÇó¡£ÁíÒ»¸öÀý×ÓÊÇÓÃÓÚ´óÈÝÁ¿´æ´¢É豸µÄÀà¹æ·¶¡£É豸ÀàµÄÍêÕûÁÐ±í ²Î¿´USBÖ÷Ò³[1]µÄ¿ª·¢Õß²¿·Ö¡£

¡¡¡¡È»¶ø, Ðí¶àÉ豸µÄЭÒéÐÅÏ¢»¹Ã»Óб»¹«²¼¡£¹ØÓÚËùÓÃЭÒéµÄÐÅÏ¢ ¿ÉÄÜ¿ÉÒÔ´ÓÖÆÔìÉ豸µÄ¹«Ë¾»ñµÃ¡£Ò»Ð©¹«Ë¾»áÔÚ¸øÄã¹æ·¶Ö®Ç°ÒªÇóÄãÇ©Êð ±£ÃÜЭÒé(Non-Disclosure Agreement, NDA)¡£´ó¶àÊýÇé¿öÏ£¬Õâ»á×èÖ¹ ½«Çý¶¯³ÌÐò¿ª·ÅÔ´´úÂë¡£

¡¡¡¡ÁíÒ»¸öÐÅÏ¢µÄºÜºÃÀ´Ô´ÊÇLinuxÇý¶¯³ÌÐòÔ´´úÂ룬ÒòΪºÜ¶à¹«Ë¾ÒѾ­ ¿ªÊ¼ÎªËûÃǵÄÉ豸ÌṩLinuxϵÄÇý¶¯³ÌÐò¡£ÁªÏµÄÇЩÇý¶¯³ÌÐò×÷ÕßѯÎÊ ËûÃǵÄÐÅÏ¢À´Ô´×ÜÊÇÒ»¸öºÃÖ÷Òâ¡£

¡¡¡¡Àý×Ó£ºÈË»ú½çÃæÉ豸¡£ÈË»ú½çÃæÉ豸£¬Èç¼üÅÌ¡¢Êó±ê¡¢Êý×ÖÊäÈë°å¡¢ °´Å¥¡¢²¦ºÅÅ̵ȵĹ淶±»ÆäËûÉ豸Àà¹æ·¶ÒýÓ㬲¢ÔںܶàÉ豸ÖÐʹÓá£

¡¡¡¡ÀýÈ磬ÒôƵÑïÉùÆ÷Ìṩµ½Êýģת»»Æ÷µÄ¶Ëµã£¬¿ÉÄÜ»¹Ìṩ¶îÍâ¹ÜµÀ ÓÃÓÚÂó¿Ë·ç¡£ËüÃÇҲΪÉè±¸Ç°ÃæµÄ°´Å¥ºÍ²¦ºÅÅÌÔÚµ¥¶ÀµÄ½Ó¿ÚÖÐÌṩHID ¶Ëµã¡£¼àÊÓÆ÷¿ØÖÆÀàÒ²ÊÇÈç´Ë¡£Í¨¹ý¿ÉÓõÄÄں˺ÍÓû§¿Õ¼äµÄ¿â£¬ÓëHID ÀàÇý¶¯³ÌÐò»òͨÓÃÇý¶¯³ÌÐòÒ»Æð¿ÉÒÔ¼òµ¥Ö±½ÓµØ´´½¨¶ÔÕâЩ½Ó¿ÚµÄÖ§³Ö¡£ ÁíÒ»¸öÉ豸¿ÉÒÔ×÷ΪÔÚÒ»¸öÅäÖÃÖеĶà¸ö½Ó¿ÚÓɲ»Í¬µÄÉ豸Çý¶¯³ÌÐòÇý¶¯ µÄÀý×Ó£¬Õâ¸öÉ豸ÊÇÒ»ÖÖ±ãÒ˵ļüÅÌ£¬´øÓÐÀϵÄÊó±ê½Ó¿Ú¡£ÎªÁ˱ÜÃâÔÚ É豸ÖÐΪUSB¼¯ÖÐÆ÷°üÀ¨Ò»¸öÓ²¼þ¶øµ¼Öµijɱ¾ÉÏÉý£¬ÖÆÔìÉ̽«´Ó¼üÅ̱³ÃæµÄ PS/2¶Ë¿Ú½ÓÊÕµ½µÄÊó±êÊý¾ÝÓëÀ´×Ô¼üÅ̵İ´¼ü×éºÏ³ÉÔÚͬһ¸öÅäÖÃÖÐµÄ Á½¸öµ¥¶ÀµÄ½Ó¿Ú¡£Êó±êºÍ¼üÅÌÇý¶¯³ÌÐò¸÷×ÔÁ¬½Óµ½Êʵ±µÄ½Ó¿Ú£¬²¢·ÖÅäµ½ Á½¸ö¶ÀÁ¢¶ËµãµÄ¹ÜµÀ.

¡¡¡¡Àý×Ó£º¹Ì¼þÏÂÔØ¡£ÒѾ­¿ª·¢³öÀ´µÄÐí¶àÉ豸ÊÇ»ùÓÚͨÓÃÄ¿µÄ´¦ÀíÆ÷£¬ ²¢½«¶îÍâµÄUSBºËÐļÓÈëÆäÖС£ÓÉÓÚÇý¶¯³ÌÐòµÄ¿ª·¢ºÍUSBÉ豸µÄ¹Ì¼þÈÔÈ» ·Ç³£Ð£¬Ðí¶àÉ豸ÐèÒªÔÚÁ¬½Ó(connect)Ö®ºóÏÂÔØ¹Ì¼þ¡£

¡¡¡¡ÏÂÃæµÄ²½Öè·Ç³£¼òÃ÷Ö±½Ó¡£É豸ͨ¹ý¹©Ó¦É̺ͲúÆ·ID±êʶ×ÔÉí¡£µÚÒ» ¸öÇý¶¯³ÌÐò̽²â²¢Á¬½Óµ½Ëü£¬²¢½«¹Ì¼þÏÂÔØµ½ÆäÖС£´ËºóÉ豸×Ô¼ºÈí¸´Î»£¬ Çý¶¯³ÌÐò·ÖÀë¡£¶ÌÔݵÄÔÝÍ£Ö®ºóÉ豸Ðû²¼ËüÔÚ×ÜÏßÉϵĴæÔÚ¡£É豸½«¸Ä±ä Æä¹©Ó¦ÉÌ/²úÆ·/°æ±¾µÄIDÒÔ·´Ó³ÆäÌṩÓй̼þµÄÊÂʵ£¬Òò´ËÁíÒ»¸öÇý¶¯³ÌÐò ½«Ì½²âËü²¢Á¬½Ó(attach)µ½Ëü¡£

¡¡¡¡ÕâЩÀàÐ͵ÄÉ豸µÄÒ»¸öÀý×ÓÊÇ»ùÓÚEZ-USBµÄActiveWire I/O°å¡£Õâ¸ö оƬÓÐÒ»¸öͨÓù̼þÏÂÔØÆ÷¡£ÏÂÔØµ½ActiveWire°å×ÓÉϵĹ̼þ¸Ä±ä°æ±¾ID¡£ È»ºóËü½«Ö´ÐÐEZ-USBоƬµÄUSB²¿·ÖµÄÈí¸´Î»£¬´ÓUSB×ÜÏßÉ϶Ͽª£¬²¢ÔÙ´Î ÖØÐÂÁ¬½Ó¡£

¡¡¡¡Àý×Ó£º´óÈÝÁ¿´æ´¢É豸¡£¶Ô´óÈÝÁ¿´æ´¢É豸µÄÖ§³ÖÖ÷ÒªÎ§ÈÆÏÖÓÐµÄ Ð­Òé¹¹½¨¡£Iomega USB ZipÇý¶¯Æ÷ÊÇ»ùÓÚSCSI°æ±¾µÄÇý¶¯Æ÷¡£SCSIÃüÁîºÍ ״̬ÐÅÏ¢±»°ü×°µ½¿éÖУ¬ÔÚ´ó¿é(bulk)¹ÜµÀÉÏ´«Êäµ½/À´×ÔÉ豸£¬ÔÚUSBÏß ÉÏÄ£ÄâSCSI¿ØÖÆÆ÷¡£ATAPIºÍUFIÃüÁîÒÔÏàËÆµÄ·½Ê½±»Ö§³Ö¡£

¡¡¡¡´óÈÝÁ¿´æ´¢¹æ·¶Ö§³ÖÁ½ÖÖ²»Í¬ÀàÐ͵ĶÔÃüÁî¿éµÄ°ü×°¡£×î³õµÄ³¢ÊÔ »ùÓÚͨ¹ýĬÈϹܵÀ·¢ËÍÃüÁîºÍ״̬ÐÅÏ¢£¬Ê¹Óôó¿é´«ÊäÔÚhostºÍÉ豸֮¼ä ÒÆ¶¯Êý¾Ý¡£ÔÚ¾­Ñé»ù´¡ÉÏÉè¼Æ³öÁíÒ»ÖÖ·½·¨£¬ÕâÖÖ·½·¨»ùÓÚ°ü×°ÃüÁîºÍ ״̬¿é£¬²¢ÔÚ´ó¿éoutºÍin¶ËµãÉÏ·¢ËÍËüÃÇ¡£¹æ·¶¾«È·µØÖ¸¶¨Á˺Îʱ±ØÐë ·¢Éúʲô£¬ÒÔ¼°ÔÚÅöµ½´íÎóÌõ¼þµÄÇé¿öÏÂÓ¦¸Ã×öʲô¡£ÎªÕâЩÉ豸±àд Çý¶¯³ÌÐòµÄ×î´óÌôÕ½ÊÇЭµ÷»ùÓÚUSBµÄЭÒ飬ÈÃËüÊʺÏÒÑÓеĶԴóÈÝÁ¿´æ´¢É豸 µÄÖ§³Ö¡£CAMÌṩÁ˹³×Ó£¬ÒÔÏ൱ֱ½ÓÁ˵±µÄ·½Ê½À´Íê³ÉÕâ¸ö¡£ATAPI¾Í ûÓÐÕâô¼òµ¥ÁË£¬ÒòΪÀúÊ·ÉÏIDE½Ó¿Ú´ÓδÓйý¶àÖÖ²»Í¬µÄ±íÏÖ·½Ê½¡£

¡¡¡¡À´×ÔY-E DataµÄ¶ÔUSBÈíÅ̵ÄÖ§³ÖÒ²²»ÊÇÄÇôֱ¹Û£¬ÒòΪÉè¼ÆÁËÒ»Ì× ÐµÄÃüÁ¡£


µÚ14ÕÂ ¡¡Newbus

д×÷£ºJeroen Ruigrok van der Werven (asmodai) ºÍ Hiten Pandya. ·­Ò룺spellar @SMTH.

¡¡¡¡Ìرð¸ÐлMatthew N. Dodd, Warner Losh, Bill Paul, Doug Rabson, Mike Smith, Peter Wemm and Scott Long.

¡¡¡¡±¾ÕÂÏêϸ½âÊÍÁËNewbusÉ豸¿ò¼Ü¡£


14.1 É豸Çý¶¯³ÌÐò

14.1.1 É豸Çý¶¯³ÌÐòµÄÄ¿µÄ

¡¡¡¡É豸Çý¶¯³ÌÐòÊÇÈí¼þ×é¼þ£¬ËüÔÚÄں˹ØÓÚÍâΧÉ豸£¨ÀýÈ磬´ÅÅÌ¡¢ÍøÂç ÊÊÅ俨£©µÄͨÓÃÊÓͼºÍÍâΧÉ豸µÄʵ¼ÊʵÏÖÖ®¼äÌṩÁ˽ӿڡ£ É豸Çý¶¯³ÌÐò½Ó¿Ú(DDI)ÊÇÄÚºËÓëÉ豸Çý¶¯³ÌÐò×é¼þ Ö®¼ä¶¨ÒåµÄ½Ó¿Ú¡£


14.1.2 É豸Çý¶¯³ÌÐòµÄÀàÐÍ

¡¡¡¡ÔÚUNIXÄǸöʱ´ú£¬FreeBSDÒ²´ÓÖÐÑÓÐø¶øÀ´£¬¶¨ÒåÁËËÄÖÖÀàÐ굀 É豸£º

  • ¿éÉ豸Çý¶¯³ÌÐò

  • ×Ö·ûÉ豸Çý¶¯³ÌÐò

  • ÍøÂçÉ豸Çý¶¯³ÌÐò

  • αÉ豸Çý¶¯³ÌÐò

¡¡¡¡¿éÉ豸ÒÔʹÓù̶¨´óСµÄ[Êý¾Ý]¿éµÄ·½Ê½ÔËÐС£ ÕâÖÖÀàÐ͵ÄÇý¶¯³ÌÐòÒÀÀµËùνµÄ »º³åÇø»º´æ(buffer cache)£¬ÆäÄ¿µÄ ÊÇÔÚÄÚ´æÖеÄרÓÃÇøÓò»º´æ·ÃÎʹýµÄÊý¾Ý¿é¡£ÕâÖÖ»º³åÇø»º´æ³£³£»ùÓÚºǫ́д (write-behind)£¬ÕâÒâζ×ÅÊý¾ÝÔÚÄÚ´æÖб»Ð޸ĺ󣬵±ÏµÍ³½øÐÐÆäÖÜÆÚÐÔ ´ÅÅÌË¢ÐÂʱ²Å»á±»Í¬²½µ½´ÅÅÌ£¬´Ó¶øÓÅ»¯Ð´²Ù×÷¡£


14.1.3 ×Ö·ûÉ豸

¡¡¡¡È»¶ø£¬ÔÚFreeBSD 4.0°æ±¾ÒÔ¼°ºóÐø°æ±¾ÖУ¬ ¿éÉ豸ºÍ×Ö·ûÉ豸µÄÇø±ð±äµÃ²»´æÔÚÁË¡£


14.2 Newbus¸ÅÀÀ

¡¡¡¡NewbusʵÏÖÁËÒ»ÖÖ»ùÓÚ³éÏó²ãµÄÐÂÐÍ×ÜÏ߽ṹ£¬ ¿ÉÒÔÔÚFreeBSD 3.0Öп´µ½ÕâÖÖ×ÜÏ߽ṹµÄ½éÉÜ£¬µ±Ê±AlphaµÄÒÆÖ²±»µ¼Èëµ½ ´úÂëÊ÷ÖС£Ö±µ½4.0Ëü²Å³ÉΪÉ豸Çý¶¯³ÌÐòʹÓõÄĬÈÏϵͳ¡£ÆäÄ¿µÄÊÇΪÖ÷»ú ϵͳÌṩ¸ø²Ù×÷ϵͳµÄ¸÷ÖÖ×ÜÏߺÍÉ豸µÄ»¥Á¬Ìṩ¸ü¼Ó ÃæÏò¶ÔÏóµÄ·½·¨¡£

¡¡¡¡ÆäÖ÷ÒªÌØÐÔ°üÀ¨£º

  • ¶¯Ì¬Á¬½Ó

  • Çý¶¯³ÌÐòÈÝÒ×Ä£¿é»¯

  • α×ÜÏß

¡¡¡¡×îÏÔÖøµÄ¸Ä±äÖ®Ò»ÊÇ´ÓÆ½ÃæºÍÌØÊâϵͳÑݱäΪÉ豸Ê÷²¼¾Ö¡£

¡¡¡¡¶¥²ãפÁôµÄÊÇ¡°¸ù¡±É豸£¬Ëü×÷Ϊ ¸¸É豸£¬ËùÓÐÆäËûÉ豸¹Ò½ÓÔÚËüÉÏÃæ¡£¶ÔÓÚÿ¸ö½á¹¹£¬Í¨³£¡°¸ù¡± Ö»Óе¥¸öº¢×Ó£¬ÆäÉÏÁ¬½Ó×ÅÖîÈçhost-to-PCIÇÅ µÈ¶«Î÷¡£¶ÔÓÚx86£¬ÕâÖÖ¡°¸ù¡±É豸Ϊ ¡°nexus¡±É豸£¬¶ÔÓÚAlpha£¬AlphaµÄ¸÷ÖÖ ²»Í¬ÐͺÅÓв»Í¬µÄ¶¥²ãÉ豸£¬¶ÔÓ¦²»Í¬µÄÓ²¼þоƬ×飬°üÀ¨ lca£¬apecs£¬ ciaºÍtsunami¡£

¡¡¡¡NewbusÉÏÏÂÎÄÖеÄÉ豸±íʾϵͳÖеĵ¥¸öÓ²¼þʵÌå¡£ÀýÈ磬ÿ¸öPCIÉ豸±» ±íʾΪһ¸öNewbusÉ豸¡£ÏµÍ³ÖеÄÈκÎÉ豸¿ÉÒÔÓк¢×Ó£»Óк¢×ÓµÄÉ豸ͨ³£±» ³ÆÎª¡°bus¡±¡£ÏµÍ³Öг£ÓÃ×ÜÏßµÄÀý×Ó¾ÍÊÇ ISAºÍPCI£¬ËûÃǸ÷×Ô¹ÜÀíÁ¬½Óµ½ISAºÍPCI×ÜÏßÉϵÄÉ豸ÁÐ±í¡£

¡¡¡¡Í¨³££¬²»Í¬ÀàÐ͵Ä×ÜÏßÖ®¼äµÄÁ¬½Ó±»±íʾΪ ¡°ÇÅ¡±É豸£¬ËüµÄº¢×Ó¾ÍÊÇËüËùÁ¬½ÓµÄ ×ÜÏß¡£Ò»¸öÀý×Ó¾ÍÊÇPCI-to-PCIÇÅ£¬ËüÔÚ¸¸PCI×ÜÏßÉϱ» ±íʾΪpcibN£¬¶øÓÃËüµÄº¢×Ó pciN±íʾÁ¬½ÓÔÚËüÉÏÃæµÄ ×ÜÏß¡£ÕâÖÖ²¼¾Ö¼ò»¯ÁËPCI×ÜÏßÊ÷µÄʵÏÖ£¬ÔÊÐí¹«¹²´úÂëͬʱÓÃÓÚ¶¥²ãºÍÇÅ½ÓµÄ ×ÜÏß¡£

¡¡¡¡Newbus½á¹¹ÖеÄÿ¸öÉ豸ÇëÇóËüµÄ¸¸É豸À´ÎªÆäÓ³Éä×ÊÔ´¡£¸¸É豸½Ó×ÅÇëÇó ËüµÄ¸¸É豸£¬Ö±µ½µ½´ïnexus¡£Òò´Ë£¬»ù±¾ÉÏnexusÊÇNewbusϵͳÖÐΨһ֪µÀËùÓÐ ×ÊÔ´µÄ²¿·Ö¡£

Ìáʾ: ISAÉ豸¿ÉÄÜÏëÔÚ0x230Ó³ÉäÆäIO¶Ë¿Ú£¬Òò´ËËüÏòÆä ¸¸É豸ÇëÇó£¬ÕâÖÖÇé¿öÏÂÊÇISA×ÜÏß¡£ISA×ÜÏß½«Ëü½»¸øPCI-to-ISAÇÅ£¬PCI-to-ISA ÇŽÓ×ÅÇëÇóPCI×ÜÏߣ¬PCI×ÜÏßµ½´ïhost-to-PCIÇÅ£¬×îºóµ½´ïnexus¡£ÕâÖÖÏòÉÏ ¹ý¶ÉµÄÓÅÃÀÖ®´¦ÔÚÓÚ¿ÉÒÔÓпռäÀ´±ä»»ÇëÇó¡£¶Ô0x230IO¶Ë¿Ú µÄÇëÇóÔÚMIPS»úÆ÷ÉÏ¿ÉÒÔ±»PCIÇűä³É 0xb0000230´¦µÄÄÚ´æÓ³Éä¡£

¡¡¡¡×ÊÔ´·ÖÅä¿ÉÒÔÔÚÉ豸Ê÷µÄÈκεط½¼ÓÒÔ¿ØÖÆ¡£ÀýÈ磬ÔںܶàAlphaƽ̨ÉÏ£¬ ISAÖжÏÓëPCIÖжÏÊǵ¥¶À¹ÜÀíµÄ£¬¶ÔISAÖжϵÄ×ÊÔ´·ÖÅäÊÇÓÉAlphaµÄISA×ÜÏßÉ豸 ¹ÜÀíµÄ¡£ÔÚIA-32ÉÏ£¬ISAºÍPCIÖж϶¼Óɶ¥²ãµÄnexusÉ豸¹ÜÀí¡£¶ÔÓÚÁ½ÖÖÒÆÖ²£¬ ÄÚ´æºÍ¶Ë¿ÚµØÖ·¿Õ¼äÓɵ¥¸öʵÌå¹ÜÀí - ÔÚIA-32ÉÏÊÇnexus£¬ÔÚAlpha£¨ÀýÈ磬CIA »òtsunami£©ÉÏÊÇÏà¹ØµÄоƬ×éÇý¶¯³ÌÐò¡£

¡¡¡¡ÎªÁ˹淶»¯¶ÔÄÚ´æºÍ¶Ë¿ÚÓ³Éä×ÊÔ´µÄ·ÃÎÊ£¬NewbusÕûºÏÁËNetBSDµÄ bus_space API¡£ËûÃÇÌṩÁ˵¥Ò»µÄAPIÀ´´úÌæinb/outb ºÍÖ±½ÓÄÚ´æ¶Áд¡£ÕâÑù×öµÄÓÅÊÆÔÚÓÚµ¥¸öÇý¶¯³ÌÐò¾Í¿ÉÒÔʹÓÃÄÚ´æÓ³Éä¼Ä´æÆ÷ »ò¶Ë¿ÚÓ³Éä¼Ä´æÆ÷£¨ÓÐЩӲ¼þÖ§³ÖÁ½Õߣ©¡£

¡¡¡¡ÕâÖÖÖ§³Ö±»ºÏ²¢µ½ÁË×ÊÔ´·ÖÅä»úÖÆÖС£·ÖÅä×ÊԴʱ£¬Çý¶¯³ÌÐò¿ÉÒÔ´Ó×ÊÔ´ ÖмìÈ¡¹ØÁªµÄbus_space_tag_tºÍ bus_space_handle_t¡£

¡¡¡¡NewbusÒ²ÔÊÐíÔÚרÓÃÓÚ´ËÄ¿µÄµÄÎļþÖж¨Òå½Ó¿Ú·½·¨¡£ÕâЩÊÇ .mÎļþ£¬¿ÉÒÔÔÚsrc/sys Ŀ¼Ê÷ÖÐÕÒµ½¡£

¡¡¡¡NewbusϵͳµÄºËÐÄÊÇ¿ÉÀ©Õ¹µÄ¡°»ùÓÚ¶ÔÏó±à³Ì(object-based programming)¡±µÄÄ£ÐÍ¡£ÏµÍ³ÖеÄÿ¸öÉ豸¾ßÓÐËüËùÖ§³ÖµÄÒ»¸ö·½·¨±í¡£ ϵͳºÍÆäËûÉ豸ʹÓÃÕâЩ·½·¨À´¿ØÖÆÉ豸²¢ÇëÇó·þÎñ¡£É豸ËùÖ§³ÖµÄ²»Í¬·½·¨ ±»¶¨ÒåΪ¶à¸ö¡°½Ó¿Ú¡±¡£¡°½Ó¿Ú¡±Ö»ÊÇ É豸ʵÏÖµÄÒ»×éÏà¹ØµÄ·½·¨¡£

¡¡¡¡ÔÚNewbusϵͳÖУ¬É豸·½·¨ÊÇͨ¹ýϵͳÖеĸ÷ÖÖÉ豸Çý¶¯³ÌÐòÌṩµÄ¡£µ± ×Ô¶¯ÅäÖÃ(auto-configuration)ÆÚ¼äÉ豸±»Á¬½Ó(attach) µ½Çý¶¯³ÌÐò£¬ËüʹÓÃÇý¶¯³ÌÐòÉùÃ÷µÄ·½·¨±í¡£ÒÔºóÉ豸¿ÉÒÔ´ÓÆäÇý¶¯³ÌÐò ·ÖÀë(detach)£¬²¢ ÖØÐÂÁ¬½Ó(re-attach)µ½¾ßÓÐз½·¨±íµÄÐÂÇý¶¯³ÌÐò¡£Õâ¾Í ÔÊÐíÇý¶¯³ÌÐòµÄ¶¯Ì¬Ìæ»»£¬¶ø¶¯Ì¬Ìæ»»¶ÔÓÚÇý¶¯³ÌÐòµÄ¿ª·¢·Ç³£ÓÐÓá£

¡¡¡¡½Ó¿Úͨ¹ýÓëÎļþϵͳÖÐÓÃÓÚ¶¨Òåvnode²Ù×÷µÄÓïÑÔÏàËÆµÄ½Ó¿Ú¶¨ÒåÓïÑÔÀ´ ÃèÊö¡£½Ó¿Ú±»±£´æÔÚ·½·¨ÎļþÖУ¨Í¨³£ÃüÃûΪfoo_if.m£©¡£

Àý 14-1. NewbusµÄ·½·¨

      # Foo ×Óϵͳ/Çý¶¯³ÌÐò£¨×¢ÊÍ...£©
      
	  INTERFACE foo

       	METHOD int doit {
       		device_t dev;
       	};
       	
       	# Èç¹ûûÓÐͨ¹ýDEVMETHOD()Ìṩһ¸ö·½·¨£¬ÔòDEFAULTΪ½«»á±»Ê¹Óõķ½·¨
       	
       	METHOD void doit_to_child {
       		device_t dev;
       		driver_t child;
       	} DEFAULT doit_generic_to_child;
      

¡¡¡¡µ±½Ó¿Ú±»±àÒëºó£¬Ëü²úÉúÒ»¸öÍ·Îļþ ¡°foo_if.h¡±£¬ÆäÖаüº¬º¯ÊýÉùÃ÷£º

      int FOO_DOIT(device_t dev);
      int FOO_DOIT_TO_CHILD(device_t dev, device_t child);
    

¡¡¡¡°éËæ×Ô¶¯²úÉúµÄÍ·Îļþ£¬Ò²»á´´½¨Ò»¸öÔ´Îļþ ¡°foo_if.c¡±£»ÆäÖаüº¬Ò»Ð©º¯ÊýµÄʵÏÖ£¬ ÕâЩº¯ÊýÓÃÓÚÔÚ¶ÔÏó·½·¨±íÖвéÕÒÏà¹Øº¯ÊýµÄλÖò¢µ÷ÓÃÄǸöº¯Êý¡£

¡¡¡¡ÏµÍ³¶¨ÒåÁËÁ½¸öÖ÷Òª½Ó¿Ú¡£µÚÒ»¸ö»ù±¾½Ó¿Ú±»³ÆÎª ¡°É豸(device)¡±£¬²¢°üÀ¨ÓëËùÓÐÉ豸Ïà¹Ø µÄ·½·¨¡£¡°É豸(device)¡±½Ó¿ÚÖеķ½·¨ °üÀ¨¡°Ì½²â(probe)¡±£¬ ¡°Á¬½Ó(attach)¡±ºÍ ¡°·ÖÀë(detach)¡±£¬ËûÃÇÓÃÀ´¿ØÖÆÓ²¼þµÄÕì²â£¬ ÒÔ¼°¡°¹Ø±Õ(shutdown)¡±£¬ ¡°¹ÒÆð(suspend)¡±ºÍ ¡°»Ö¸´(resume)¡±£¬ËûÃÇÓÃÓڹؼüʼþ֪ͨ¡£

¡¡¡¡ÁíÒ»¸ö£¬¸ü¼Ó¸´ÔÓ½Ó¿ÚÊÇ¡°bus¡±¡£ ´Ë½Ó¿Ú°üº¬µÄ·½·¨ÊÊÓÃÓÚ´øÓк¢×ÓµÄÉ豸£¬°üÀ¨·ÃÎÊ×ÜÏßÌØ¶¨µÄÿÉ豸ÐÅÏ¢ [2]£¬Ê¼þ֪ͨ £¨child_detached£¬ driver_added£©ºÍÏìÓ¦¹ÜÀí £¨alloc_resource£¬ activate_resource£¬ deactivate_resource£¬ release_resource£©¡£

¡¡¡¡¡°bus¡±½Ó¿ÚÖеĺܶ෽·¨Îª×ÜÏßÉ豸µÄijЩº¢×ÓÖ´ÐзþÎñ¡£ ÕâЩ·½·¨Í¨³£Ê¹ÓÃǰÁ½¸ö²ÎÁ¿Ö¸¶¨Ìṩ·þÎñµÄ×ÜÏߺÍÇëÇó·þÎñµÄ×ÓÉ豸¡£ÎªÁË ¼ò»¯É豸Çý¶¯³ÌÐò´úÂ룬ÕâЩ·½·¨Öеĺܶ඼ÓзÃÎÊÕß(accessor)º¯Êý£¬·ÃÎÊÕß º¯ÊýÓÃÀ´²éÕÒ¸¸É豸²¢µ÷Óø¸É豸Éϵķ½·¨¡£ÀýÈ磬·½·¨ BUS_TEARDOWN_INTR(device_t dev, device_t child, ...) ¿ÉÒÔʹÓú¯Êý bus_teardown_intr(device_t child, ...)À´µ÷Óá£

¡¡¡¡ÏµÍ³ÖеÄijЩ×ÜÏßÀàÐÍÌṩÁ˶îÍâ½Ó¿ÚÒÔÌṩ¶Ô×ÜÏßÌØ¶¨¹¦ÄܵķÃÎÊ¡£ ÀýÈ磬PCI×ÜÏßÇý¶¯³ÌÐò¶¨ÒåÁË¡°pci¡±½Ó¿Ú£¬´Ë½Ó¿ÚÓÐÁ½¸ö·½·¨ read_configºÍ write_config£¬ÓÃÓÚ·ÃÎÊPCIÉ豸 µÄÅäÖüĴæÆ÷¡£


14.3 Newbus API

¡¡¡¡ÓÉÓÚNewbus API·Ç³£ÅӴ󣬱¾½ÚŬÁ¦½«ËüÎĵµ»¯¡£±¾ÎĵµµÄÏÂÒ»°æ±¾»á ´øÀ´¸ü¶àÐÅÏ¢¡£


14.3.1 Ô´´úÂëĿ¼Ê÷ÖеÄÖØÒªÎ»ÖÃ

¡¡¡¡src/sys/[arch]/[arch] - ÌØ¶¨»úÆ÷½á¹¹µÄ Äں˴úÂëλÓÚÕâ¸öĿ¼¡£ÀýÈçi386½á¹¹»ò SPARC64½á¹¹¡£

¡¡¡¡src/sys/dev/[bus] - Ö§³ÖÌØ¶¨ [bus]µÄÉ豸λÓÚÕâ¸öĿ¼¡£

¡¡¡¡src/sys/dev/pci - PCI×ÜÏßÖ§³Ö´úÂëλÓÚ Õâ¸öĿ¼¡£

¡¡¡¡src/sys/[isa|pci] - PCI/ISAÉ豸Çý¶¯³ÌÐò λÓÚÕâ¸öĿ¼¡£FreeBSD4.0°æ±¾ÖУ¬PCI/ISAÖ§³Ö´úÂë ¹ýÈ¥´æÔÚÓÚÕâ¸öĿ¼ÖС£


14.3.2 ÖØÒª½á¹¹ºÍÀàÐͶ¨Òå

¡¡¡¡devclass_t - ÕâÊÇÖ¸Ïò struct devclassµÄÖ¸ÕëµÄÀàÐͶ¨Òå¡£

¡¡¡¡device_method_t - Óë kobj_method_tÏàͬ£¨²Î¿´ src/sys/kobj.h£©¡£

¡¡¡¡device_t - ÕâÊÇÖ¸Ïò struct deviceµÄÖ¸ÕëµÄÀàÐͶ¨Òå¡£ device_t ±íʾϵͳÖеÄÉ豸¡£ËüÊÇÄں˶ÔÏó¡£ ÊµÏÖϸ½Ú²Î¿´src/sys/sys/bus_private.h¡£

¡¡¡¡driver_t - ÕâÊÇÒ»¸öÀàÐͶ¨Ò壬ËüÒýÓà struct driver¡£ driver½á¹¹ÊÇÒ»Àà device(É豸)Äں˶ÔÏó£»ËüÒ²±£´æ×ÅÇý¶¯³ÌÐòµÄ˽ÓÐÊý¾Ý¡£

ͼ 14-1. driver_tʵÏÖ

	  struct driver {
	     	KOBJ_CLASS_FIELDS;
	      	void	*priv;			/* Çý¶¯³ÌÐò˽ÓÐÊý¾Ý */
	  };
	

¡¡¡¡device_state_tÊÇÒ»¸öö¾ÙÀàÐÍ£¬¼´ device_state¡£Ëü°üº¬NewbusÉ豸ÔÚ×Ô¶¯ÅäÖÃǰºó ¿ÉÄܵÄ״̬¡£

ͼ 14-2. É豸״̬device_state_t

	  /*
	   * src/sys/sys/bus.h
	   */
	  typedef enum device_state {
	  	DS_NOTPRESENT,	/* δ̽²â»ò̽²âʧ°Ü */
	    	DS_ALIVE,		/* ̽²â³É¹¦ */
	    	DS_ATTACHED,	/* µ÷ÓÃÁËÁ¬½Ó·½·¨ */
	    	DS_BUSY			/* É豸ÒÑ´ò¿ª */
	  } device_state_t;
	

µÚ15Õ ¡¡ÉùÒô×Óϵͳ

¹©¸å£ºJean-Francois Dockes. ·­Ò룺spellar @SMTH.

15.1 ¼ò½é

¡¡¡¡FreeBSDÉùÒô×ÓϵͳÇåÎúµØ½«Í¨ÓÃÉùÒô´¦ÀíÎÊÌâÓëÉè±¸ÌØ¶¨µÄÎÊÌâ·ÖÀë ¿ªÀ´¡£ÕâʹµÃ¸üÈÝÒ×¼ÓÈë¶ÔÐÂÉ豸µÄÖ§³Ö¡£

¡¡¡¡ pcm(4)¿ò¼ÜÊÇÉùÒô×ÓϵͳµÄÖÐÐIJ¿·Ö¡£ËüÖ÷ҪʵÏÖÏÂÃæµÄ×é¼þ£º

  • Ò»¸öµ½Êý×Ö»¯ÉùÒôºÍ»ìÒôÆ÷º¯ÊýµÄϵͳµ÷Óýӿڣ¨read, write, ioctls£©¡£ioctlÃüÁºÏ¼æÈÝÀϵÄOSS »òVoxware½Ó¿Ú£¬ÔÊÐíÒ»°ã¶àýÌåÓ¦ÓóÌÐò ²»¼ÓÐ޸ĵØÒÆÖ²¡£

  • ´¦ÀíÉùÒôÊý¾ÝµÄ¹«¹²´úÂ루¸ñʽת»»£¬ÐéÄâͨµÀ£©¡£

  • Ò»¸öͳһµÄÈí¼þ½Ó¿Ú£¬ÓëÓ²¼þÌØ¶¨µÄÒôƵ½Ó¿ÚÄ£¿é½Ó¿Ú

  • ¶ÔijЩͨÓÃÓ²¼þ½Ó¿Ú£¨ac97£©»ò¹²ÏíµÄÓ²¼þÌØ¶¨´úÂë £¨ÀýÈ磺ISA DMAÀý³Ì£©µÄ¶îÍâÖ§³Ö¡£

¡¡¡¡¶ÔÌØ¶¨Éù¿¨µÄÖ§³ÖÊÇͨ¹ýÓ²¼þÌØ¶¨µÄÇý¶¯³ÌÐòÀ´ÊµÏֵģ¬ÕâЩÇý¶¯³ÌÐò ÌṩͨµÀºÍ»ìÒôÆ÷½Ó¿Ú£¬²åÈ뵽ͨÓÃpcm´úÂëÖС£

¡¡¡¡±¾ÕÂÖУ¬ÊõÓïpcm½«Ö¸ÉùÒôÇý¶¯³ÌÐòµÄ ÖÐÐÄ£¬Í¨Óò¿·Ö£¬ÕâÊǶԱÈÓ²¼þÌØ¶¨µÄÄ£¿é¶øÑԵġ£

¡¡¡¡Ô¤ÆÚµÄÇý¶¯³ÌÐò±àдÕßµ±È»Ï£Íû´ÓÏÖÓÐÄ£¿é¿ªÊ¼£¬²¢Ê¹ÓÃÄÇЩ´úÂë×÷Ϊ ×îÖղο¼¡£µ«ÊÇ£¬ÓÉÓÚÉùÒô´úÂëÊ®·Ö¼ò½àƯÁÁ£¬ÕâÒ²»ù±¾ÉÏÃâ³ýÁË×¢ÊÍ¡£ ±¾ÎĵµÊÔͼ¸ø³ö¿ò¼Ü½Ó¿ÚµÄÒ»¸ö¸ÅÀÀ£¬²¢»Ø´ð¸ÄдÏÖÓдúÂëʱ¿ÉÄܳöÏÖµÄ Ò»Ð©ÎÊÌâ¡£

¡¡¡¡×÷ΪÁíÍâµÄ;¾¶£¬»òÕß˵³ýÁË´ÓÒ»¸ö¿É¹¤×÷µÄ·¶Àý¿ªÊ¼µÄ°ì·¨Ö®Í⣬ Äã¿ÉÒÔ´Ó http://people.FreeBSD.org/~cg/template.cÕÒµ½Ò»¸ö×¢Ê͹ýµÄ Çý¶¯³ÌÐòÄ£°å¡£


15.2 Îļþ

¡¡¡¡³ý/usr/src/sys/sys/soundcard.hÖеĹ«¹² ioctl½Ó¿Ú¶¨ÒåÍ⣬ËùÓеÄÏà¹Ø´úÂ뵱ǰ(FreeBSD 4.4)λÓÚ /usr/src/sys/dev/sound/¡£

¡¡¡¡ÔÚ/usr/src/sys/dev/sound/ÏÂÃæ£¬ pcm/Ŀ¼Öб£´æ×ÅÖÐÐÄ´úÂ룬 ¶øisa/ºÍpci/Ŀ¼ÖÐÓÐ ISAºÍPCI°åµÄÇý¶¯³ÌÐò¡£


15.3 ̽²â£¬Á¬½ÓµÈ

¡¡¡¡ÉùÒôÇý¶¯³ÌÐòʹÓÃÓëÈκÎÓ²¼þÇý¶¯³ÌÐòÄ£¿éÏàͬµÄ·½·¨Ì½²âºÍÁ¬½Ó£¨É豸£©¡£ Äã¿ÉÄÜÏ£Íûä¯ÀÀÒ»ÏÂÊÖ²áÖÐISA»òPCIÕ½ڵÄÄÚÈÝÀ´»ñÈ¡¸ü¶àÐÅÏ¢¡£

¡¡¡¡È»¶ø£¬ÉùÒôÇý¶¯³ÌÐòÔÚijЩ·½ÃæÓÖÓÐЩ²»Í¬£º

  • ËûÃǽ«×Ô¼ºÉùÃ÷ΪpcmÀàÉ豸£¬´øÓÐÒ»¸ö É豸˽Óнṹstruct snddev_info£º

              static driver_t xxx_driver = {
                  "pcm",
                  xxx_methods,
                  sizeof(struct snddev_info)
              };
    
              DRIVER_MODULE(snd_xxxpci, pci, xxx_driver, pcm_devclass, 0, 0);
              MODULE_DEPEND(snd_xxxpci, snd_pcm, PCM_MINVER, PCM_PREFVER,PCM_MAXVER);
    

    ´ó¶àÊýÉùÒôÇý¶¯³ÌÐòÐèÒª´æ´¢¹ØÓÚÆäÉ豸µÄ¸½¼Ó˽ÓÐÐÅÏ¢¡£Ë½ÓÐÊý¾Ý ½á¹¹Í¨³£ÔÚÁ¬½ÓÀý³ÌÖзÖÅä¡£ÆäµØÖ·Í¨¹ýµ÷Óà pcm_register()ºÍ mixer_init()´«µÝ¸ø pcm¡£ºóÃæpcm ½«´ËµØÖ·×÷Ϊµ÷ÓÃÉùÒôÇý¶¯³ÌÐò½Ó¿ÚʱµÄ²ÎÊý´«µÝ»ØÀ´¡£

  • ÉùÒôÇý¶¯³ÌÐòµÄÁ¬½ÓÀý³ÌÓ¦µ±Í¨¹ýµ÷ÓÃmixer_init() ÏòpcmÉùÃ÷ËüµÄMIXER»òAC97 ½Ó¿Ú¡£¶ÔÓÚMIXER½Ó¿Ú£¬Õâ»á½Ó×ÅÒýÆðµ÷Óà xxxmixer_init()¡£

  • ÉùÒôÇý¶¯³ÌÐòµÄÁ¬½ÓÀý³Ìͨ¹ýµ÷Óà pcm_register(dev, sc, nplay, nrec) ÏòpcmÉùÃ÷ÆäͨÓÃCHANNELÅäÖã¬ÆäÖÐ scÊÇÉ豸Êý¾Ý½á¹¹µÄµØÖ·£¬ ÔÚpcmÒÔºóµÄµ÷ÓÃÖн«»áÓõ½Ëü£¬ nplayºÍnrecÊDz¥·ÅºÍ¼Òô ͨµÀµÄÊýÄ¿¡£

  • ÉùÒôÇý¶¯³ÌÐòµÄÁ¬½ÓÀý³Ìͨ¹ýµ÷Óà pcm_addchan()ÉùÃ÷ËüµÄÿ¸öͨµÀ¶ÔÏó¡£Õâ»áÔÚ pcmÖн¨Á¢ÆðͨµÀºÏ³É£¬²¢½Ó×Å»áÒýÆðµ÷Óà xxxchannel_init() £¨Òë×¢£ºÇë²Î¿¼Ô­ÎÄ£©¡£

  • ÉùÒôÇý¶¯³ÌÐòµÄ·ÖÀëÀý³ÌÔÚÊÍ·ÅÆä×ÊԴ֮ǰӦµ±µ÷Óà pcm_unregister()¡£

¡¡¡¡ÓÐÁ½ÖÖ¿ÉÄܵķ½·¨À´´¦Àí·ÇPnPÉ豸£º

  • ʹÓÃdevice_identify()·½·¨ £¨·¶Àý£ºsound/isa/es1888.c£©¡£ device_identify()·½·¨ÔÚÒÑÖªµØÖ·Ì½²âÓ²¼þ£¬ Èç¹û·¢ÏÖÖ§³ÖµÄÉ豸¾Í»á´´½¨Ò»¸öеÄpcmÉ豸£¬Õâ¸öpcmÉ豸½Ó×Å »á±»´«µÝµ½probe/attach¡£

  • ʹÓö¨ÖÆÄÚºËÅäÖõķ½·¨£¬ÎªpcmÉ豸ÉèÖÃÊʵ±µÄhints£¨·¶Àý£º sound/isa/mss.c£©¡£

¡¡¡¡pcmÇý¶¯³ÌÐòÓ¦µ±ÊµÏÖ device_suspend£¬ device_resumeºÍ device_shutdownÀý³Ì£¬ÕâÑùµçÔ´¹ÜÀíºÍÄ£¿éÐ¶ÔØ¾ÍÄÜ ÕýÈ·µØ·¢»Ó×÷Óá£


15.4 ½Ó¿Ú

¡¡¡¡pcmºËÐÄÓëÉùÒôÇý¶¯³ÌÐòÖ®¼äµÄ½Ó¿ÚÒÔÊõÓï Äں˶ÔÏóµÄ½Ð·¨À´¶¨Òå¡£

¡¡¡¡ÉùÒôÇý¶¯³ÌÐòͨ³£ÌṩÁ½ÖÖÖ÷ÒªµÄ½Ó¿Ú£º CHANNELÒÔ¼° MIXER»òAC97¡£

¡¡¡¡AC97ÊÇÒ»¸öºÜСµÄÓ²¼þ·ÃÎÊ£¨¼Ä´æÆ÷¶Á/д£© ½Ó¿Ú£¬ÓÉÇý¶¯³ÌÐòΪ´øAC97±àÂë½âÂëÆ÷µÄÓ²¼þÀ´ÊµÏÖ¡£ÕâÖÖÇé¿öÏ£¬Êµ¼ÊµÄ MIXER½Ó¿ÚÓÉpcmÖй²ÏíµÄAC97´úÂëÌṩ¡£


15.4.1 CHANNEL½Ó¿Ú

15.4.1.1 º¯Êý²ÎÊýµÄͨ³£×¢ÒâÊÂÏî

¡¡¡¡ÉùÒôÇý¶¯³ÌÐòͨ³£ÓÃÒ»¸ö˽ÓÐÊý¾Ý½á¹¹À´ÃèÊöËûÃǵÄÉ豸£¬Çý¶¯ ³ÌÐòËùÖ§³ÖµÄ²¥·ÅºÍ¼ÒôÊý¾ÝͨµÀ¸÷ÓÐÒ»¸ö¡£

¡¡¡¡¶ÔÓÚËùÓеÄCHANNEL½Ó¿Úº¯Êý£¬µÚÒ»¸ö²ÎÊýÊÇÒ»¸ö²»Í¸Ã÷µÄÖ¸Õë¡£

¡¡¡¡µÚ¶þ¸ö²ÎÊýÊÇÖ¸Ïò˽ÓеÄͨµÀÊý¾Ý½á¹¹µÄÖ¸Õ룬 channel_init()ÊǸöÀýÍ⣬ËüµÄÖ¸ÕëÖ¸Ïò˽ÓÐ É豸½á¹¹£¨²¢·µ»ØÓÉpcmÒÔºóʹÓõÄͨµÀÖ¸Õ룩¡£


15.4.1.2 Êý¾Ý´«Êä²Ù×÷¸ÅÀÀ

¡¡¡¡¶ÔÓÚÉùÒôÊý¾Ý´«Ê䣬pcmºËÐÄÓëÉùÒôÇý¶¯ ³ÌÐòÊÇͨ¹ýÒ»¸öÓÉstruct snd_dbufÃèÊöµÄ ¹²ÏíÄÚ´æÇøÓò½øÐÐͨÐŵġ£

¡¡¡¡struct snd_dbufÊÇ pcm˽Óеģ¬ÉùÒôÇý¶¯³ÌÐòͨ¹ýµ÷Ó÷ÃÎÊÕß º¯Êý£¨sndbuf_getxxx()£©À´»ñµÃ¸ÐÐËȤµÄÖµ¡£

¡¡¡¡¹²ÏíÄÚ´æÇøÓòµÄ´óСµÈÓÚ sndbuf_getsize()£¬²¢±»·Ö¸îΪ´óС¹Ì¶¨£¬ÇÒµÈÓÚ sndbuf_getblksz()×ֽڵĺܶà¿é¡£

¡¡¡¡µ±²¥·Åʱ£¬³£¹æµÄ´«Êä»úÖÆÈçÏ£¨½«Òâ˼·´¹ýÀ´¾ÍÊǼÒô£©£º

  • pcm¿ªÊ¼Ê±Ìî³ä»º³åÇø£¬È»ºóÒÔ ²ÎÊýPCMTRIG_STARTµ÷ÓÃÉùÒôÇý¶¯³ÌÐòµÄ xxxchannel_trigger() ¡£

  • ÉùÒôÇý¶¯³ÌÐò½Ó×Ű²ÅÅÒÔ sndbuf_getblksz()×Ö½Ú´óСΪ¿é£¬Öظ´½« Õû¸öÄÚ´æÇøÓò£¨sndbuf_getbuf()£¬ sndbuf_getsize()£©´«Êäµ½É豸¡£¶ÔÓÚÿ¸ö ´«Êä¿é»Øµ÷pcmº¯Êý chn_intr()£¨Õâͨ³£ÔÚÖжÏʱ¼ä·¢Éú£©¡£

  • chn_intr()°²ÅŽ«ÐÂÊý¾Ý¿½±´µ½ÄÇЩ Êý¾ÝÒÑ´«Êäµ½É豸£¨ÏÖÔÚ¿ÕÏУ©µÄÇøÓò£¬²¢¶Ô snd_dbuf½á¹¹½øÐÐÊʵ±µÄ¸üС£


15.4.1.3 channel_init

¡¡¡¡µ÷ÓÃxxxchannel_init()À´³õʼ»¯Ã¿¸ö²¥·Å ºÍ¼ÒôͨµÀ¡£Õâ¸öµ÷ÓôÓÉùÒôÇý¶¯³ÌÐòµÄÁ¬½ÓÀý³ÌÖз¢Æð¡££¨²Î¿´ ̽²âºÍÁ¬½ÓÒ»½Ú£©¡£

          static void *
          xxxchannel_init(kobj_t obj, void *data, 
             struct snd_dbuf *b, struct pcm_channel *c, int dir)(1)
          {
              struct xxx_info *sc = data;
              struct xxx_chinfo *ch;
               ...
              return ch;(2)
           }
(1)
bΪͨµÀ struct snd_dbufµÄµØÖ·¡£ËüÓ¦µ±ÔÚ º¯ÊýÖÐͨ¹ýµ÷ÓÃsndbuf_alloc()À´³õʼ»¯¡£ ËùÓõĻº³åÇø´óСͨ³£ÊÇÉ豸'µäÐÍ'´«Êä´óСµÄÒ»¸ö½ÏСµÄ±¶Êý¡£

cΪ pcmͨµÀ¿ØÖƽṹµÄÖ¸Õë¡£ÕâÊǸö²»Í¸Ã÷ Ö¸Õë¡£º¯ÊýÓ¦µ±½«Ëü±£´æµ½¾Ö²¿Í¨µÀ½á¹¹ÖУ¬ÔÚºóÃæµ÷Óà pcmº¯Êý£¨ÀýÈ磺 chn_intr(c)£©Ê±»áʹÓÃËü¡£

dirָʾͨµÀ·½Ïò £¨PCMDIR_PLAY»ò PCMDIR_REC£©¡£

(2)
º¯ÊýÓ¦µ±·µ»ØÒ»¸öÖ¸Õ룬´ËÖ¸ÕëÖ¸ÏòÓÃÓÚ¿ØÖÆ´ËͨµÀµÄ˽ÓÐ ÇøÓò¡£Ëü½«×÷Ϊ²ÎÊý±»´«µÝµ½¶ÔÆäËûͨµÀ½Ó¿ÚµÄµ÷Óá£

15.4.1.4 channel_setformat

¡¡¡¡xxxchannel_setformat()Ó¦µ±°´Ìض¨Í¨µÀ£¬ ÌØ¶¨ÉùÒô¸ñʽÉèÖÃÓ²¼þ¡£

          static int
          xxxchannel_setformat(kobj_t obj, void *data, u_int32_t format)(1)
          {
              struct xxx_chinfo *ch = data;
               ...
              return 0;
           }
(1)
formatΪ AFMT_XXX valueÖµÖ®Ò» £¨soundcard.h£©¡£

15.4.1.5 channel_setspeed

¡¡¡¡xxxchannel_setspeed()°´Ö¸¶¨µÄÈ¡ÑùËÙ¶È ÉèÖÃͨµÀÓ²¼þ£¬²¢·µ»Ø·µ»Ø¿ÉÄܵ÷Õû¹ýµÄËÙ¶È¡£

          static int
          xxxchannel_setspeed(kobj_t obj, void *data, u_int32_t speed)
          {
              struct xxx_chinfo *ch = data;
               ...
              return speed;
           }

15.4.1.6 channel_setblocksize

¡¡¡¡xxxchannel_setblocksize()ÉèÖÿé´óС£¬ ÕâÊÇpcmÓëÉùÒôÇý¶¯³ÌÐò£¬ÒÔ¼°ÉùÒôÇý¶¯ ³ÌÐòÓëÉ豸֮¼äµÄ´«Ê䵥λµÄ´óС¡£´«ÊäÆÚ¼ä£¬Ã¿´Î´«ÊäÕâÑù´óСµÄ Êý¾Ýºó£¬ÉùÒôÇý¶¯³ÌÐò¶¼Ó¦µ±µ÷ÓÃpcmµÄ chn_intr()¡£

¡¡¡¡´ó¶àÊýÇý¶¯³ÌÐòÖ»×¢ÒâÕâ¶ùµÄ¿é´óС£¬ÒòΪµ±Êµ¼Ê´«Ê俪ʼʱӦ¸Ã ʹÓÃÕâ¸öÖµ¡£

          static int
          xxxchannel_setblocksize(kobj_t obj, void *data, u_int32_t blocksize)
          {
              struct xxx_chinfo *ch = data;
                ...
              return blocksize;(1)
           }
(1)
º¯Êý·µ»Ø¿ÉÄܵ÷Õû¹ýµÄ¿é´óС¡£Èç¹û¿é´óÐ¡ÕæµÄ±ä»¯ÁË£¬ ÕâÖÖÇé¿öÏÂÓ¦µ±µ÷ÓÃsndbuf_resize()µ÷Õû »º³åÇøµÄ´óС¡£

15.4.1.7 channel_trigger

¡¡¡¡xxxchannel_trigger()ÓÉ pcmÀ´¿ØÖÆÇý¶¯³ÌÐòÖеÄʵ¼Ê´«Êä²Ù×÷¡£

          static int
          xxxchannel_trigger(kobj_t obj, void *data, int go)(1)
          {
              struct xxx_chinfo *ch = data;
               ...
              return 0;
           }
(1)
go¶¨Ò嵱ǰµ÷Óõ͝×÷¡£¿ÉÄܵÄֵΪ£º
  • PCMTRIG_START£ºÇý¶¯³ÌÐòÓ¦µ± Æô¶¯´Ó/µ½Í¨µÀ»º³åÇøµÄÊý¾Ý´«Êä¡£Èç¹ûÐèÒª£¬Ó¦µ±Í¨¹ý sndbuf_getbuf()ºÍ sndbuf_getsize()¼ìÈ¡»º³åÇøµÄ »ùµØÖ·ºÍ´óС¡£

  • PCMTRIG_EMLDMAWR / PCMTRIG_EMLDMARD£º¸æËßÇý¶¯³ÌÐò£¬ ÊäÈë»òÊä³ö»º³åÇø¿ÉÄÜÒѱ»¸üйýÁË¡£´ó¶àÊýÇý¶¯³ÌÐòÖ»ÊÇ ºöÂÔÕâЩµ÷Óá£

  • PCMTRIG_STOP / PCMTRIG_ABORT£ºÇý¶¯³ÌÐòÓ¦µ±Í£Ö¹µ±Ç° µÄ´«Êä¡£

×¢Òâ: Èç¹ûÇý¶¯³ÌÐòʹÓÃISA DMA£¬ÔòÓ¦µ±ÔÚÉ豸ÉÏÖ´Ðж¯×÷ǰ µ÷ÓÃsndbuf_isadma()£¬²¢´¦ÀíDMAоƬһ·½µÄ ÊÂÇé¡£


15.4.1.8 channel_getptr

¡¡¡¡xxxchannel_getptr()·µ»Ø´«Ê仺³åÇøÖÐ µ±Ç°µÄ»º³å¡£Ëüͨ³£ÓÉchn_intr()µ÷Ó㬶øÇÒ ÕâÒ²ÊÇΪʲôpcmÖªµÀËüÓ¦µ±ÍùÄĶù´«ËÍ ÐÂÊý¾Ý¡£


15.4.1.9 channel_free

¡¡¡¡µ÷ÓÃxxxchannel_free()À´ÊÍ·ÅͨµÀ×ÊÔ´£¬ ÀýÈçµ±Çý¶¯³ÌÐòÐ¶ÔØÊ±£¬²¢ÇÒÈç¹ûͨµÀÊý¾Ý½á¹¹ÊǶ¯Ì¬·ÖÅäµÄ£¬»òÕß Èç¹û²»Ê¹ÓÃsndbuf_alloc()½øÐлº³åÇø·ÖÅ䣬 ÔòÓ¦µ±ÊµÏÖÕâ¸öº¯Êý¡£


15.4.1.10 channel_getcaps

          struct pcmchan_caps *
          xxxchannel_getcaps(kobj_t obj, void *data)
          {
              return &xxx_caps;(1)
           }
(1)
Õâ¸öÀý³Ì·µ»ØÖ¸Ïò£¨Í¨³£¾²Ì¬¶¨ÒåµÄ£© pcmchan_caps½á¹¹µÄÖ¸Õ루ÔÚ sound/pcm/channel.hÖж¨Ò壩¡£Õâ¸ö½á¹¹ ±£´æ×Å×îСºÍ×î´ó²ÉÑùƵÂʺͱ»½ÓÊܵÄÉùÒô¸ñʽ¡£ÈκÎÉùÒôÇý¶¯ ³ÌÐò¶¼¿ÉÒÔ×÷Ϊһ¸ö·¶Àý¡£

15.4.1.11 ¸ü¶àº¯Êý

¡¡¡¡channel_reset(), channel_resetdone()ºÍ channel_notify()ÓÃÓÚÌØÊâÄ¿µÄ£¬Î´ÓëȨÍþÈËÊ¿ (Cameron Grant )½øÐÐ̽ÌÖ֮ǰ²»Ó¦µ±ÔÚÇý¶¯³ÌÐòÖÐʵÏÖËü¡£

¡¡¡¡²»ÔÞ³ÉʹÓÃchannel_setdir().


15.4.2 MIXER½Ó¿Ú

15.4.2.1 mixer_init

¡¡¡¡xxxmixer_init()³õʼ»¯Ó²¼þ£¬²¢¸æËß pcmʲô»ìÒôÆ÷É豸¿ÉÓÃÀ´²¥·ÅºÍ¼Òô¡£

          static int
          xxxmixer_init(struct snd_mixer *m)
          {
              struct xxx_info   *sc = mix_getdevinfo(m);
              u_int32_t v;

              [³õʼ»¯Ó²¼þ]

              [Ϊ²¥·Å»ìÒôÆ÷ÉèÖÃvÖÐÊʵ±µÄλ](1)
              mix_setdevs(m, v);
              [Ϊ¼Òô»ìÒôÆ÷ÉèÖÃvÖÐÊʵ±µÄλ]
              mix_setrecdevs(m, v)

              return 0;              
          }
(1)
ÉèÖÃÒ»¸öÕûÊýÖµÖеÄ룬²¢µ÷Óà mix_setdevs()ºÍ mix_setrecdevs()À´¸æËß pcm´æÔÚʲôÉ豸¡£

¡¡¡¡»ìÒôÆ÷µÄ붨Òå¿ÉÒÔÔÚsoundcard.hÖÐ ÕÒµ½¡££¨SOUND_MASK_XXXÖµºÍ SOUND_MIXER_XXXÒÆÎ»£©¡£


15.4.2.2 mixer_set

¡¡¡¡xxxmixer_set()Ϊ»ìÒôÆ÷É豸ÉèÖÃÒôÁ¿¼¶±ð (level)¡£

          static int
          xxxmixer_set(struct snd_mixer *m, unsigned dev, 
                           unsigned left, unsigned right)(1)
          {
              struct sc_info *sc = mix_getdevinfo(m);
              [ÉèÖÃÒôÁ¿¼¶±ð(level)]
              return left | (right << 8);(2)
          }
(1)
É豸±»Ö¸¶¨Îª SOUND_MIXER_XXX Öµ

ÔÚ·¶Î§[0-100]Ö®¼äÖ¸¶¨ÒôÁ¿Öµ¡£ÁãÖµÓ¦µ±ÈÃÉ豸¾²Òô¡£

(2)
ÓÉÓÚÓ²¼þ(ÒôÁ¿)¼¶±ð(level)¿ÉÄܲ»Æ¥ÅäÊäÈë±ÈÀý£¬»á³öÏÖ Ä³Ð©Ô²Õû£¬Àý³Ì·µ»ØÈçÉÏÃæËùʾµÄʵ¼Ê¼¶±ðÖµ£¨·¶Î§0-100ÄÚ£©¡£

15.4.2.3 mixer_setrecsrc

¡¡¡¡xxxmixer_setrecsrc()É趨¼ÒôÔ´É豸¡£

          static int
          xxxmixer_setrecsrc(struct snd_mixer *m, u_int32_t src)(1)
          {
              struct xxx_info *sc = mix_getdevinfo(m);

              [²é¿´srcÖеķÇÁãλ, ÉèÖÃÓ²¼þ]

              [¸üÐÂsrc·´Ó³Êµ¼Ê¶¯×÷]
              return src;(2)
           }
(1)
ÆÚÍûµÄ¼ÒôÉ豸ÓÉÒ»¸öλÓòÖ¸¶¨.
(2)
·µ»ØÉèÖÃÓÃÀ´Â¼ÒôµÄʵ¼ÊÉ豸¡£Ò»Ð©Çý¶¯³ÌÐòÖ»ÄÜÉèÖÃÒ»¸ö ¼ÒôÉ豸¡£Èç¹û³öÏÖ´íÎ󣬺¯ÊýÓ¦µ±·µ»Ø-1¡£

15.4.2.4 mixer_uninit, mixer_reinit

¡¡¡¡xxxmixer_uninit()Ó¦µ±È·±£²»»á·¢³öÈκΠÉùÒô£¬²¢ÇÒÈç¹û¿ÉÄÜÔòÓ¦µ±ÈûìÒôÆ÷Ó²¼þ¶Ïµç¡£

¡¡¡¡xxxmixer_reinit()Ó¦µ±È·±£»ìÒôÆ÷Ó²¼þ ¼Óµç£¬²¢ÇÒ»Ö¸´ËùÓв»ÊÜmixer_set()»ò mixer_setrecsrc()¿ØÖƵÄÉèÖá£


15.4.3 AC97½Ó¿Ú

¡¡¡¡AC97ÓÉ´øÓÐAC97±àÂë½âÂëÆ÷µÄÇý¶¯³ÌÐòʵÏÖ¡£ ËüÖ»ÓÐÈý¸ö·½·¨£º

  • xxxac97_init()·µ»ØÕÒµ½µÄ ac97±àÂë½âÂëÆ÷µÄÊýÄ¿¡£

  • ac97_read()Óë ac97_write()¶Áдָ¶¨µÄ¼Ä´æÆ÷¡£

¡¡¡¡The AC97½Ó¿ÚÓÉ pcmÖеÄAC97´úÂëÀ´Ö´Ðи߲ã²Ù×÷¡£²Î¿´ sound/pci/maestro3.c»ò sound/pci/ϺܶàÆäËûÄÚÈÝ×÷Ϊ·¶Àý¡£


µÚ16ÕÂ ¡¡PC Card

·­Ò룺spellar @SMTH.

¡¡¡¡±¾Õ½«ÌÖÂÛFreeBSDΪ±àдPC Card»òCardBusÉ豸µÄÇý¶¯³ÌÐò¶øÌṩµÄ»úÖÆ¡£ µ«Ä¿Ç°±¾ÎÄÖ»¼Ç¼ÁËÈçºÎÏòÏÖÓеÄpccardÇý¶¯³ÌÐòÖÐÌí¼ÓÇý¶¯³ÌÐò¡£


16.1 Ìí¼ÓÉ豸

¡¡¡¡ÏòËùÖ§³ÖµÄpccardÉ豸ÁбíÖÐÌí¼ÓÐÂÉ豸µÄ²½ÖèÒѾ­ÓëϵͳÔÚFreeBSD 4 ÖÐʹÓõķ½·¨²»Í¬ÁË¡£ÔÚÒÔǰµÄ°æ±¾ÖУ¬ÐèÒª±à¼­ /etcÖеÄÒ»¸öÎļþÀ´ÁгöÉ豸¡£´ÓFreeBSD 5.0¿ªÊ¼£¬ É豸Çý¶¯³ÌÐòÖªµÀËüÃÇÖ§³ÖʲôÉ豸¡£ÏÖÔÚÄÚºËÖÐÓÐÒ»¸öÊÜÖ§³ÖÉ豸µÄ±í£¬ Çý¶¯³ÌÐòÓÃËüÀ´Á¬½ÓÉ豸¡£


16.1.1 ¸ÅÀÀ

¡¡¡¡¿ÉÒÔÓÐÁ½ÖÖ·½·¨À´Ê¶±ðPC Card£¬ËûÃǶ¼»ùÓÚ¿¨É쵀 CISÐÅÏ¢¡£µÚÒ»ÖÖ·½·¨ÊÇʹÓÃÖÆÔìÉ̺ͲúÆ·µÄÊý×Ö±àºÅ¡£ µÚ¶þÖÖ·½·¨ÊÇʹÓÃÈ˿ɶÁµÄ×Ö·û´®£¬×Ö·û´®Ò²Êǰüº¬ÔÚCISÖС£PC Card×ÜÏß Ê¹Óü¯ÖÐʽÊý¾Ý¿âºÍһЩºêÀ´Ìṩһ¸öÒ×ÓõÄÉè¼ÆÄ£Ê½£¬ÈÃÇý¶¯³ÌÐòµÄ±àд ÕߺÜÈÝÒ×µØÈ·¶¨Æ¥ÅäÆäÇý¶¯³ÌÐòµÄÉ豸¡£

¡¡¡¡Ò»¸öºÜÆÕ±éµÄʵ¼ÊÇé¿öÊÇ£¬Ä³¸ö¹«Ë¾ÎªÒ»¿îPC Card²úÆ·¿ª·¢³ö²Î¿¼ Éè¼Æ£¬È»ºó°ÑÕâ¸öÉè¼ÆÂô¸øÁíÍâµÄ¹«Ë¾£¬ÒÔ±ãÔÚÊг¡ÉϳöÊÛ¡£ÄÇЩ¹«Ë¾¸Ä½ø Ô­Éè¼Æ£¬°ÑÏòËûÃǵÄÄ¿±ê¿Í»§Èº»òµØÀíÇøÓò³öÊÛ²úÆ·£¬²¢½«ËûÃÇ×Ô¼ºµÄÃû×Ö ·Åµ½¿¨ÖС£È»¶øËùνµÄ¶ÔÏÖÓп¨µÄ¸Ä½ø£¬¼´Ê¹×ö¹ýÈκÎÐ޸ģ¬ÕâЩÐÞ¸Äͨ³£ Ҳ΢ºõÆä΢¡£È»¶ø£¬ÎªÁËÇ¿»¯ËûÃÇ×Ô¼º°æ±¾µÄÆ·ÅÆ£¬ÕâЩ¹©»õÉ̳£³£»á°ÑËûÃÇ ¹«Ë¾µÄÃû×Ö·ÅÈëCIS¿Õ¼äµÄ¿É¶Á×Ö·û´®ÖУ¬È´²»»á¸Ä¶¯ÖÆÔìÉ̺ͲúÆ·µÄID¡£

¡¡¡¡¼øÓÚÒÔÉÏÇé¿ö£¬¶ÔÓÚFreeBSDÀ´ËµÊ¹ÓÃÊý×ÖID¿ÉÒÔ¼õС¹¤×÷Á¿¡£Í¬Ê±Ò² »á¼õС½«ID¼ÓÈ뵽ϵͳµÄ¹ý³ÌÖÐËù´øÀ´µÄ¸´ÔÓÐÔ¡£±ØÐë×Ðϸ¼ì²éË­ÊÇ¿¨µÄ ÕæÕýÖÆÔìÕߣ¬ÓÈÆäµ±Ìṩԭ¿¨µÄ¹©»õÉÌÔÚÖÐÐÄÊý¾Ý¿âÖÐÒѾ­ÓÐÒ»¸ö²»Í¬µÄID ʱ¡£Linksys£¬D-LinkºÍNetGearÊǾ­³£³öÊÛÏàͬÉè¼ÆµÄ¼¸¸öÃÀ¹úÖÆÔìÉÌ¡£ ÏàͬµÄÉè¼Æ¿ÉÄÜÔÚÈÕ±¾ÒÔÖîÈçBuffaloºÍCoregaµÄÃû×Ö³öÊÛ¡£È»¶ø£¬ÕâЩ É豸³£³£¾ßÓÐÏàͬµÄÖÆÔìÉ̺ͲúÆ·ID¡£

¡¡¡¡PC Card×ÜÏßÔÚÆäÖÐÐÄÊý¾Ý¿â /sys/dev/pccard/pccarddevsÖб£´æÁË¿¨µÄÐÅÏ¢£¬ µ«²»°üº¬ÄĸöÇý¶¯³ÌÐòÓëËüÃǹØÁªµÄÐÅÏ¢¡£ËüÒ²ÌṩÁËÒ»Ì׺꣬ÒÔÔÊÐíÔÚ Çý¶¯³ÌÐòÓÃÀ´ÉùÃ÷É豸µÄ±íÖÐÈÝÒ׵ش´½¨¼òµ¥ÌõÄ¿¡£

¡¡¡¡×îºó£¬Ä³Ð©·Ç³£µÍ¶ËµÄÉ豸¸ù±¾²»°üº¬ÖÆÔìÉ̱êʶ¡£ÕâЩÉ豸ÐèҪʹÓà ¿É¶ÁCIS×Ö·û´®À´Æ¥ÅäËüÃÇ¡£Èç¹ûÎÒÃDz»ÐèÒªÕâÖÖÓ¦¼±°ì·¨¸ÃÓжàºÃ£¬µ«¶ÔÓÚ Ä³Ð©·Ç³£µÍ¶ËÈ´·Ç³£Á÷ÐеÄCD-ROM²¥·ÅÆ÷À´ËµÈ´ÊDZØÐèµÄ¡£Í¨³£Ó¦µ±±ÜÃâ ʹÓÃÕâÖÖ·½·¨£¬µ«±¾½ÚÖл¹ÊÇÁгöÁ˺ܶàÉ豸£¬ÒòΪËüÃÇÊÇÔÚÈÏʶµ½PC CardÉÌÒµµÄOEM±¾ÖÊ֮ǰ¼ÓÈëµÄ£¬Ó¦µ±ÓÅÏÈʹÓà Êý×Ö·½·¨¡£


16.1.2 pccarddevsµÄ¸ñʽ

¡¡¡¡pccarddevsÎļþÓÐËĽڡ£µÚÒ»½ÚΪʹÓà ËüÃǵÄÄÇЩ¹©»õÉÌÁгöÁËÖÆÔìÉ̺ÅÂë¡£±¾½Ú°´Êý×ÖÅÅÐò¡£ÏÂÒ»½Ú°üº¬ÁË ÕâЩ¹©»õÉÌʹÓõÄËùÓвúÆ·£¬°üÀ¨ËûÃǵIJúÆ·IDºÅÂëºÍÃèÊö×Ö·û´®¡£ ÃèÊö×Ö·û´®Í¨³£²»»á±»Ê¹Óã¨Ïà·´£¬¼´Ê¹ÎÒÃÇ¿ÉÒÔÆ¥ÅäÊý×Ö°æ±¾ºÅ£¬ÎÒÃÇ ÈÔÈ»»ùÓÚÈ˿ɶÁµÄCISÉèÖÃÉ豸µÄÃèÊö£©¡£È»ºóΪʹÓÃ×Ö·û´®Æ¥Åä·½·¨µÄ ÄÇЩÉè±¸ÖØ¸´ÕâÁ½½ÚµÄ¶«Î÷¡£×îºó£¬ÎļþÈκεط½¿ÉÒÔʹÓÃC·ç¸ñµÄ×¢ÊÍ¡£

¡¡¡¡ÎļþµÄµÚÒ»½Ú°üº¬¹©»õÉÌID¡£Çë±£³ÖÁÐ±í°´Êý×ÖÅÅÐò¡£´ËÍ⣬ΪÁË ÄÜÓÐÒ»¸öͨÓÃÇåÎúµÄ±£´æµØÀ´·½±ãµØ±£´æÕâЩÐÅÏ¢£¬ÎÒÃÇÓëNetBSD¹²Ïí´Ë Îļþ£¬Òò´ËÇëЭµ÷¶Ô´ËÎļþµÄÈκθü¸Ä¡£ÀýÈ磺

vendor FUJITSU			0x0004  Fujitsu Corporation
vendor NETGEAR_2		0x000b  Netgear
vendor PANASONIC		0x0032	Matsushita Electric Industrial Co.
vendor SANDISK			0x0045	Sandisk Corporation

¡¡¡¡ÏÔʾÁ˼¸¸ö¹©»õÉÌID¡£ºÜ´ÕÇɵÄÊÇNETGEAR_2 ʵ¼ÊÉÏÊÇNETGEAR´ÓÆä¹ºÂò¿¨µÄOEM£¬¶ÔÄÇЩ¿¨Ìṩ֧³ÖµÄ×÷ÕßÄÇʱ²¢²»ÖªµÀ NETgearʹÓõÄÊDZðÈ˵ÄID¡£ÕâЩÌõÄ¿Ï൱ֱ½ÓÒ×¶®¡£Ã¿ÐÐÉ϶¼Óй©»õÉÌ ¹Ø¼ü×ÖÀ´Ö¸Ê¾±¾ÐеÄÀà±ð¡£Ò²Óй©»õÉ̵ÄÃû×Ö¡£Ãû×Ö½«»áÔÚpccarddevsÎļþ µÄºóÃæÖØ¸´³öÏÖ£¬Ãû×ÖÒ²»áÓÃÔÚÇý¶¯³ÌÐòµÄÆ¥Åä±íÖУ¬Òò´Ë±£³ÖËüµÄ¶ÌС ²¢ÇÒÊÇÓÐЧµÄC±êʶ·û¡£»¹ÓÐÒ»¸ö¸ø¹©»õÉ̵ÄÊ®Áù½øÖÆÊý×ÖID¡£²»ÒªÌí¼Ó 0xffffffff»ò0xffffÐÎʽµÄID£¬ ÒòΪËüÃÇÊDZ£ÁôID£¨Ç°ÕßÊÇ'¿ÕID¼¯ºÏ'£¬¶øºóÕßÓÐʱ»áÔÚÖÊÁ¿¼«Æä²îµÄ¿¨ÖÐ ¿´µ½£¬ÓÃÀ´Ö¸Ê¾none£©¡£×îºó»¹ÓйØÓÚÖÆ¿¨¹«Ë¾µÄÃèÊö×Ö·û´®¡£Õâ¸ö×Ö·û´® ÔÚFreeBSDÖгýÁËÓÃÓÚ×¢ÊÍÄ¿µÄÍⲢûÓб»Ê¹Óùý¡£

¡¡¡¡ÎļþµÄµÚ¶þ½Ú°üº¬²úÆ·. ÈçÄãÔÚÏÂÃæÀý×ÓÖп´µ½µÄ:

/* Allied Telesis K.K. */
product ALLIEDTELESIS LA_PCM	0x0002 Allied Telesis LA-PCM

/* Archos */
product	ARCHOS ARC_ATAPI	0x0043 MiniCD

¡¡¡¡¸ñʽÓ빩»õÉ̵ÄÄÇЩÐÐÏàËÆ¡£ÆäÖÐÓвúÆ·¹Ø¼ü×Ö¡£È»ºóÊǹ©»õÉÌÃû×Ö£¬ ÓÉÉÏÃæÖØ¸´¶øÀ´¡£ºóÃæ¸ú×ŲúÆ·Ãû×Ö£¬´ËÃû×ÖÔÚÇý¶¯³ÌÐòÖÐʹÓã¬ÇÒÓ¦µ± ÊÇÒ»¸öÓÐЧC±êʶ·û£¬µ«¿ÉÒÔÒÔÊý×Ö¿ªÍ·¡£È»ºóÊÇ¿¨µÄÊ®Áù½øÖƲúÆ·ID¡£ ¹©»õÉÌͨ³£¶Ô0xffffffffºÍ 0xffffÓÐÏàͬµÄÔ¼¶¨¡£×îºóÊǹØÓÚÉ豸×ÔÉíµÄ×Ö·û´® ÃèÊö¡£ÓÉÓÚFreeBSDµÄpccard×ÜÏßÇý¶¯³ÌÐò»á´ÓÈ˿ɶÁµÄCISÌõÄ¿´´½¨Ò»¸ö ×Ö·û´®£¬Òò´ËÕâ¸ö×Ö·û´®ÔÚFreeBSDÖÐͨ³£²»±»Ê¹Ó㬵«Ä³Ð©CISÌõÄ¿²»ÄÜ Âú×ãÒªÇóµÄÇé¿öÏ»¹¿ÉÄÜʹÓᣲúÆ·°´ÖÆÔìÉ̵Ä×Öĸ˳ÐòÅÅÐò£¬È»ºóÔÙ°´ ²úÆ·IDµÄÊý×ÖÅÅÐò¡£Ã¿¸öÖÆÔìÉÌÌõĿǰÓÐÒ»ÌõC×¢ÊÍ£¬ÌõĿ֮¼äÓÐÒ»¸ö¿ÕÐС£

¡¡¡¡µÚÈý½ÚºÜÏóÇ°ÃæµÄ¹©»õÉÌÒ»½Ú£¬µ«ËùÓɵÄÖÆÔìÉÌIDΪ -1¡£-1ÔÚFreeBSD pccard×ÜÏß ´úÂëÖÐÒâζ×Å¡°Æ¥Åä·¢ÏÖµÄÈκζ«Î÷¡±¡£ÓÉÓÚËüÃÇÊÇC±êʶ·û£¬ ËüÃǵÄÃû×Ö±ØÐëΨһ¡£³ý´ËÖ®Íâ¸ñʽµÈͬÓÚÎļþµÄµÚÒ»½Ú¡£

¡¡¡¡×îºóÒ»½Ú°üº¬ÄÇЩ±ØÐëÓÃ×Ö·û´®Æ¥ÅäµÄ¿¨¡£ÕâÒ»½ÚµÄ¸ñʽÓëͨÓà ½ÚµÄ¸ñʽÓе㲻ͬ£º

product ADDTRON AWP100		{ "Addtron", "AWP-100&spWireless&spPCMCIA", "Version&sp01.02", NULL }
product ALLIEDTELESIS WR211PCM	{ "Allied&spTelesis&spK.K.", "WR211PCM", NULL, NULL } Allied Telesis WR211PCM

¡¡¡¡ÎÒÃÇÒѾ­ÊìϤÁ˲úÆ·¹Ø¼ü×Ö£¬ºó¸ú¹©»õÉÌÃû×Ö£¬È»ºóÔÙ¸ú¿¨µÄÃû×Ö£¬ ¾ÍÏóÔÚÎļþµÚ¶þ½ÚÖÐÄÇÑù¡£È»¶ø£¬ÕâÖ®ºó¾ÍÓëÄǸñʽ²»Í¬ÁË¡£ÓÐÒ»¸ö {}·Ö×飬ºó¸ú¼¸¸ö×Ö·û´®¡£ÕâЩ×Ö·û´®¶ÔÓ¦CIS_INFOÈýÔª×éÖж¨ÒåµÄ ¹©»õÉÌ£¬²úÆ·ºÍ¶îÍâÐÅÏ¢¡£ÕâЩ×Ö·û´®±»²úÉú pccarddevs.hµÄ³ÌÐò¹ýÂË£¬½« &spÌæ»»Îª ʵ¼ÊµÄ¿Õ¸ñ¡£¿ÕÌõÄ¿Òâζ×ÅÌõÄ¿µÄÕⲿ·ÖÓ¦µ±±»ºöÂÔ¡£ÔÚÎÒÑ¡ÔñµÄÀý×ÓÖÐ ÓÐÒ»¸ö´íÎóµÄÌõÄ¿¡£³ý·Ç¶Ô¿¨µÄ²Ù×÷À´ËµÖÁ¹ØÖØÒª£¬·ñÔò²»Ó¦µ±ÔÚÆäÖÐ °üº¬°æ±¾ºÅ¡£ÓÐʱ¹©»õÉÌÔÚÕâ¸ö×Ö¶ÎÖлáÓп¨µÄºÜ¶à²»Í¬°æ±¾£¬ÕâЩ°æ±¾ ¶¼Äܹ¤×÷£¬ÕâÖÖÇé¿öÏÂÄÇЩÐÅÏ¢Ö»»áÈÃÄÇЩӵÓÐÏàËÆ¿¨µÄÈËÔÚFreeBSDÖÐ ¸üÄÑÒÔʹÓá£ÓÐʱµ±¹©»õÉ̳öÓÚÊг¡¿¼ÂÇ£¨¿ÉÓÃÐÔ£¬¼Û¸ñµÈµÈ£©£¬Ï£Íû³öÊÛ Í¬Ò»Æ·ÅÆÏµĺܶ಻ͬ²¿·Öʱ£¬ÕâÒ²ÊÇÓбØÒªµÄ¡£Èç¹ûÕâÑù£¬ÔòÔÚÄÇЩ ¹©»õÉÌÈÔÈ»±£³ÖÏàͬµÄÖÆÔìÉÌ/²úÆ·¶ÔµÄÉÙ¼ûÇé¿öÏ£¬ÄÜ·ñÇø·Ö¿ª¿¨ÖÁ¹Ø ÖØÒª. ´Ëʱ²»ÄÜʹÓÃÕýÔò±í´ïʽƥÅä¡£


16.1.3 ̽²âÀý³ÌÑùÀý

¡¡¡¡Òª¶®µÃÈçºÎÏòËùÖ§³ÖµÄÉ豸ÁбíÖÐÌí¼ÓÉ豸£¬¾Í±ØÐë¶®µÃºÜ¶àÇý¶¯³ÌÐò ¶¼ÓеÄ̽²âºÍ/»òÆ¥ÅäÀý³Ì¡£ÓÉÓÚҲΪÀÏ¿¨ÌṩÁËÒ»¸ö¼æÈݲ㣬ÕâÔÚ FreeBSD 5.xÖÐÓÐÒ»µã¸´ÔÓ¡£ÓÉÓÚÖ»ÊÇwindow-dressing²»Í¬£¬Õâ¶ù¸ø³öÁË Ò»¸öÀíÏ뻯µÄ°æ±¾¡£

static const struct pccard_product wi_pccard_products[] = {
	PCMCIA_CARD(3COM, 3CRWE737A, 0),
	PCMCIA_CARD(BUFFALO, WLI_PCM_S11, 0),
	PCMCIA_CARD(BUFFALO, WLI_CF_S11G, 0),
	PCMCIA_CARD(TDK, LAK_CD011WL, 0),
	{ NULL }
};

static int
wi_pccard_probe(dev)
	device_t	dev;
{
	const struct pccard_product *pp;

	if ((pp = pccard_product_lookup(dev, wi_pccard_products,
	    sizeof(wi_pccard_products[0]), NULL)) != NULL) {
		if (pp->pp_name != NULL)
			device_set_desc(dev, pp->pp_name);
		return (0);
	}
	return (ENXIO);
}

¡¡¡¡Õâ¶ùÎÒÃÇÓÐÒ»¸ö¿ÉÒÔÆ¥ÅäÉÙÊý¼¸¸öÉ豸µÄ¼òµ¥pccard̽²âÀý³Ì¡£ÈçÉÏÃæ ËùÌáµ½£¬Ãû×Ö¿ÉÄܲ»Í¬£¨Èç¹û²»ÊÇ foo_pccard_probe()Ôò¾ÍÊÇ foo_pccard_match()£©¡£º¯Êý pccard_product_lookup()ÊÇÒ»¸öͨÓú¯Êý£¬Ëü±éÀú ±í²¢·µ»ØÖ¸ÏòËüËùÆ¥ÅäµÄµÚÒ»ÏîµÄÖ¸Õ롣һЩÇý¶¯³ÌÐò¿ÉÄÜʹÓÃÕâ¸ö»úÖÆÀ´ ½«Ä³Ð©¿¨µÄ¸½¼ÓÐÅÏ¢´«µÝµ½Çý¶¯³ÌÐòµÄÆäËü²¿·Ö£¬Òò´Ë±íÖпÉÄÜÓÐЩ±äÌå¡£ ΨһµÄÒªÇó¾ÍÊÇÈç¹ûÄãÓÐÒ»¸ö²»Í¬µÄ±í£¬ÔòÈñíµÄ½á¹¹µÄµÚÒ»¸öÔªËØÎª ½á¹¹pccard_product¡£

¡¡¡¡¹Û²ìһϱíwi_pccard_products¾Í»á·¢ÏÖ£¬ ËùÓÐÌõÄ¿¶¼ÊÇ PCMCIA_CARD(foo£¬ bar£¬ baz)µÄÐÎʽ¡£ foo²¿·ÖΪÀ´×Ô pccarddevsµÄÖÆÔìÉÌID¡£ bar²¿·ÖΪ²úÆ·¡£ bazΪ´Ë¿¨ËùÆÚÍûµÄ¹¦Äܺš£Ðí¶àpccards ¿ÉÒÔÓжà¸ö¹¦ÄÜ£¬ÐèÒªÓÐ°ì·¨Çø·Ö¿ª¹¦ÄÜ1ºÍ¹¦ÄÜ0¡£Äã¿ÉÒÔ¿´Ò»Ï PCMCIA_CARD_D£¬Ëü°üÀ¨ÁËÀ´×Ô pccarddevsÎļþµÄÉ豸ÃèÊö¡£ÄãÒ²¿ÉÒÔ¿´¿´ PCMCIA_CARD2ºÍ PCMCIA_CARD2_D£¬µ±ÄãÐèÒª°´ ¡°Ê¹ÓÃĬÈÏÃèÊö¡±ºÍ¡°´ÓpccarddevsÖÐÈ¡µÃ¡± ×ö·¨£¬Í¬Ê±Æ¥ÅäCIS×Ö·û´®ºÍÖÆÔìÉ̺ÅÂëʱ¾Í»áÓõ½ËüÃÇ¡£


16.1.4 ½«ËüºÏÔÚÒ»Æð

¡¡¡¡Òò´Ë£¬ÎªÁËÒ»¸öÔö¼ÓÐÂÉ豸£¬±ØÐë½øÐÐÏÂÃæ²½Öè¡£Ê×ÏÈ£¬±ØÐë´ÓÉ豸 »ñµÃ±êʶÐÅÏ¢¡£Íê³ÉÕâ¸ö×îÈÝÒ׵ķ½·¨¾ÍÊǽ«É豸²åÈëµ½PC Card»òCF²ÛÖУ¬ ²¢·¢³ödevinfo -v¡£Äã¿ÉÄܻῴµ½Ò»Ð©ÀàËÆÏÂÃæµÄ ¶«Î÷£º

        cbb1 pnpinfo vendor=0x104c device=0xac51 subvendor=0x1265 subdevice=0x0300 class=0x060700 at slot=10 function=1
          cardbus1
          pccard1
            unknown pnpinfo manufacturer=0x026f product=0x030c cisvendor="BUFFALO" cisproduct="WLI2-CF-S11" function_type=6 at function=0

¡¡¡¡×÷ΪÊä³öµÄÒ»²¿·Ö¡£ÖÆÔìÉ̺ͲúƷΪ²úÆ·µÄÊý×ÖID¡£¶øcisvenderºÍ cisproductΪCISÖÐÌṩµÄÃèÊö±¾²úÆ·µÄ×Ö·û´®¡£

¡¡¡¡ÓÉÓÚÎÒÃÇÊ×ÏÈÏëÓÅÏÈʹÓÃÊý×ÖÑ¡ÏÒò´ËÊ×Ïȳ¢ÊÔ´´½¨»ùÓڴ˵ÄÌõÄ¿¡£ ΪÁËʾÀý£¬ÉÏÃæµÄ¿¨ÒѾ­±»ÉÔÉÔÐé¹¹»¯ÁË¡£ÎÒÃÇ¿´µ½µÄ¹©»õÉÌΪBUFFALO£¬ ËüÒѾ­ÓÐÒ»¸öÌõÄ¿ÁË£º

vendor BUFFALO			0x026f	BUFFALO (Melco Corporation)

¡¡¡¡ÕâÑùÎÒÃǾͿÉÒÔÁË¡£ÎªÕâ¸ö¿¨²éÕÒÒ»¸öÌõÄ¿£¬µ«ÎÒÃÇûÓз¢ÏÖ¡£µ«ÎÒÃÇ ·¢ÏÖ£º

/* BUFFALO */
product BUFFALO WLI_PCM_S11	0x0305	BUFFALO AirStation 11Mbps WLAN
product BUFFALO LPC_CF_CLT	0x0307	BUFFALO LPC-CF-CLT
product	BUFFALO	LPC3_CLT	0x030a	BUFFALO LPC3-CLT Ethernet Adapter
product BUFFALO WLI_CF_S11G	0x030b	BUFFALO AirStation 11Mbps CF WLAN

¡¡¡¡ÎÒÃǾͿÉÒÔÏòpccarddevsÖÐÌí¼Ó£º

product BUFFALO WLI2_CF_S11G	0x030c	BUFFALO AirStation ultra 802.11b CF

¡¡¡¡Ä¿Ç°£¬ÐèÒªÒ»¸öÊÖ¶¯²½ÖèÀ´ ÖØÐ²úÉúpccarddevs.h£¬ÓÃÀ´½«ÕâЩ±êʶ·ûת»» µ½¿Í»§Çý¶¯³ÌÐò¡£ÄãÔÚÇý¶¯³ÌÐòÖÐʹÓÃËüÃÇ֮ǰ±ØÐëÍê³ÉÏÂÃæ²½Ö裺

# cd src/sys/dev/pccard
# make -f Makefile.pccarddevs

¡¡¡¡Ò»µ©Íê³ÉÁËÕâЩ²½Ö裬Äã¾Í¿ÉÒÔÏòÇý¶¯³ÌÐòÖÐÌí¼Ó¿¨ÁË¡£ÕâÖ»ÊÇÒ»¸ö Ìí¼ÓÒ»Ðеļòµ¥²Ù×÷£º

static const struct pccard_product wi_pccard_products[] = {
	PCMCIA_CARD(3COM, 3CRWE737A, 0),
	PCMCIA_CARD(BUFFALO, WLI_PCM_S11, 0),
	PCMCIA_CARD(BUFFALO, WLI_CF_S11G, 0),
+	PCMCIA_CARD(BUFFALO, WLI_CF2_S11G, 0),
	PCMCIA_CARD(TDK, LAK_CD011WL, 0),
	{ NULL }
};

¡¡¡¡×¢Ò⣬ÎÒÔÚÎÒÌí¼ÓµÄÐÐÇ°Ãæ°üº¬ÁË'+'£¬µ«ÕâÖ»ÊÇ ÓÃÀ´Ç¿µ÷ÕâÒ»ÐС£²»Òª°ÑËüÌí¼Óµ½Êµ¼ÊÇý¶¯³ÌÐòÖС£Ò»µ©ÄãÌí¼ÓÁËÕâÐУ¬¾Í ¿ÉÒÔÖØÐ±àÒëÄں˻òÄ£¿é£¬²¢ÊÔ×Å¿´ËüÊÇ·ñÄÜʶ±ðÉ豸¡£Èç¹ûËüʶ±ð³öÉ豸 ²¢Äܹ¤×÷£¬ÇëÌá½»²¹¶¡¡£Èç¹ûËü²»¹¤×÷£¬ÇëÕÒ³öÈÃËü¹¤×÷ËùÐèÒªµÄ¶«Î÷²¢ Ìá½»Ò»¸ö²¹¶¡¡£Èç¹ûËü¸ù±¾²»Ê¶±ðÉ豸£¬ÄÇôÄã¿ÉÄÜ×ö´íÁËʲô£¬Ó¦µ±ÖØÐ ¼ì²éÿһ²½¡£

¡¡¡¡Èç¹ûÄãÊÇÒ»¸öFreeBSDÔ´´úÂëµÄcommitter£¬²¢ÇÒËùÓж«Î÷¿´ÆðÀ´¶¼ Õý³£¹¤×÷£¬ÔòÄãÓ¦µ±°ÑÕâЩ¸Ä±äÌá½»µ½Ê÷ÖС£È»¶øÓÐЩС¼¼ÇɵĶ«Î÷Äã ÐèÒª¿¼ÂÇ¡£Ê×ÏÈ£¬Äã±ØÐëÌá½»pccarddevsÎļþµ½ Ê÷ÖС£Íê³Éºó£¬Äã±ØÐëÖØÐ²úÉúpccarddevs.h ²¢½«Ëü×÷ΪÁíÒ»´ÎÌá½»À´Ìá½»£¨ÕâÊÇΪÁËÈ·±£ÕýÈ·µÄ $FreeBSD$±êÇ©»áÁôÔÚºóÃæµÄÎļþÖУ©¡£×îºó£¬ÄãÐèÒª°Ñ ÆäËü¶«Î÷Ìá½»µ½Çý¶¯³ÌÐò¡£


16.1.5 Ìá½»ÐÂÉ豸

¡¡¡¡ºÜ¶àÈËÖ±½Ó°ÑÐÂÉ豸µÄÌõÄ¿·¢Ë͸ø×÷Õß¡£Çë²»ÒªÄÇÑù×ö¡£Ç뽫ËüÃÇ×÷Ϊ PRÀ´Ìá½»£¬²¢½«PRºÅÂë·¢Ë͸ø×÷ÕßÓÃÓڼǼ¡£ÕâÑùÈ·±£ÌõÄ¿²»»á¶ªÊ§¡£Ìá½» PRʱ£¬²¹¶¡ÖÐûÓбØÒª°üº¬pccardevs.hµÄdiff£¬ ÒòΪÄÇЩ¶«Î÷¿ÉÒÔÖØÐ²úÉú¡£°üº¬É豸µÄÃèÊöºÍ¿Í»§Çý¶¯³ÌÐòµÄ²¹¶¡ÊDZØÒª µÄ¡£Èç¹ûÄã²»ÖªµÀÃû×Ö£¬Ê¹ÓÃOEM99×÷ΪÃû×Ö£¬×÷Õß½«»áµ÷²éºóÏàÓ¦µØµ÷Õû OEM99¡£Ìá½»Õß²»Ó¦µ±Ìá½»OEM99£¬¶øÓ¦¸ÃÕÒµ½×î¸ßµÄOEMÌõÄ¿²¢Ìá½»¸ßÓÚÄǸö µÄÒ»¸ö¡£

µÚIII²¿·Ö. ¸½Â¼

Ŀ¼
²Î¿¼ÊéÄ¿

²Î¿¼ÊéÄ¿

[1] Marshall Kirk McKusick¡¢ Keith Bostic¡¢ Michael J Karels ºÍ John S Quarterman, 1996, 0-201-54979-4, Addison-Wesley Publishing Company, Inc., The Design and Implementation of the 4.4 BSD Operating System, 1-2.

±¸×¢

[1]

ÓÐЩ¹¤¾ßÈçdisklabel(8) »áʹÓÃÕâÒ»ÇøÓò´æ´¢ÐÅÏ¢£¬Ö÷ÒªÊÇÔÚµÚ¶þÉÈÇøÀï¡£

[2]

bus_generic_read_ivar(9) and bus_generic_write_ivar(9)


±¾ÎĵµºÍÆäËüÎĵµ¿É´ÓÕâÀïÏÂÔØ£ºftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.

Èç¹û¶ÔÓÚFreeBSDÓÐÎÊÌ⣬ÇëÏÈÔĶÁÎĵµ£¬Èç²»Äܽâ¾öÔÙÁªÏµ<questions@FreeBSD.org>.
¹ØÓÚ±¾ÎĵµµÄÎÊÌâÇë·¢ÐÅÁªÏµ <doc@FreeBSD.org>.