·¢²©ÎÄ
²Ý±¾Ö²Îï

http://blog.chinaunix.net/space.php?uid=20246210

ÎÒ˼¹ÊÎÒÔÚ¡£¡£¡£ blowingwind@126.com   
¸öÈË×ÊÁÏ
  • ²©¿Í·ÃÎÊ£º226596
  • ²©ÎÄÊýÁ¿£º113
  • ²©¿Í»ý·Ö£º3030
  • ²©¿ÍµÈ¼¶£ºÖÐУ
  • ¹Ø×¢ÈËÆø£º 1
  • ×¢²áʱ¼ä£º2006-03-05 01:00:11
¶©ÔÄÎҵIJ©¿Í
  • ¶©ÔÄ
  • ¶©Ôĵ½Ïʹû
  • ¶©Ôĵ½×¥Ïº
  • ¶©Ôĵ½Google
×ÖÌå´óС£º´ó ÖРС²©ÎÄ
·ÖÀࣺ linuxÉ豸Çý¶¯

¡¡¡¡Linux²Ù×÷ÏµÍ³ÍøÂçÇý¶¯³ÌÐò±àд
(4334 ¸ö×Öì¶´ËÆªÌû×Ó)
(ÒÑÔĶÁ: 1984 ´Î)




·¢ÐÅÈË: Bordi (do it), ÐÅÇø: Linux
±ê Ìâ: LinuxÇý¶¯³ÌÐò±àд
·¢ÐÅÕ¾: ÍøÒ× BBS (Sun Aug 8 11:38:15 1999), תÐÅ
¹¤×÷ÐèҪдÁËÎÒÃǹ«Ë¾Ò»¿éÍø¿¨µÄLinuxÇý¶¯³ÌÐò¡£¾­ÀúÒ»¸ö´ÓÎÞµ½ÓеĹý³Ì£¬
Éî¸Ð¼¼Êõ½»Á÷µÄÖØÒª¡£Linux×÷ΪÌôս΢Èí¢¶ÏµÄÇ¿ÓÐÁ¦ÎäÆ÷£¬ÈÕÒæÊܵ½´ó¼ÒµÄϲ
°®¡£ÕæÏ£ÍûËýÄÜÔÚÖйúѸËٳɳ¤¡£°Ñ³ÌÐòÎĵµÌù³öÀ´£¬Ï£ÍûºÍ´ó¼Ò̽ÌÖLinux¼¼Êõ
ºÍÓ¦Ó㬴ٽøLinuxÔÚÖйúµÄÆÕ¼°¡£
±¾ÎÄ¿ÉËæÒâ×ªÔØ£¬µ«Çë²»ÒªÔÚÓ¯ÀûÐÔ³ö°æÎïÉÏ¿¯µÇ¡£
------------------ Linux²Ù×÷ÏµÍ³ÍøÂçÇý¶¯³ÌÐò±àд -------------------
------------ Contact the author by mailto:bordi@bordi.dhs.org ------
Linux²Ù×÷ÏµÍ³ÍøÂçÇý¶¯³ÌÐò±àд
Ò».LinuxϵͳÉ豸Çý¶¯³ÌÐò¸ÅÊö
1.1 LinuxÉ豸Çý¶¯³ÌÐò·ÖÀà
1.2 ±àдÇý¶¯³ÌÐòµÄһЩ»ù±¾¸ÅÄî
¶þ.LinuxÏµÍ³ÍøÂçÉ豸Çý¶¯³ÌÐò
2.1 ÍøÂçÇý¶¯³ÌÐòµÄ½á¹¹
2.2 ÍøÂçÇý¶¯³ÌÐòµÄ»ù±¾·½·¨
2.3 ÍøÂçÇý¶¯³ÌÐòÖÐÓõ½µÄÊý¾Ý½á¹¹
2.4 ³£ÓõÄϵͳ֧³Ö
Èý.±àдLinuxÍøÂçÇý¶¯³ÌÐòÖпÉÄÜÓöµ½µÄÎÊÌâ
3.1 ÖжϹ²Ïí
3.2 Ó²¼þ·¢ËÍæʱµÄ´¦Àí
3.3 Á÷Á¿¿ØÖÆ(flow control)
3.4 µ÷ÊÔ
ËÄ.½øÒ»²½µÄÔĶÁ
Îå.ÔÓÏî
Ò».LinuxϵͳÉ豸Çý¶¯³ÌÐò¸ÅÊö
1.1 LinuxÉ豸Çý¶¯³ÌÐò·ÖÀà
LinuxÉ豸Çý¶¯³ÌÐòÔÚLinuxµÄÄÚºËÔ´´úÂëÖÐÕ¼ÓкܴóµÄ±ÈÀý£¬Ô´´úÂëµÄ³¤¶ÈÈÕ
ÒæÔö¼Ó£¬Ö÷ÒªÊÇÇý¶¯³ÌÐòµÄÔö¼Ó¡£ÔÚLinuxÄں˵IJ»¶ÏÉý¼¶¹ý³ÌÖУ¬Çý¶¯³ÌÐòµÄ½á¹¹
»¹ÊÇÏà¶ÔÎȶ¨¡£ÔÚ2.0.xxµ½2.2.xxµÄ±ä¶¯ÀÇý¶¯³ÌÐòµÄ±àд×öÁËһЩ¸Ä±ä£¬µ«ÊÇ
´Ó2.0.xxµÄÇý¶¯µ½2.2.xxµÄÒÆÖ²Ö»Ðè×öÉÙÁ¿µÄ¹¤×÷¡£
LinuxϵͳµÄÉ豸·ÖΪ×Ö·ûÉ豸(char device)£¬¿éÉ豸(block device)ºÍÍøÂç
É豸(network device)ÈýÖÖ¡£×Ö·ûÉ豸ÊÇÖ¸´æÈ¡Ê±Ã»Óлº´æµÄÉ豸¡£¿éÉ豸µÄ¶Áд
¶¼Óлº´æÀ´Ö§³Ö£¬²¢ÇÒ¿éÉ豸±ØÐëÄܹ»Ëæ»ú´æÈ¡(random access)£¬×Ö·ûÉ豸ÔòûÓÐ
Õâ¸öÒªÇó¡£µäÐ͵Ä×Ö·ûÉ豸°üÀ¨Êó±ê£¬¼üÅÌ£¬´®Ðпڵȡ£¿éÉ豸Ö÷Òª°üÀ¨Ó²ÅÌÈíÅÌ
É豸£¬CD-ROMµÈ¡£Ò»¸öÎļþϵͳҪ°²×°½øÈë²Ù×÷ϵͳ±ØÐëÔÚ¿éÉ豸ÉÏ¡£
ÍøÂçÉ豸ÔÚLinuxÀï×öרÃŵĴ¦Àí¡£LinuxµÄÍøÂçϵͳÖ÷ÒªÊÇ»ùÓÚBSD unixµÄsocket

»úÖÆ¡£ÔÚϵͳºÍÇý¶¯³ÌÐòÖ®¼ä¶¨ÒåÓÐרÃŵÄÊý¾Ý½á¹¹(sk_buff)½øÐÐÊý¾ÝµÄ´«µÝ¡£Ïµ
ͳÀïÖ§³Ö¶Ô·¢ËÍÊý¾ÝºÍ½ÓÊÕÊý¾ÝµÄ»º´æ£¬ÌṩÁ÷Á¿¿ØÖÆ»úÖÆ£¬Ìṩ¶Ô¶àЭÒéµÄÖ§³Ö¡£
1.2 ±àдÇý¶¯³ÌÐòµÄһЩ»ù±¾¸ÅÄî
ÎÞÂÛÊÇʲô²Ù×÷ϵͳµÄÇý¶¯³ÌÐò£¬¶¼ÓÐһЩͨÓõĸÅÄî¡£²Ù×÷ϵͳÌṩ¸øÇý¶¯
³ÌÐòµÄÖ§³ÖÒ²´óÖÂÏàͬ¡£ÏÂÃæ¼òµ¥½éÉÜÒ»ÏÂÍøÂçÉ豸Çý¶¯³ÌÐòµÄһЩ»ù±¾ÒªÇó¡£
1.2.1 ·¢ËͺͽÓÊÕ
ÕâÊÇÒ»¸öÍøÂçÉ豸×î»ù±¾µÄ¹¦ÄÜ¡£Ò»¿éÍø¿¨Ëù×öµÄÎ޷ǾÍÊÇÊÕ·¢¹¤×÷¡£ËùÒÔÇý
¶¯³ÌÐòÀïÒª¸æËßϵͳÄãµÄ·¢Ëͺ¯ÊýÔÚÄÄÀϵͳÔÚÓÐÊý¾ÝÒª·¢ËÍʱ¾Í»áµ÷ÓÃÄãµÄ·¢
ËͳÌÐò¡£»¹ÓÐÇý¶¯³ÌÐòÓÉÓÚÊÇÖ±½Ó²Ù×ÝÓ²¼þµÄ£¬ËùÒÔÍøÂçÓ²¼þÓÐÊý¾ÝÊÕµ½×îÏÈÄܵÃ
µ½Õâ¸öÊý¾ÝµÄÒ²¾ÍÊÇÇý¶¯³ÌÐò£¬Ëü¸ºÔð°ÑÕâЩԭʼÊý¾Ý½øÐбØÒªµÄ´¦ÀíÈ»ºóË͸øÏµ
ͳ¡£ÕâÀ²Ù×÷ϵͳ±ØÐëÒªÌṩÁ½¸ö»úÖÆ£¬Ò»¸öÊÇÕÒµ½Çý¶¯³ÌÐòµÄ·¢Ëͺ¯Êý£¬Ò»¸ö
ÊÇÇý¶¯³ÌÐò°ÑÊÕµ½µÄÊý¾ÝË͸øÏµÍ³¡£
1.2.2 ÖжÏ
ÖжÏÔÚÏÖ´ú¼ÆËã»ú½á¹¹ÖÐÓÐÖØÒªµÄµØÎ»¡£²Ù×÷ϵͳ±ØÐëÌṩÇý¶¯³ÌÐòÏìÓ¦ÖжÏ
µÄÄÜÁ¦¡£Ò»°ãÊǰÑÒ»¸öÖжϴ¦Àí³ÌÐò×¢²áµ½ÏµÍ³ÖÐÈ¥¡£²Ù×÷ϵͳÔÚÓ²¼þÖжϷ¢Éúºó
µ÷ÓÃÇý¶¯³ÌÐòµÄ´¦Àí³ÌÐò¡£LinuxÖ§³ÖÖжϵĹ²Ïí£¬¼´¶à¸öÉ豸¹²ÏíÒ»¸öÖжϡ£
1.2.3 ʱÖÓ
ÔÚʵÏÖÇý¶¯³ÌÐòʱ£¬ºÜ¶àµØ·½»áÓõ½Ê±ÖÓ¡£ÈçijЩЭÒéÀïµÄ³¬Ê±´¦Àí£¬Ã»ÓÐÖÐ
¶Ï»úÖÆµÄÓ²¼þµÄÂÖѯµÈ¡£²Ù×÷ϵͳӦΪÇý¶¯³ÌÐòÌṩ¶¨Ê±»úÖÆ¡£Ò»°ãÊÇÔÚÔ¤¶¨µÄʱ
¼ä¹ýÁËÒÔºó»Øµ÷×¢²áµÄʱÖÓº¯Êý¡£ÔÚÍøÂçÇý¶¯³ÌÐòÖУ¬Èç¹ûÓ²¼þûÓÐÖжϹ¦ÄÜ£¬¶¨
ʱÆ÷¿ÉÒÔÌṩÂÖѯ(poll)·½Ê½¶ÔÓ²¼þ½øÐдæÈ¡¡£»òÕßÊÇʵÏÖijЩЭÒéʱÐèÒªµÄ³¬Ê±
ÖØ´«µÈ¡£
¶þ.LinuxÏµÍ³ÍøÂçÉ豸Çý¶¯³ÌÐò
2.1 ÍøÂçÇý¶¯³ÌÐòµÄ½á¹¹
ËùÓеÄLinuxÍøÂçÇý¶¯³ÌÐò×ñѭͨÓõĽӿڡ£Éè¼ÆÊ±²ÉÓõÄÊÇÃæÏò¶ÔÏóµÄ·½·¨¡£
Ò»¸öÉ豸¾ÍÊÇÒ»¸ö¶ÔÏó(device ½á¹¹)£¬ËüÄÚ²¿ÓÐ×Ô¼ºµÄÊý¾ÝºÍ·½·¨¡£Ã¿Ò»¸öÉ豸µÄ
·½·¨±»µ÷ÓÃʱµÄµÚÒ»¸ö²ÎÊý¶¼ÊÇÕâ¸öÉ豸¶ÔÏó±¾Éí¡£ÕâÑùÕâ¸ö·½·¨¾Í¿ÉÒÔ´æÈ¡×ÔÉí
µÄÊý¾Ý(ÀàËÆÃæÏò¶ÔÏó³ÌÐòÉè¼ÆÊ±µÄthisÒýÓÃ)¡£
Ò»¸öÍøÂçÉ豸×î»ù±¾µÄ·½·¨Óгõʼ»¯¡¢·¢ËͺͽÓÊÕ¡£
------------------- ---------------------
|deliver packets | |receive packets queue|
|(dev_queue_xmit()) | |them(netif_rx()) |
------------------- ---------------------
| | /
/ | |
-------------------------------------------------------
| methods and variables(initialize,open,close,hard_xmit,|
| interrupt handler,config,resources,status...) |
-------------------------------------------------------
| | /
/ | |
----------------- ----------------------
|send to hardware | |receivce from hardware|
----------------- ----------------------
| | /
/ | |
-----------------------------------------------------
| hardware media |
-----------------------------------------------------
³õʼ»¯³ÌÐòÍê³ÉÓ²¼þµÄ³õʼ»¯¡¢deviceÖбäÁ¿µÄ³õʼ»¯ºÍϵͳ×ÊÔ´µÄÉêÇë¡£·¢ËÍ
³ÌÐòÊÇÔÚÇý¶¯³ÌÐòµÄÉϲãЭÒé²ãÓÐÊý¾ÝÒª·¢ËÍʱ×Ô¶¯µ÷Óõġ£Ò»°ãÇý¶¯³ÌÐòÖв»¶Ô·¢
ËÍÊý¾Ý½øÐлº´æ£¬¶øÊÇÖ±½ÓʹÓÃÓ²¼þµÄ·¢Ë͹¦ÄܰÑÊý¾Ý·¢ËͳöÈ¥¡£½ÓÊÕÊý¾ÝÒ»°ãÊÇͨ
¹ýÓ²¼þÖжÏÀ´Í¨ÖªµÄ¡£ÔÚÖжϴ¦Àí³ÌÐòÀ°ÑÓ²¼þÖ¡ÐÅÏ¢ÌîÈëÒ»¸öskbuff½á¹¹ÖУ¬È»
------------------ Linux²Ù×÷ÏµÍ³ÍøÂçÇý¶¯³ÌÐò±àд -------------------
------------ Contact the author by mailto:bordi@bordi.dhs.org ------
ºóµ÷ÓÃnetif_rx()´«µÝ¸øÉϲ㴦Àí¡£
2.2 ÍøÂçÇý¶¯³ÌÐòµÄ»ù±¾·½·¨
ÍøÂçÉ豸×öΪһ¸ö¶ÔÏó£¬ÌṩһЩ·½·¨¹©ÏµÍ³·ÃÎÊ¡£ÕýÊÇÕâЩÓÐͳһ½Ó¿ÚµÄ·½·¨£¬

ÑÚ±ÎÁËÓ²¼þµÄ¾ßÌåϸ½Ú£¬ÈÃϵͳ¶Ô¸÷ÖÖÍøÂçÉ豸µÄ·ÃÎʶ¼²ÉÓÃͳһµÄÐÎʽ£¬×öµ½Ó²¼þ
ÎÞ¹ØÐÔ¡£
ÏÂÃæ½âÊÍ×î»ù±¾µÄ·½·¨¡£
2.2.1 ³õʼ»¯(initialize)
Çý¶¯³ÌÐò±ØÐëÓÐÒ»¸ö³õʼ»¯·½·¨¡£ÔÚ°ÑÇý¶¯³ÌÐòÔØÈëϵͳµÄʱºò»áµ÷ÓÃÕâ¸ö³õ
ʼ»¯³ÌÐò¡£Ëü×öÒÔϼ¸·½ÃæµÄ¹¤×÷¡£¼ì²âÉ豸¡£ÔÚ³õʼ»¯³ÌÐòÀïÄã¿ÉÒÔ¸ù¾ÝÓ²¼þµÄ
ÌØÕ÷¼ì²éÓ²¼þÊÇ·ñ´æÔÚ£¬È»ºó¾ö¶¨ÊÇ·ñÆô¶¯Õâ¸öÇý¶¯³ÌÐò¡£ÅäÖúͳõʼ»¯Ó²¼þ¡£ÔÚ
³õʼ»¯³ÌÐòÀïÄã¿ÉÒÔÍê³É¶ÔÓ²¼þ×ÊÔ´µÄÅäÖ㬱ÈÈç¼´²å¼´ÓõÄÓ²¼þ¾Í¿ÉÒÔÔÚÕâ¸öʱ
ºò½øÐÐÅäÖÃ(LinuxÄں˶ÔPnP¹¦ÄÜûÓкܺõÄÖ§³Ö£¬¿ÉÒÔÔÚÇý¶¯³ÌÐòÀïÍê³ÉÕâ¸ö¹¦
ÄÜ)¡£ÅäÖûòЭÉ̺ÃÓ²¼þÕ¼ÓõÄ×ÊÔ´ÒԺ󣬾ͿÉÒÔÏòϵͳÉêÇëÕâЩ×ÊÔ´¡£ÓÐЩ×ÊÔ´ÊÇ
¿ÉÒԺͱðµÄÉ豸¹²ÏíµÄ£¬ÈçÖжϡ£ÓÐЩÊDz»Äܹ²ÏíµÄ£¬ÈçIO¡¢DMA¡£½ÓÏÂÀ´ÄãÒª³õʼ
»¯device½á¹¹ÖеıäÁ¿¡£×îºó£¬Äã¿ÉÒÔÈÃÓ²¼þÕýʽ¿ªÊ¼¹¤×÷¡£
2.2.2 ´ò¿ª(open)
openÕâ¸ö·½·¨ÔÚÍøÂçÉ豸Çý¶¯³ÌÐòÀïÊÇÍøÂçÉ豸±»¼¤»îµÄʱºò±»µ÷ÓÃ(¼´É豸״
̬ÓÉdown-->up)¡£ËùÒÔʵ¼ÊÉϺܶàÔÚinitializeÖеŤ×÷¿ÉÒԷŵ½ÕâÀïÀ´×ö¡£±ÈÈç×Ê
Ô´µÄÉêÇ룬Ӳ¼þµÄ¼¤»î¡£Èç¹ûdev->open·µ»Ø·Ç0(error)£¬ÔòÓ²¼þµÄ״̬»¹ÊÇdown¡£
open·½·¨ÁíÒ»¸ö×÷ÓÃÊÇÈç¹ûÇý¶¯³ÌÐò×öΪһ¸öÄ£¿é±»×°È룬ÔòÒª·Àֹģ¿éÐ¶ÔØÊ±
É豸´¦ÓÚ´ò¿ª×´Ì¬¡£ÔÚopen·½·¨ÀïÒªµ÷ÓÃMOD_INC_USE_COUNTºê¡£
2.2.3 ¹Ø±Õ(stop)
close·½·¨×öºÍopenÏà·´µÄ¹¤×÷¡£¿ÉÒÔÊÍ·ÅijЩ×ÊÔ´ÒÔ¼õÉÙϵͳ¸ºµ£¡£closeÊÇÔÚ
É豸״̬ÓÉupתΪdownʱ±»µ÷Óõġ£ÁíÍâÈç¹ûÊÇ×öΪģ¿é×°ÈëµÄÇý¶¯³ÌÐò£¬closeÀï
Ó¦¸Ãµ÷ÓÃMOD_DEC_USE_COUNT£¬¼õÉÙÉ豸±»ÒýÓõĴÎÊý£¬ÒÔʹÇý¶¯³ÌÐò¿ÉÒÔ±»Ð¶ÔØ¡£
ÁíÍâclose·½·¨±ØÐë·µ»Ø³É¹¦(0==success)¡£
2.2.4 ·¢ËÍ(hard_start_xmit)
ËùÓеÄÍøÂçÉ豸Çý¶¯³ÌÐò¶¼±ØÐëÓÐÕâ¸ö·¢ËÍ·½·¨¡£ÔÚϵͳµ÷ÓÃÇý¶¯³ÌÐòµÄxmit
ʱ£¬·¢Ë͵ÄÊý¾Ý·ÅÔÚÒ»¸ösk_buff½á¹¹ÖС£Ò»°ãµÄÇý¶¯³ÌÐò°ÑÊý¾Ý´«¸øÓ²¼þ·¢³öÈ¥¡£
Ò²ÓÐÒ»Ð©ÌØÊâµÄÉ豸±ÈÈçloopback°ÑÊý¾Ý×é³ÉÒ»¸ö½ÓÊÕÊý¾ÝÔÙ»ØË͸øÏµÍ³£¬»òÕß
dummyÉ豸ֱ½Ó¶ªÆúÊý¾Ý¡£
Èç¹û·¢Ëͳɹ¦£¬hard_start_xmit·½·¨ÀïÊÍ·Åsk_buff£¬·µ»Ø0(·¢Ëͳɹ¦)¡£Èç¹û
É豸ÔÝʱÎÞ·¨´¦Àí£¬±ÈÈçÓ²¼þ棬Ôò·µ»Ø1¡£ÕâʱÈç¹ûdev->tbusyÖÃΪ·Ç0£¬Ôòϵͳ
ÈÏΪӲ¼þ棬ҪµÈµ½dev->tbusyÖÃ0ÒÔºó²Å»áÔٴη¢ËÍ¡£tbusyµÄÖÃ0ÈÎÎñÒ»°ãÓÉÖжÏ
Íê³É¡£Ó²¼þÔÚ·¢ËͽáÊøºó²úÉúÖжϣ¬Õâʱ¿ÉÒÔ°ÑtbusyÖÃ0£¬È»ºóÓÃmark_bh()µ÷ÓÃͨ
֪ϵͳ¿ÉÒÔÔٴη¢ËÍ¡£ÔÚ·¢ËͲ»³É¹¦µÄÇé¿öÏ£¬Ò²¿ÉÒÔ²»ÖÃdev->tbusyΪ·Ç0£¬ÕâÑù
ϵͳ»á²»¶Ï³¢ÊÔÖØ·¢¡£Èç¹ûhard_start_xmit·¢ËͲ»³É¹¦£¬Ôò²»ÒªÊÍ·Åsk_buff¡£
´«ËÍÏÂÀ´µÄsk_buffÖеÄÊý¾ÝÒѾ­°üº¬Ó²¼þÐèÒªµÄÖ¡Í·¡£ËùÒÔÔÚ·¢ËÍ·½·¨Àï²»Ðè
ÒªÔÙÌî³äÓ²¼þÖ¡Í·£¬Êý¾Ý¿ÉÒÔÖ±½ÓÌá½»¸øÓ²¼þ·¢ËÍ¡£sk_buffÊDZ»Ëø×¡µÄ(locked)£¬
È·±£ÆäËû³ÌÐò²»»á´æÈ¡Ëü¡£
2.2.5 ½ÓÊÕ(reception)
Çý¶¯³ÌÐò²¢²»´æÔÚÒ»¸ö½ÓÊÕ·½·¨¡£ÓÐÊý¾ÝÊÕµ½Ó¦¸ÃÊÇÇý¶¯³ÌÐòÀ´Í¨ÖªÏµÍ³µÄ¡£
Ò»°ãÉ豸ÊÕµ½Êý¾Ýºó¶¼»á²úÉúÒ»¸öÖжϣ¬ÔÚÖжϴ¦Àí³ÌÐòÖÐÇý¶¯³ÌÐòÉêÇëÒ»¿é
sk_buff(skb)£¬´ÓÓ²¼þ¶Á³öÊý¾Ý·ÅÖõ½ÉêÇëºÃµÄ»º³åÇøÀï¡£½ÓÏÂÀ´Ìî³äsk_buffÖÐ
µÄһЩÐÅÏ¢¡£skb->dev = dev£¬ÅжÏÊÕµ½Ö¡µÄЭÒéÀàÐÍ£¬ÌîÈëskb->protocol(¶àЭ
ÒéµÄÖ§³Ö)¡£°ÑÖ¸Õëskb->mac.rawÖ¸ÏòÓ²¼þÊý¾ÝÈ»ºó¶ªÆúÓ²¼þÖ¡Í·(skb_pull)¡£»¹Òª
ÉèÖÃskb->pkt_type£¬±êÃ÷µÚ¶þ²ã(Á´Â·²ã)Êý¾ÝÀàÐÍ¡£¿ÉÒÔÊÇÒÔÏÂÀàÐÍ£º
PACKET_BROADCAST : Á´Â·²ã¹ã²¥
PACKET_MULTICAST : Á´Â·²ã×é²¥
PACKET_SELF : ·¢¸ø×Ô¼ºµÄÖ¡
PACKET_OTHERHOST : ·¢¸ø±ðÈ˵ÄÖ¡(¼àÌýģʽʱ»áÓÐÕâÖÖÖ¡)
×îºóµ÷ÓÃnetif_rx()°ÑÊý¾Ý´«Ë͸øÐ­Òé²ã¡£netif_rx()ÀïÊý¾Ý·ÅÈë´¦Àí¶ÓÁÐÈ»ºó·µ
»Ø£¬ÕæÕýµÄ´¦ÀíÊÇÔÚÖжϷµ»ØÒÔºó£¬ÕâÑù¿ÉÒÔ¼õÉÙÖжÏʱ¼ä¡£µ÷ÓÃnetif_rx()ÒÔºó£¬
Çý¶¯³ÌÐò¾Í²»ÄÜÔÙ´æÈ¡Êý¾Ý»º³åÇøskb¡£
2.2.6 Ó²¼þÖ¡Í·(hard_header)
Ó²¼þÒ»°ã¶¼»áÔÚÉϲãÊý¾Ý·¢ËÍ֮ǰ¼ÓÉÏ×Ô¼ºµÄÓ²¼þÖ¡Í·£¬±ÈÈçÒÔÌ«Íø(Ethernet)
¾ÍÓÐ14×Ö½ÚµÄÖ¡Í·¡£Õâ¸öÖ¡Í·ÊǼÓÔÚÉϲãip¡¢ipxµÈÊý¾Ý°üµÄÇ°ÃæµÄ¡£Çý¶¯³ÌÐòÌṩ
Ò»¸öhard_header·½·¨£¬Ð­Òé²ã(ip¡¢ipx¡¢arpµÈ)ÔÚ·¢ËÍÊý¾Ý֮ǰ»áµ÷ÓÃÕâ¶Î³ÌÐò¡£
Ó²¼þÖ¡Í·µÄ³¤¶È±ØÐëÌîÔÚdev->hard_header_len£¬ÕâÑùЭÒé²ã»ØÔÚÊý¾Ý֮ǰ±£ÁôºÃ
Ó²¼þÖ¡Í·µÄ¿Õ¼ä¡£ÕâÑùhard_header³ÌÐòÖ»Òªµ÷ÓÃskb_pushÈ»ºóÕýÈ·ÌîÈëÓ²¼þÖ¡Í·¾Í
¿ÉÒÔÁË¡£
ÔÚЭÒé²ãµ÷ÓÃhard_headerʱ£¬´«Ë͵IJÎÊý°üÀ¨(2.0.xx)£ºÊý¾ÝµÄsk_buff£¬
deviceÖ¸Õ룬protocol£¬Ä¿µÄµØÖ·(daddr)£¬Ô´µØÖ·(saddr)£¬Êý¾Ý³¤¶È(len)¡£Êý¾Ý
³¤¶È²»ÒªÊ¹ÓÃsk_buffÖеIJÎÊý£¬ÒòΪµ÷ÓÃhard_headerʱÊý¾Ý¿ÉÄÜ»¹Ã»ÍêÈ«×éÖ¯ºÃ¡£
saddrÊÇNULLµÄ»°ÊÇʹÓÃȱʡµØÖ·(default)¡£daddrÊÇNULL±íÃ÷ЭÒé²ã²»ÖªµÀÓ²¼þÄ¿
µÄµØÖ·¡£Èç¹ûhard_headerÍêÈ«ÌîºÃÁËÓ²¼þÖ¡Í·£¬Ôò·µ»ØÌí¼ÓµÄ×Ö½ÚÊý¡£Èç¹ûÓ²¼þÖ¡
Í·ÖеÄÐÅÏ¢»¹²»ÍêÈ«(±ÈÈçdaddrΪNULL£¬µ«ÊÇÖ¡Í·ÖÐÐèҪĿµÄÓ²¼þµØÖ·¡£µäÐ͵ÄÇé
¿öÊÇÒÔÌ«ÍøÐèÒªµØÖ·½âÎö(arp))£¬Ôò·µ»Ø¸º×Ö½ÚÊý¡£hard_header·µ»Ø¸ºÊýµÄÇé¿ö
Ï£¬Ð­Òé²ã»á×ö½øÒ»²½µÄbuild headerµÄ¹¤×÷¡£Ä¿Ç°LinuxϵͳÀï¾ÍÊÇ×öarp
(Èç¹ûhard_header·µ»ØÕý£¬dev->arp=1£¬±íÃ÷²»ÐèÒª×öarp£¬·µ»Ø¸º£¬dev->arp=0£¬
×öarp)¡£
¶Ôhard_headerµÄµ÷ÓÃÔÚÿ¸öЭÒé²ãµÄ´¦Àí³ÌÐòÀï¡£Èçip_output¡£
2.2.7 µØÖ·½âÎö(xarp)
ÓÐÐ©ÍøÂçÓÐÓ²¼þµØÖ·(±ÈÈçEthernet)£¬²¢ÇÒÔÚ·¢ËÍÓ²¼þ֡ʱÐèÒªÖªµÀÄ¿µÄÓ²¼þ
µØÖ·¡£ÕâÑù¾ÍÐèÒªÉϲãЭÒ鵨ַ(ip¡¢ipx)ºÍÓ²¼þµØÖ·µÄ¶ÔÓ¦¡£Õâ¸ö¶ÔÓ¦ÊÇͨ¹ýµØÖ·
½âÎöÍê³ÉµÄ¡£ÐèÒª×öarpµÄµÄÉ豸ÔÚ·¢ËÍ֮ǰ»áµ÷ÓÃÇý¶¯³ÌÐòµÄrebuild_header·½
·¨¡£µ÷ÓõÄÖ÷Òª²ÎÊý°üÀ¨Ö¸ÏòÓ²¼þÖ¡Í·µÄÖ¸Õ룬ЭÒé²ãµØÖ·¡£Èç¹ûÇý¶¯³ÌÐòÄܹ»½â
ÎöÓ²¼þµØÖ·£¬¾Í·µ»Ø1£¬Èç¹û²»ÄÜ£¬·µ»Ø0¡£
¶Ôrebuild_headerµÄµ÷ÓÃÔÚnet/core/dev.cµÄdo_dev_queue_xmit()Àï¡£
2.2.8 ²ÎÊýÉèÖúÍͳ¼ÆÊý¾Ý
ÔÚÇý¶¯³ÌÐòÀﻹÌṩһЩ·½·¨¹©ÏµÍ³¶ÔÉ豸µÄ²ÎÊý½øÐÐÉèÖúͶÁÈ¡ÐÅÏ¢¡£Ò»°ã
Ö»Óг¬¼¶Óû§(root)ȨÏÞ²ÅÄܶÔÉ豸²ÎÊý½øÐÐÉèÖá£ÉèÖ÷½·¨ÓУº
dev->set_mac_address()
µ±Óû§µ÷ÓÃioctlÀàÐÍΪSIOCSIFHWADDRʱÊÇÒªÉèÖÃÕâ¸öÉ豸µÄmacµØÖ·¡£Ò»°ã
¶ÔmacµØÖ·µÄÉèÖÃûÓÐÌ«´óÒâÒåµÄ¡£
dev->set_config()
------------------ Linux²Ù×÷ÏµÍ³ÍøÂçÇý¶¯³ÌÐò±àд -------------------
------------ Contact the author by mailto:bordi@bordi.dhs.org ------
µ±Óû§µ÷ÓÃioctlʱÀàÐÍΪSIOCSIFMAPʱ£¬ÏµÍ³»áµ÷ÓÃÇý¶¯³ÌÐòµÄset_config
·½·¨¡£Óû§»á´«µÝÒ»¸öifmap½á¹¹°üº¬ÐèÒªµÄI/O¡¢ÖжϵȲÎÊý¡£
dev->do_ioctl()
Èç¹ûÓû§µ÷ÓÃioctlʱÀàÐÍÔÚSIOCDEVPRIVATEºÍSIOCDEVPRIVATE+15Ö®¼ä£¬ÏµÍ³
»áµ÷ÓÃÇý¶¯³ÌÐòµÄÕâ¸ö·½·¨¡£Ò»°ãÊÇÉèÖÃÉ豸µÄרÓÃÊý¾Ý¡£
¶ÁÈ¡ÐÅÏ¢Ò²ÊÇͨ¹ýioctlµ÷ÓýøÐС£³ý´ÎÖ®ÍâÇý¶¯³ÌÐò»¹¿ÉÒÔÌṩһ¸ö
dev->get_stats·½·¨£¬·µ»ØÒ»¸öenet_statistics½á¹¹£¬°üº¬·¢ËͽÓÊÕµÄͳ¼ÆÐÅÏ¢¡£
ioctlµÄ´¦ÀíÔÚnet/core/dev.cµÄdev_ioctl()ºÍdev_ifsioc()Àï¡£
2.3 ÍøÂçÇý¶¯³ÌÐòÖÐÓõ½µÄÊý¾Ý½á¹¹
×îÖØÒªµÄÊÇÍøÂçÉ豸µÄÊý¾Ý½á¹¹¡£¶¨ÒåÔÚinclude/linux/netdevice.hÀï¡£Ëü
µÄ×¢ÊÍÒѾ­×ã¹»Ï꾡¡£
struct device
{
/*
* This is the first field of the "visible" part of this structure
* (i.e. as seen by users in the "Space.c" file). It is the name
* the interface.
*/
char *name;
/* I/O specific fields - FIXME: Merge these and struct ifmap into one */
unsigned long rmem_end; /* shmem "recv" end */
unsigned long rmem_start; /* shmem "recv" start */
unsigned long mem_end; /* shared mem end */
unsigned long mem_start; /* shared mem start */
unsigned long base_addr; /* device I/O address */
unsigned char irq; /* device IRQ number */
/* Low-level status flags. */
volatile unsigned char start, /* start an operation */
interrupt; /* interrupt arrived */
/* ÔÚ´¦ÀíÖжÏʱinterruptÉèΪ1£¬´¦ÀíÍêÇå0¡£ */
unsigned long tbusy; /* transmitter busy must be
long
for
bitops */
struct device *next;
/* The device initialization function. Called only once. */
/* Ö¸ÏòÇý¶¯³ÌÐòµÄ³õʼ»¯·½·¨¡£ */
int (*init)(struct device *dev);
/* Some hardware also needs these fields, but they are not part of the
usual set specified in Space.c. */
/* һЩӲ¼þ¿ÉÒÔÔÚÒ»¿é°åÉÏÖ§³Ö¶à¸ö½Ó¿Ú£¬¿ÉÄÜÓõ½if_port¡£ */
unsigned char if_port; /* Selectable AUI, TP,..*/
unsigned char dma; /* DMA channel */
struct enet_statistics* (*get_stats)(struct device *dev);
/*
* This marks the end of the "visible" part of the structure. All
* fields hereafter are internal to the system, and may change at
* will (read: may be cleaned up at will).
*/
/* These may be needed for future network-power-down code. */
/* trans_start¼Ç¼×îºóÒ»´Î³É¹¦·¢Ë͵Äʱ¼ä¡£¿ÉÒÔÓÃÀ´È·¶¨Ó²¼þÊÇ·ñ¹¤×÷Õý³£¡£*/

unsigned long trans_start; /* Time (in jiffies) of last Tx */
unsigned long last_rx; /* Time of last Rx */
/* flagsÀïÃæÓкܶàÄÚÈÝ£¬¶¨ÒåÔÚinclude/linux/if.hÀï¡£*/
unsigned short flags; /* interface flags (a la BSD) */
unsigned short family; /* address family ID (AF_INET) */
unsigned short metric; /* routing metric (not used) */
unsigned short mtu; /* interface MTU value */
/* type±êÃ÷ÎïÀíÓ²¼þµÄÀàÐÍ¡£Ö÷Ҫ˵Ã÷Ó²¼þÊÇ·ñÐèÒªarp¡£¶¨ÒåÔÚ
include/linux/if_arp.hÀï¡£ */
unsigned short type; /* interface hardware type */
/* ÉϲãЭÒé²ã¸ù¾Ýhard_header_lenÔÚ·¢ËÍÊý¾Ý»º³åÇøÇ°ÃæÔ¤ÁôÓ²¼þÖ¡Í·¿Õ¼ä¡£*/
unsigned short hard_header_len; /* hardware hdr length */
/* privÖ¸ÏòÇý¶¯³ÌÐò×Ô¼º¶¨ÒåµÄһЩ²ÎÊý¡£*/
void *priv; /* pointer to private data */
/* Interface address info. */
unsigned char broadcast[MAX_ADDR_LEN]; /* hw bcast add */
unsigned char pad; /* make dev_addr ali
gned
to 8
bytes */
unsigned char dev_addr[MAX_ADDR_LEN]; /* hw address */
unsigned char addr_len; /* hardware address length */
unsigned long pa_addr; /* protocol address */
unsigned long pa_brdaddr; /* protocol broadcast addr */
unsigned long pa_dstaddr; /* protocol P-P other side addr */
unsigned long pa_mask; /* protocol netmask */
unsigned short pa_alen; /* protocol address length */
struct dev_mc_list *mc_list; /* Multicast mac addresses */
int mc_count; /* Number of installed mcasts */
struct ip_mc_list *ip_mc_list; /* IP multicast filter chain */
__u32 tx_queue_len; /* Max frames per queue allowed */
------------------ Linux²Ù×÷ÏµÍ³ÍøÂçÇý¶¯³ÌÐò±àд -------------------
------------ Contact the author by mailto:bordi@bordi.dhs.org ------
/* For load balancing driver pair support */
unsigned long pkt_queue; /* Packets queued */
struct device *slave; /* Slave device */
struct net_alias_info *alias_info; /* main dev alias info */
struct net_alias *my_alias; /* alias devs */
/* Pointer to the interface buffers. */
struct sk_buff_head buffs[DEV_NUMBUFFS];
/* Pointers to interface service routines. */
int (*open)(struct device *dev);
int (*stop)(struct device *dev);
int (*hard_start_xmit) (struct sk_buff *skb,
struct device *dev);
int (*hard_header) (struct sk_buff *skb,
struct device *dev,
unsigned short type,
void *daddr,
void *saddr,
unsigned len);
int (*rebuild_header)(void *eth, struct device *dev,
unsigned long raddr, struct sk_buff *skb);
#define HAVE_MULTICAST
void (*set_multicast_list)(struct device *dev);
#define HAVE_SET_MAC_ADDR
int (*set_mac_address)(struct device *dev, void *addr)
;
#define HAVE_PRIVATE_IOCTL
int (*do_ioctl)(struct device *dev, struct ifreq *ifr,
int
cmd);
#define HAVE_SET_CONFIG
int (*set_config)(struct device *dev, struct ifmap *ma
p);
#define HAVE_HEADER_CACHE
void (*header_cache_bind)(struct hh_cache **hhp, struct
dev
ce
*dev, unsigned short htype, __u32 daddr);
void (*header_cache_update)(struct hh_cache *hh, struct
dev
ce
*dev, unsigned char * haddr);
#define HAVE_CHANGE_MTU
int (*change_mtu)(struct device *dev, int new_mtu);
struct iw_statistics* (*get_wireless_stats)(struct device *dev);
};
2.4 ³£ÓõÄϵͳ֧³Ö
2.4.1 ÄÚ´æÉêÇëºÍÊÍ·Å
include/linux/kernel.hÀïÉùÃ÷ÁËkmalloc()ºÍkfree()¡£ÓÃÓÚÔÚÄÚºËģʽÏÂÉê
ÇëºÍÊÍ·ÅÄÚ´æ¡£
void *kmalloc(unsigned int len,int priority);
void kfree(void *__ptr);
ÓëÓû§Ä£Ê½ÏµÄmalloc()²»Í¬£¬kmalloc()ÉêÇë¿Õ¼äÓдóСÏÞÖÆ¡£³¤¶ÈÊÇ2µÄÕû
´Î·½¡£¿ÉÒÔÉêÇëµÄ×î´ó³¤¶ÈÒ²ÓÐÏÞÖÆ¡£ÁíÍâkmalloc()ÓÐpriority²ÎÊý£¬Í¨³£Ê¹ÓÃ
ʱ¿ÉÒÔΪGFP_KERNEL£¬Èç¹ûÔÚÖжÏÀïµ÷ÓÃÓÃGFP_ATOMIC²ÎÊý£¬ÒòΪʹÓÃGFP_KERNEL
Ôòµ÷ÓÃÕß¿ÉÄܽøÈësleep״̬£¬ÔÚ´¦ÀíÖжÏʱÊDz»ÔÊÐíµÄ¡£
kfree()ÊͷŵÄÄÚ´æ±ØÐëÊÇkmalloc()ÉêÇëµÄ¡£Èç¹ûÖªµÀÄÚ´æµÄ´óС£¬Ò²¿ÉÒÔÓÃ
kfree_s()ÊÍ·Å¡£
2.4.2 request_irq()¡¢free_irq()
ÕâÊÇÇý¶¯³ÌÐòÉêÇëÖжϺÍÊÍ·ÅÖжϵĵ÷Óá£ÔÚinclude/linux/sched.hÀïÉùÃ÷¡£
request_irq()µ÷Óõ͍Ò壺
int request_irq(unsigned int irq,
void (*handler)(int irq, void *dev_id, struct pt_regs *regs
),
unsigned long irqflags,
const char * devname,
void *dev_id);
irqÊÇÒªÉêÇëµÄÓ²¼þÖжϺš£ÔÚIntelƽ̨£¬·¶Î§0--15¡£handlerÊÇÏòϵͳµÇ¼Ç
µÄÖжϴ¦Àíº¯Êý¡£ÕâÊÇÒ»¸ö»Øµ÷º¯Êý£¬ÖжϷ¢Éúʱ£¬ÏµÍ³µ÷ÓÃÕâ¸öº¯Êý£¬´«ÈëµÄ²Î
Êý°üÀ¨Ó²¼þÖжϺţ¬device id£¬¼Ä´æÆ÷Öµ¡£dev_id¾ÍÊÇÏÂÃæµÄrequest_irqʱ´«µÝ
¸øÏµÍ³µÄ²ÎÊýdev_id¡£irqflagsÊÇÖжϴ¦ÀíµÄһЩÊôÐÔ¡£±È½ÏÖØÒªµÄÓÐSA_INTERRUPT£¬

±êÃ÷Öжϴ¦Àí³ÌÐòÊÇ¿ìËÙ´¦Àí³ÌÐò(ÉèÖÃSA_INTERRUPT)»¹ÊÇÂýËÙ´¦Àí³ÌÐò(²»ÉèÖÃ
SA_INTERRUPT)¡£¿ìËÙ´¦Àí³ÌÐò±»µ÷ÓÃʱÆÁ±ÎËùÓÐÖжϡ£ÂýËÙ´¦Àí³ÌÐò²»ÆÁ±Î¡£»¹ÓÐ
Ò»¸öSA_SHIRQÊôÐÔ£¬ÉèÖÃÁËÒÔºóÔËÐжà¸öÉ豸¹²ÏíÖжϡ£dev_idÔÚÖжϹ²Ïíʱ»áÓÃ
µ½¡£Ò»°ãÉèÖÃΪÕâ¸öÉ豸µÄdevice½á¹¹±¾Éí»òÕßNULL¡£Öжϴ¦Àí³ÌÐò¿ÉÒÔÓÃdev_id
ÕÒµ½ÏàÓ¦µÄ¿ØÖÆÕâ¸öÖжϵÄÉ豸£¬»òÕßÓÃirq2dev_mapÕÒµ½Öж϶ÔÓ¦µÄÉ豸¡£
void free_irq(unsigned int irq,void *dev_id);
2.4.3 ʱÖÓ
ʱÖӵĴ¦ÀíÀàËÆÖжϣ¬Ò²ÊǵǼÇÒ»¸öʱ¼ä´¦Àíº¯Êý£¬ÔÚÔ¤¶¨µÄʱ¼ä¹ýºó£¬ÏµÍ³
»áµ÷ÓÃÕâ¸öº¯Êý¡£ÔÚinclude/linux/timer.hÀïÉùÃ÷¡£
struct timer_list {
struct timer_list *next;
struct timer_list *prev;
unsigned long expires;
unsigned long data;
void (*function)(unsigned long);
};
void add_timer(struct timer_list * timer);
int del_timer(struct timer_list * timer);
void init_timer(struct timer_list * timer);
ʹÓÃʱÖÓ£¬ÏÈÉùÃ÷Ò»¸ötimer_list½á¹¹£¬µ÷ÓÃinit_timer¶ÔËü½øÐгõʼ»¯¡£
time_list½á¹¹ÀïexpiresÊDZêÃ÷Õâ¸öʱÖÓµÄÖÜÆÚ£¬µ¥Î»²ÉÓÃjiffiesµÄµ¥Î»¡£
jiffiesÊÇLinuxÒ»¸öÈ«¾Ö±äÁ¿£¬´ú±íʱ¼ä¡£ËüµÄµ¥Î»ËæÓ²¼þƽ̨µÄ²»Í¬¶ø²»Í¬¡£
ϵͳÀﶨÒåÁËÒ»¸ö³£ÊýHZ£¬´ú±íÿÃëÖÖ×îСʱ¼ä¼ä¸ôµÄÊýÄ¿¡£ÕâÑùjiffiesµÄµ¥Î»
¾ÍÊÇ1/HZ¡£Intelƽ̨jiffiesµÄµ¥Î»ÊÇ1/100Ã룬Õâ¾ÍÊÇϵͳËùÄÜ·Ö±æµÄ×îСʱ¼ä
¼ä¸ôÁË¡£ËùÒÔexpires/HZ¾ÍÊÇÒÔÃëΪµ¥Î»µÄÕâ¸öʱÖÓµÄÖÜÆÚ¡£
function¾ÍÊÇʱ¼äµ½ÁËÒÔºóµÄ»Øµ÷º¯Êý£¬ËüµÄ²ÎÊý¾ÍÊÇtimer_listÖеÄdata¡£
dataÕâ¸ö²ÎÊýÔÚ³õʼ»¯Ê±ÖÓµÄʱºò¸³Öµ£¬Ò»°ã¸³¸øËüÉ豸µÄdevice½á¹¹Ö¸Õë¡£
ÔÚÔ¤ÖÃʱ¼äµ½ÏµÍ³µ÷ÓÃfunction£¬Í¬Ê±ÏµÍ³°ÑÕâ¸ötime_list´Ó¶¨Ê±¶ÓÁÐÀïÇå
³ý¡£ËùÒÔÈç¹ûÐèҪһֱʹÓö¨Ê±º¯Êý£¬ÒªÔÚfunctionÀïÔٴε÷ÓÃadd_timer()°ÑÕâ
------------------ Linux²Ù×÷ÏµÍ³ÍøÂçÇý¶¯³ÌÐò±àд -------------------
------------ Contact the author by mailto:bordi@bordi.dhs.org ------
¸ötimer_list¼Ó½ø¶¨Ê±¶ÓÁС£
2.4.4 I/O
I/O¶Ë¿ÚµÄ´æÈ¡Ê¹Óãº
inline unsigned int inb(unsigned short port);
inline unsigned int inb_p(unsigned short port);
inline void outb(char value, unsigned short port);
inline void outb_p(char value, unsigned short port);
ÔÚinclude/adm/io.hÀﶨÒå¡£
inb_p()¡¢outb_p()Óëinb()¡¢outb_p()µÄ²»Í¬ÔÚÓÚǰÕßÔÚ´æÈ¡I/OʱÓеȴý
(pause)Ò»ÊÊÓ¦ÂýËÙµÄI/OÉ豸¡£
ΪÁË·ÀÖ¹´æÈ¡I/Oʱ·¢Éú³åÍ»£¬LinuxÌṩ¶Ô¶Ë¿ÚʹÓÃÇé¿öµÄ¿ØÖÆ¡£ÔÚʹÓö˿Ú
֮ǰ£¬¿ÉÒÔ¼ì²éÐèÒªµÄI/OÊÇ·ñÕýÔÚ±»Ê¹Óã¬Èç¹ûûÓУ¬Ôò°Ñ¶Ë¿Ú±ê¼ÇΪÕýÔÚʹÓã¬
ʹÓÃÍêºóÔÙÊÍ·Å¡£ÏµÍ³ÌṩÒÔϼ¸¸öº¯Êý×öÕâЩ¹¤×÷¡£
int check_region(unsigned int from, unsigned int extent);
void request_region(unsigned int from, unsigned int extent,const char *n
ame)
void release_region(unsigned int from, unsigned int extent);
ÆäÖеIJÎÊýfrom±íʾÓõ½µÄI/O¶Ë¿ÚµÄÆðʼµØÖ·£¬extent±êÃ÷´Ófrom¿ªÊ¼µÄ¶Ë
¿ÚÊýÄ¿¡£nameΪÉ豸Ãû³Æ¡£
2.4.5 Öжϴò¿ª¹Ø±Õ
ϵͳÌṩ¸øÇý¶¯³ÌÐò¿ª·ÅºÍ¹Ø±ÕÏìÓ¦ÖжϵÄÄÜÁ¦¡£ÊÇÔÚinclude/asm/system.h
ÖеÄÁ½¸ö¶¨Òå¡£
#define cli() __asm__ __volatile__ ("cli"::)
#define sti() __asm__ __volatile__ ("sti"::)
2.4.6 ´òÓ¡ÐÅÏ¢
ÀàËÆÆÕͨ³ÌÐòÀïµÄprintf()£¬Çý¶¯³ÌÐòÒªÊä³öÐÅϢʹÓÃprintk()¡£ÔÚinclude
/linux/kernel.hÀïÉùÃ÷¡£
int printk(const char* fmt, ...);
ÆäÖÐfmtÊǸñʽ»¯×Ö·û´®¡£...ÊDzÎÊý¡£¶¼ÊǺÍprintf()¸ñʽһÑùµÄ¡£
2.4.7 ×¢²áÇý¶¯³ÌÐò
Èç¹ûʹÓÃÄ£¿é(module)·½Ê½¼ÓÔØÇý¶¯³ÌÐò£¬ÐèÒªÔÚÄ£¿é³õʼ»¯Ê±°ÑÉ豸ע²á
µ½ÏµÍ³É豸±íÀïÈ¥¡£²»ÔÙʹÓÃʱ£¬°ÑÉ豸´ÓϵͳÖÐж³ý¡£¶¨ÒåÔÚdrivers/net/net_init
.h
ÀïµÄÁ½¸öº¯ÊýÍê³ÉÕâ¸ö¹¤×÷¡£
int register_netdev(struct device *dev);
void unregister_netdev(struct device *dev);
dev¾ÍÊÇҪע²á½øÏµÍ³µÄÉ豸½á¹¹Ö¸Õë¡£ÔÚregister_netdev()ʱ£¬dev½á¹¹Ò»
°ãÌîÐ´Ç°Ãæ11Ï¼´µ½init£¬ºóÃæµÄÔÝʱ¿ÉÒÔ²»Óóõʼ»¯¡£×îÖØÒªµÄÊÇnameÖ¸ÕëºÍ
init·½·¨¡£nameÖ¸Õë¿Õ(NULL)»òÕßÄÚÈÝΪ''»òÕßname[0]Ϊ¿Õ¸ñ(space)£¬Ôòϵͳ
°ÑÄãµÄÉ豸×öΪÒÔÌ«ÍøÉ豸´¦Àí¡£ÒÔÌ«ÍøÉ豸ÓÐͳһµÄÃüÃû¸ñʽ£¬ethX¡£¶ÔÒÔÌ«Íø
ÕâÃ´ÌØ±ð¶Ô´ý´ó¸ÅºÍLinuxµÄÀúÊ·Óйء£
init·½·¨Ò»¶¨ÒªÌṩ£¬register_netdev()»áµ÷ÓÃÕâ¸ö·½·¨ÈÃÄã¶ÔÓ²¼þ¼ì²âºÍ
ÉèÖá£
register_netdev()·µ»Ø0±íʾ³É¹¦£¬·Ç0²»³É¹¦¡£
2.4.8 sk_buff
LinuxÍøÂç¸÷²ãÖ®¼äµÄÊý¾Ý´«ËͶ¼ÊÇͨ¹ýsk_buff¡£sk_buffÌṩһÌ×¹ÜÀí»º³å
ÇøµÄ·½·¨£¬ÊÇLinuxÏµÍ³ÍøÂç¸ßЧÔËÐеĹؼü¡£Ã¿¸ösk_buff°üÀ¨Ò»Ð©¿ØÖÆ·½·¨ºÍÒ»
¿éÊý¾Ý»º³åÇø¡£¿ØÖÆ·½·¨°´¹¦ÄÜ·ÖΪÁ½ÖÖÀàÐÍ¡£Ò»ÖÖÊÇ¿ØÖÆÕû¸öbufferÁ´µÄ·½·¨£¬
ÁíÒ»ÖÖÊÇ¿ØÖÆÊý¾Ý»º³åÇøµÄ·½·¨¡£sk_buff×éÖ¯³ÉË«ÏòÁ´±íµÄÐÎʽ£¬¸ù¾ÝÍøÂçÓ¦ÓÃ
µÄÌØµã£¬¶ÔÁ´±íµÄ²Ù×÷Ö÷ÒªÊÇɾ³ýÁ´±íÍ·µÄÔªËØºÍÌí¼Óµ½Á´±íβ¡£sk_buffµÄ¿ØÖÆ
·½·¨¶¼ºÜ¶ÌСÒÔ¾¡Á¿¼õÉÙϵͳ¸ººÉ¡£(translated from article written by Alan
Cox)
³£Óõķ½·¨°üÀ¨£º
.alloc_skb() ÉêÇëÒ»¸ösk_buff²¢¶ÔËü³õʼ»¯¡£·µ»Ø¾ÍÊÇÉêÇëµ½µÄsk_buff¡£
.dev_alloc_skb()ÀàËÆalloc_skb£¬ÔÚÉêÇëºÃ»º³åÇøºó£¬±£Áô16×Ö½ÚµÄÖ¡Í·¿Õ
¼ä¡£Ö÷ÒªÓÃÔÚEthernetÇý¶¯³ÌÐò¡£
.kfree_skb() ÊÍ·ÅÒ»¸ösk_buff¡£
.skb_clone() ¸´ÖÆÒ»¸ösk_buff£¬µ«²»¸´ÖÆÊý¾Ý²¿·Ö¡£
.skb_copy()ÍêÈ«¸´ÖÆÒ»¸ösk_buff¡£
.skb_dequeue() ´ÓÒ»¸ösk_buffÁ´±íÀïÈ¡³öµÚÒ»¸öÔªËØ¡£·µ»ØÈ¡³öµÄsk_buff£¬
Èç¹ûÁ´±í¿ÕÔò·µ»ØNULL¡£ÕâÊdz£ÓõÄÒ»¸ö²Ù×÷¡£
.skb_queue_head() ÔÚÒ»¸ösk_buffÁ´±íÍ··ÅÈëÒ»¸öÔªËØ¡£
.skb_queue_tail() ÔÚÒ»¸ösk_buffÁ´±íβ·ÅÈëÒ»¸öÔªËØ¡£ÕâÒ²Êdz£ÓõÄÒ»¸ö
²Ù×÷¡£ÍøÂçÊý¾ÝµÄ´¦ÀíÖ÷ÒªÊǶÔÒ»¸öÏȽøÏȳö¶ÓÁеĹÜÀí£¬skb_queue_tail()
ºÍskb_dequeue()Íê³ÉÕâ¸ö¹¤×÷¡£
.skb_insert() ÔÚÁ´±íµÄij¸öÔªËØÇ°²åÈëÒ»¸öÔªËØ¡£
.skb_append() ÔÚÁ´±íµÄij¸öÔªËØºó²åÈëÒ»¸öÔªËØ¡£Ò»Ð©Ð­Òé(ÈçTCP)¶Ôû°´
˳Ðòµ½´ïµÄÊý¾Ý½øÐÐÖØ×éʱÓõ½skb_insert()ºÍskb_append()¡£
.skb_reserve() ÔÚÒ»¸öÉêÇëºÃµÄsk_buffµÄ»º³åÇøÀï±£ÁôÒ»¿é¿Õ¼ä¡£Õâ¸ö¿Õ¼ä
Ò»°ãÊÇÓÃ×öÏÂÒ»²ãЭÒéµÄÍ·¿Õ¼äµÄ¡£
.skb_put() ÔÚÒ»¸öÉêÇëºÃµÄsk_buffµÄ»º³åÇøÀïΪÊý¾Ý±£ÁôÒ»¿é¿Õ¼ä¡£ÔÚ
alloc_skbÒÔºó£¬ÉêÇëµ½µÄsk_buffµÄ»º³åÇø¶¼ÊÇ´¦ÓÚ¿Õ(free)״̬£¬ÓÐÒ»¸ö
tailÖ¸ÕëÖ¸Ïòfree¿Õ¼ä£¬Êµ¼ÊÉÏ¿ªÊ¼Ê±tail¾ÍÖ¸Ïò»º³åÇøÍ·¡£skb_reserve()
ÔÚfree¿Õ¼äÀïÉêÇëЭÒéÍ·¿Õ¼ä£¬skb_put()ÉêÇëÊý¾Ý¿Õ¼ä¡£¼ûÏÂÃæµÄͼ¡£
.skb_push() °Ñsk_buff»º³åÇøÀïÊý¾Ý¿Õ¼äÍùÇ°ÒÆ¡£¼´°ÑHead roomÖеĿռäÒÆ
Ò»²¿·Öµ½Data area¡£
.skb_pull() °Ñsk_buff»º³åÇøÀïData areaÖеĿռäÒÆÒ»²¿·Öµ½Head roomÖС£
--------------------------------------------------
| Tail room(free) |
--------------------------------------------------
After alloc_skb()
--------------------------------------------------
| Head room | Tail room(free) |
--------------------------------------------------
After skb_reserve()
--------------------------------------------------
| Head room | Data area | Tail room(free) |
--------------------------------------------------
After skb_put()
--------------------------------------------------
|Head| skb_ | Data | Tail room(free) |
|room| push | | |
| | Data area | |
--------------------------------------------------
After skb_push()
--------------------------------------------------
| Head | skb_ | Data area | Tail room(free) |
| | pull | | |
| Head room | | |
--------------------------------------------------
After skb_pull()
------------------ Linux²Ù×÷ÏµÍ³ÍøÂçÇý¶¯³ÌÐò±àд -------------------
------------ Contact the author by mailto:bordi@bordi.dhs.org ------
Èý.±àдLinuxÍøÂçÇý¶¯³ÌÐòÖÐÐèҪעÒâµÄÎÊÌâ
3.1 ÖжϹ²Ïí
LinuxϵͳÔËÐм¸¸öÉ豸¹²Ïíͬһ¸öÖжϡ£ÐèÒª¹²ÏíµÄ»°£¬ÔÚÉêÇëµÄʱºòÖ¸Ã÷
¹²Ïí·½Ê½¡£ÏµÍ³ÌṩµÄrequest_irq()µ÷Óõ͍Ò壺
int request_irq(unsigned int irq,
void (*handler)(int irq, void *dev_id, struct pt_regs *regs
),
unsigned long irqflags,
const char * devname,
void *dev_id);
Èç¹û¹²ÏíÖжϣ¬irqflagsÉèÖÃSA_SHIRQÊôÐÔ£¬ÕâÑù¾ÍÔÊÐí±ðµÄÉ豸ÉêÇëͬһ¸ö
Öжϡ£ÐèҪעÒâËùÓÐÓõ½Õâ¸öÖжϵÄÉ豸ÔÚµ÷ÓÃrequest_irq()¶¼±ØÐëÉèÖÃÕâ¸öÊô
ÐÔ¡£ÏµÍ³Ôڻص÷ÿ¸öÖжϴ¦Àí³ÌÐòʱ£¬¿ÉÒÔÓÃdev_idÕâ¸ö²ÎÊýÕÒµ½ÏàÓ¦µÄÉ豸¡£Ò»
°ãdev_id¾ÍÉèΪdevice½á¹¹±¾Éí¡£ÏµÍ³´¦Àí¹²ÏíÖжÏÊÇÓø÷×ÔµÄdev_id²ÎÊýÒÀ´Îµ÷
ÓÃÿһ¸öÖжϴ¦Àí³ÌÐò¡£
3.2 Ó²¼þ·¢ËÍæʱµÄ´¦Àí
Ö÷CPUµÄ´¦ÀíÄÜÁ¦Ò»°ã±ÈÍøÂç·¢ËÍÒª¿ì£¬ËùÒÔ¾­³£»áÓöµ½ÏµÍ³ÓÐÊý¾ÝÒª·¢£¬µ«
ÉÏÒ»°üÊý¾ÝÍøÂçÉ豸»¹Ã»·¢ËÍÍê¡£ÒòΪÔÚLinuxÀïÍøÂçÉ豸Çý¶¯³ÌÐòÒ»°ã²»×öÊý¾Ý
»º´æ£¬²»ÄÜ·¢Ë͵ÄÊý¾Ý¶¼ÊÇ֪ͨϵͳ·¢ËͲ»³É¹¦£¬ËùÒÔ±ØÐëÒªÓÐÒ»¸ö»úÖÆÔÚÓ²¼þ²»
æʱ¼°Ê±Í¨ÖªÏµÍ³½Ó×Å·¢ËÍÏÂÃæµÄÊý¾Ý¡£
Ò»°ã¶Ô·¢ËÍæµÄ´¦ÀíÔÚÇ°ÃæÉ豸µÄ·¢ËÍ·½·¨(hard_start_xmit)ÀïÒѾ­ÃèÊö¹ý£¬
¼´Èç¹û·¢ËÍæ£¬ÖÃtbusyΪ1¡£´¦ÀíÍê·¢ËÍÊý¾Ýºó£¬ÔÚ·¢ËͽáÊøÖжÏÀïÇåtbusy£¬Í¬
ʱÓÃmark_bh()µ÷ÓÃ֪ͨϵͳ¼ÌÐø·¢ËÍ¡£
µ«ÔÚ¾ßÌåʵÏÖÎÒµÄÇý¶¯³ÌÐòʱ·¢ÏÖ£¬ÕâÑùµÄ´¦ÀíϵͳºÃÏó²¢²»Äܼ°Ê±µØÖªµÀÓ²
¼þÒѾ­¿ÕÏÐÁË£¬¼´ÔÚmark_bh()ÒÔºó£¬ÏµÍ³ÒªµÈÒ»¶Îʱ¼ä²Å»á½Ó×Å·¢ËÍ¡£Ôì³É·¢ËÍ
ЧÂʺܵ͡£2MÏß·ֻÓÐ10%²»µ½µÄʹÓÃÂÊ¡£Äں˰汾Ϊ2.0.35¡£
ÎÒ×îºóµÄʵÏÖÊDz»°ÑtbusyÖÃ1£¬ÈÃϵͳʼÖÕÈÏΪӲ¼þ¿ÕÏУ¬µ«ÊDZ¨¸æ·¢ËͲ»³É
¹¦¡£ÏµÍ³»áÒ»Ö±³¢ÊÔÖØ·¢¡£ÕâÑù´¦Àí¾ÍÔËÐÐÕý³£ÁË¡£µ«ÊDZéÑ­ÄÚºËÔ´ÂëÖеÄÍøÂçÇý
¶¯³ÌÐò£¬ËƺõûÓÐÕâÑù´¦ÀíµÄ¡£²»ÖªµÀÖ¢½áÔÚÄÄÀï¡£
3.3 Á÷Á¿¿ØÖÆ(flow control)
ÍøÂçÊý¾ÝµÄ·¢ËͺͽÓÊÕ¶¼ÐèÒªÁ÷Á¿¿ØÖÆ¡£ÕâЩ¿ØÖÆÊÇÔÚϵͳÀïʵÏֵ쬲»ÐèÒª
Çý¶¯³ÌÐò×ö¹¤×÷¡£Ã¿¸öÉ豸Êý¾Ý½á¹¹Àï¶¼ÓÐÒ»¸ö²ÎÊýdev->tx_queue_len£¬Õâ¸ö²ÎÊý
±êÃ÷·¢ËÍʱ×î¶à»º´æµÄÊý¾Ý°ü¡£ÔÚLinuxϵͳÀïÒÔÌ«ÍøÉ豸(10/100Mbps)
tx_queue_lenÒ»°ãÉèÖÃΪ100£¬´®ÐÐÏß·(Òì²½´®¿Ú)Ϊ10¡£Êµ¼ÊÉÏÈç¹û¿´Ô´Âë¿ÉÒÔ
ÖªµÀ£¬ÉèÖÃÁËdev->tx_queue_len²¢²»ÊÇΪ»º´æÕâЩÊý¾ÝÉêÇëÁ˿ռ䡣Õâ¸ö²ÎÊýÖ»ÊÇ
ÔÚÊÕµ½Ð­Òé²ãµÄÊý¾Ý°üʱÅжϷ¢ËͶÓÁÐÀïµÄÊý¾ÝÊDz»Êǵ½ÁËtx_queue_lenµÄÏÞ¶È£¬
ÒÔ¾ö¶¨ÕâÒ»°üÊý¾Ý¼Ó²»¼Ó½ø·¢ËͶÓÁС£·¢ËÍʱÁíÒ»¸ö·½ÃæµÄÁ÷¿ØÊǸü¸ß²ãЭÒéµÄ·¢
ËÍ´°¿Ú(TCPЭÒéÀï¾ÍÓз¢ËÍ´°¿Ú)¡£´ïµ½ÁË´°¿Ú´óС£¬¸ß²ãЭÒé¾Í²»»áÔÙ·¢ËÍÊý¾Ý¡£
½ÓÊÕÁ÷¿ØÒ²·ÖÁ½¸ö²ã´Î¡£netif_rx()»º´æµÄÊý¾Ý°üÓÐÏÞÖÆ¡£ÁíÍâ¸ß²ãЭÒéÒ²»á
ÓÐÒ»¸ö×î´óµÄµÈ´ý´¦ÀíµÄÊý¾ÝÁ¿¡£
·¢ËͺͽÓÊÕÁ÷¿Ø´¦ÀíÔÚnet/core/dev.cµÄdo_dev_queue_xmit()ºÍnetif_rx()
ÖС£
3.4 µ÷ÊÔ
ºÜ¶àLinuxµÄÇý¶¯³ÌÐò¶¼ÊDZàÒë½øÄں˵ģ¬ÐγÉÒ»¸ö´óµÄÄÚºËÎļþ¡£µ«¶Ôµ÷ÊÔ
À´Ëµ£¬ÕâÊÇÏ൱Âé·³µÄ¡£µ÷ÊÔÇý¶¯³ÌÐò¿ÉÒÔÓÃmodule·½Ê½¼ÓÔØ¡£Ö§³ÖÄ£¿é·½Ê½µÄ
Çý¶¯³ÌÐò±ØÐëÌṩÁ½¸öº¯Êý£ºint init_module(void)ºÍvoid cleanup_module(void)¡£

init_module()ÔÚ¼ÓÔØ´ËÄ£¿éʱµ÷Óã¬ÔÚÕâ¸öº¯ÊýÀï¿ÉÒÔregister_netdev()×¢²á
É豸¡£init_module()·µ»Ø0±íʾ³É¹¦£¬·µ»Ø¸º±íʾʧ°Ü¡£cleanup_module()ÔÚÇý¶¯
³ÌÐò±»Ð¶ÔØÊ±µ÷Óã¬Çå³ýÕ¼ÓõÄ×ÊÔ´£¬µ÷ÓÃunregister_netdev()¡£
Ä£¿é¿ÉÒÔ¶¯Ì¬µØ¼ÓÔØ¡¢Ð¶ÔØ¡£ÔÚ2.0.xx°æ±¾À»¹ÓÐkerneld×Ô¶¯¼ÓÔØÄ£¿é£¬
µ«ÊÇ2.2.xxÖÐÒѾ­È¡ÏûÁËkerneld¡£ÊÖ¹¤¼ÓÔØÊ¹ÓÃinsmodÃüÁî£¬Ð¶ÔØÓÃrmmodÃüÁ
¿´ÄÚºËÖеÄÄ£¿éÓÃlsmodÃüÁî¡£
±àÒëÇý¶¯³ÌÐòÓÃgcc£¬Ö÷ÒªÃüÁîÐвÎÊý-DKERNEL -DMODULE¡£²¢ÇÒ×÷Ϊģ¿é¼ÓÔØ
µÄÇý¶¯³ÌÐò£¬Ö»±àÒë³ÉobjÐÎʽ(¼Ó-c²ÎÊý)¡£±àÒëºÃµÄÄ¿±êÎļþ·ÅÔÚ/lib/modules
/2.x.xx/miscÏ£¬ÔÚÆô¶¯ÎļþÀïÓÃinsmod¼ÓÔØ¡£
ËÄ.½øÒ»²½µÄÔĶÁ
Linux³ÌÐòÉè¼Æ×ÊÁÏ¿ÉÒÔ´ÓÍøÉÏ»ñµÃ¡£Õâ¾ÍÊÇ¿ª·ÅÔ´´úÂëµÄºÃ´¦¡£²¢ÇÒûÓÐʲ
ô¡°Î´¹«¿ªµÄÃØÃÜ¡±¡£ÎÒ±àдÇý¶¯³ÌÐòʱ²ÎÔĵÄÖ÷Òª×ÊÁϰüÀ¨£º
LinuxÄÚºËÔ´´úÂë
<> by Michael K. Johnson
<> by Ori Pomerantz
<> by olly in BBSˮľÇ廪վ
¿ÉÒÔÑ¡ÔñÒ»¸öÄ£°å×÷Ϊ¿ªÊ¼£¬ÄÚºËÔ´´úÂëÀïÓÐÒ»¸öÍøÂçÇý¶¯³ÌÐòµÄÄ£°å£¬
drivers/net/skeleton.c¡£ÀïÃæ°üº¬ÁËÇý¶¯³ÌÐòµÄ»ù±¾ÄÚÈÝ¡£µ«Õâ¸öÄ£°åÊÇÒÔÒÔÌ«
ÍøÉ豸Ϊ¶ÔÏóµÄ£¬ÒÔÌ«ÍøµÄ´¦ÀíÔÚLinuxϵͳÀïÓÐÌØÊâ¡°´ýÓö¡±£¬ËùÒÔÈç¹û²»ÊÇÒÔ
Ì«ÍøÉ豸£¬ÓÐЩϸ½ÚÉÏҪעÒ⣬Ö÷ÒªÔÚ³õʼ»¯³ÌÐòÀï¡£
×îºó£¬¶à²ÎÕÕ±ðÈËдµÄ³ÌÐò£¬ÌýÌýÆäËû¿ª·¢Õߵľ­Ñé̸֮´ó¸ÅÊÇ×îÓÐЧµÄ°ïÖú
ÁË¡£

 

 

 

LinuxµÄÔ´ÂëÀï£¬ÍøÂç½Ó¿ÚµÄʵÏÖ²¿·ÝÊǷdz£ÖµµÃÒ»¶ÁµÄ£¬Í¨¹ý¶ÁÔ´Â룬²»½ö¶ÔÍøÂçЭÒé»áÓиüÉîµÄÁ˽⣬ҲÓÐÖúÓÚÔÚÍøÂç±à³ÌµÄʱºò£¬¶ÔÓ¦Óú¯ÊýÓиü¾«È·µÄÁ˽âºÍ°ÑÎÕ¡£

¡¡¡¡±¾ÎİÑÖØµã·ÅÔÚÍøÂç½Ó¿Ú³ÌÐòµÄ×ÜÌå½á¹¹ÉÏ£¬Ï£ÍûÄÜ×÷Ϊ¶ÁÔ´ÂëʱһЩָµ¼ÐÔµÄÎÄ×Ö¡£

¡¡¡¡±¾ÎÄÒÔLinux2.4.16ÄÚºË×÷Ϊ½²½âµÄ¶ÔÏó£¬ÄÚºËÔ´Âë¿ÉÒÔÔÚhttp://www.kernel.orgÉÏÏÂÔØ¡£ÎÒ¶ÁÔ´Âëʱ²Î¿¼µÄÊÇhttp://lxr.linux.no/Õâ¸ö½»²î²Î¿¼µÄÍøÕ¾£¬ÎÒ¸öÈËÈÏΪÊÇÒ»¸öºÜºÃµÄ¹¤¾ß£¬Èç¹ûÓÐÌõ¼þ×îºÃÉÏÕâ¸öÍøÕ¾¡£

¡¡¡¡¶þ.ÍøÂç½Ó¿Ú³ÌÐòµÄ½á¹¹

¡¡¡¡LinuxµÄÍøÂç½Ó¿Ú·ÖΪËIJ¿·Ý£ºÍøÂçÉ豸½Ó¿Ú²¿·Ý£¬ÍøÂç½Ó¿ÚºËÐIJ¿·Ý£¬ÍøÂçЭÒé×岿·Ý£¬ÒÔ¼°ÍøÂç½Ó¿Úsocket²ã¡£
¡¡¡¡ÍøÂçÉ豸½Ó¿Ú²¿·ÝÖ÷Òª¸ºÔð´ÓÎïÀí½éÖʽÓÊպͷ¢ËÍÊý¾Ý¡£ÊµÏÖµÄÎļþÔÚlinu/driver/netĿ¼ÏÂÃæ¡£

¡¡¡¡ÍøÂç½Ó¿ÚºËÐIJ¿·ÝÊÇÕû¸öÍøÂç½Ó¿ÚµÄ¹Ø¼ü²¿Î»£¬ËüÎªÍøÂçЭÒéÌṩͳһµÄ·¢Ëͽӿڣ¬ÆÁ±Î¸÷ÖÖ¸÷ÑùµÄÎïÀí½éÖÊ£¬Í¬Ê±ÓиºÔð°ÑÀ´×ÔϲãµÄ°üÏòºÏÊʵÄЭÒéÅäËÍ¡£ËüÊÇÍøÂç½Ó¿ÚµÄÖÐÊಿ·Ý¡£ËüµÄÖ÷ҪʵÏÖÎļþÔÚlinux/net/coreĿ¼Ï£¬ÆäÖÐlinux/net/core/dev.cΪÖ÷Òª¹ÜÀíÎļþ¡£

¡¡¡¡ÍøÂçЭÒé×岿·ÝÊǸ÷ÖÖ¾ßÌåЭÒéʵÏֵIJ¿·Ý¡£LinuxÖ§³ÖTCP/IP£¬IPX£¬X.25£¬AppleTalkµÈµÄЭÒ飬¸÷ÖÖ¾ßÌåЭÒéʵÏÖµÄÔ´ÂëÔÚlinux/net/Ŀ¼ÏÂÏàÓ¦µÄÃû³Æ¡£ÔÚÕâÀïÖ÷ÒªÌÖÂÛTCP/IP(IPv4)ЭÒ飬ʵÏÖµÄÔ´ÂëÔÚlinux/net/ipv4,ÆäÖÐlinux/net/ipv4/af_inet.cÊÇÖ÷ÒªµÄ¹ÜÀíÎļþ¡£

¡¡¡¡ÍøÂç½Ó¿ÚSocket²ãΪÓû§ÌṩµÄÍøÂç·þÎñµÄ±à³Ì½Ó¿Ú¡£Ö÷ÒªµÄÔ´ÂëÔÚlinux/net/socket.c

¡¡¡¡Èý.ÍøÂçÉ豸½Ó¿Ú²¿·Ý

¡¡¡¡ÎïÀí²ãÉÏÓÐÐí¶à²»Í¬ÀàÐ͵ÄÍøÂç½Ó¿ÚÉ豸, ÔÚÎļþinclude/linux/if_arp.hµÄ28ÐÐÀﶨÒåÁËARPÄÜ´¦ÀíµÄ¸÷ÖÖµÄÎïÀíÉ豸µÄ±êÖ¾·û¡£ÍøÂçÉ豸½Ó¿ÚÒª¸ºÔð¾ßÌåÎïÀí½éÖʵĿØÖÆ£¬´ÓÎïÀí½éÖʽÓÊÕÒÔ¼°·¢ËÍÊý¾Ý£¬²¢¶ÔÎïÀí½éÖʽøÐÐÖîÈç×î´óÊý¾Ý°üÖ®ÀàµÄ¸÷ÖÖÉèÖá£ÕâÀïÎÒÃÇÒԱȽϼòµ¥µÄ3Com3c501 Ì«Íø¿¨µÄÇý¶¯³ÌÐòΪÀý£¬´ó¸Å½²Ò»ÏÂÕâ²ãµÄ¹¤×÷Ô­Àí¡£Ô´ÂëÔÚLinux/drivers/net/3c501.c¡£

¡¡¡¡ÎÒÃÇ´ÓÖ±¾õÉÏÀ´¿¼ÂÇ£¬Ò»¸öÍø¿¨µ±È»×îÖ÷ÒªµÄÊÇÍê³ÉÊý¾ÝµÄ½ÓÊպͷ¢ËÍ£¬ÔÚÕâÀïÎÒÃÇÀ´¿´¿´½ÓÊպͷ¢Ë͵Ĺý³ÌÊÇÔõôÑùµÄ¡£

¡¡¡¡·¢ËÍÏà¶ÔÀ´Ëµ±È½Ï¼òµ¥£¬ÔÚLinux/drivers/net/3c501.cµÄÐÐ475 ¿ªÊ¼µÄel_start_xmit()Õâ¸öº¯Êý¾ÍÊÇʵ¼ÊÏò3Com3c501ÒÔÌ«Íø¿¨·¢ËÍÊý¾ÝµÄº¯Êý£¬¾ßÌåµÄ·¢Ë͹¤×÷²»ÍâºõÊǶÔһЩ¼Ä´æÆ÷µÄ¶Áд£¬Ô´ÂëµÄ×¢ÊͺÜÇå³þ£¬´ó¼Ò¿ÉÒÔ¿´¿´¡£

¡¡¡¡½ÓÊյŤ×÷Ïà¶ÔÀ´Ëµ±È½Ï¸´ÔÓ¡£Í¨³£À´Ëµ£¬Ò»¸öеİüµ½ÁË£¬»òÕßÒ»¸ö°ü·¢ËÍÍê³ÉÁË£¬¶¼»á²úÉúÒ»¸öÖжϡ£Linux/drivers/net/3c501.cµÄ572¿ªÊ¼el_interrupt()µÄº¯ÊýÀïÃæ£¬Ç°°ë²¿·Ý´¦ÀíµÄÊǰü·¢ËÍÍêÒÔºóµÄ»ã±¨£¬ºó°ë²¿·Ý´¦ÀíµÄÊÇÒ»¸öеİüÀ´µÄ£¬¾ÍÊÇ˵½ÓÊÕµ½ÁËеÄÊý¾Ý¡£el_interrupt()º¯Êý²¢Ã»ÓжÔеİü½øÐÐÌ«¶àµÄ´¦Àí£¬¾Í½»¸øÁ˽ÓÊÕ´¦Àíº¯Êýel_receive()¡£el_receive()Ê×Ïȼì²é½ÓÊյİüÊÇ·ñÕýÈ·£¬Èç¹ûÊÇÒ»¸ö¡°ºÃ¡±°ü¾Í»áΪ°ü·ÖÅäÒ»¸ö»º³å½á¹¹(dev_alloc_skb())£¬ÕâÑùÇý¶¯³ÌÐò¶Ô°üµÄ½ÓÊÕ¹¤×÷¾ÍÍê³ÉÁË£¬Í¨¹ýµ÷ÓÃÉϲãµÄº¯Êýnetif_rx()(net/core/dev.c1214ÐÐ) £¬°Ñ°ü½»¸øÉϲ㡣

¡¡¡¡ÏÖÔÚÇý¶¯³ÌÐòÓÐÁË·¢ËͺͽÓÊÕÊý¾ÝµÄ¹¦ÄÜÁË£¬Çý¶¯³ÌÐòÔõôÑùºÍÉϲ㽨Á¢ÁªÏµÄØ£¿¾ÍÊÇ˵½ÓÊÕµ½°üÒÔºóÔõôË͸øÉϲ㣬ÒÔ¼°ÉϲãÔõôÄܵ÷ÓÃÇý¶¯³ÌÐòµÄ·¢Ëͺ¯ÊýÄØ£¿

¡¡¡¡ÓÉÏÂÍùÉϵĹØÏµ£¬ÊÇͨ¹ýÇý¶¯³ÌÐòµ÷ÓÃÉϲãµÄnetif_rx()(net/core/dev.c 1214ÐÐ)º¯ÊýʵÏֵģ¬Çý¶¯³ÌÐòͨ¹ýÕâ¸öº¯Êý°Ñ½Óµ½µÄÊý¾Ý½»¸øÉϲ㣬Çë×¢ÒâËùÓеÄÍø¿¨Çý¶¯³ÌÐò¶¼ÐèÒªµ÷ÓÃÕâ¸öº¯ÊýµÄ£¬ÕâÊÇÍøÂç½Ó¿ÚºËÐIJãºÍÍøÂç½Ó¿ÚÉ豸ÁªÏµµÄÇÅÁº¡£

¡¡¡¡ÓÉÉÏÍùÏµĹØÏµ¾Í¸´ÔÓµã¡£ÍøÂç½Ó¿ÚºËÐIJãÐèÒªÖªµÀÓжàÉÙÍøÂçÉ豸¿ÉÒÔÓã¬Ã¿¸öÉ豸µÄº¯ÊýµÄÈë¿ÚµØÖ·µÈ¶¼ÒªÖªµÀ¡£ÍøÂç½Ó¿ÚºËÐIJã»á´óÉùº°£¬¡°ºÙ£¬ÓжàÉÙÉ豸¿ÉÒÔ°ïÎÒ·¢ËÍÊý¾Ý°ü£¿ÄÜ·¢Ë͵ÄÇë¸øÎÒÅųÉÒ»¶Ó£¡¡±¡£ÕâÒ»¶Ó¾ÍÓÉdev_base¿ªÊ¼£¬Ö¸Õëstructnet_device *dev_base (Linux/include/linux/netdevice.h 436ÐÐ)¾ÍÊDZ£´æÁËÍøÂç½Ó¿ÚºËÐIJãËùÖªµÀµÄËùÓÐÉ豸¡£¶ÔÓÚÍøÂç½Ó¿ÚºËÐIJãÀ´Ëµ£¬ËùÓеÄÉ豸¶¼ÊÇÒ»¸önet_device½á¹¹£¬ËüÔÚinclude/linux/netdevice.h,line 233Àï±»¶¨Ò壬ÕâÊÇ´ÓÍøÂç½Ó¿ÚºËÐIJãµÄ½Ç¶È¿´µ½µÄÒ»¸ö³éÏóµÄÉ豸£¬ÎÒÃÇÀ´¿´¿´ÍøÂç½Ó¿ÚºËÐIJãµÄ½Ç¶È¿´µ½µÄÍøÂçÉ豸¾ßÓеŦÄÜ£º

¡¡¡¡struct net_device {
¡¡¡¡¡­¡­¡­
¡¡¡¡open()
¡¡¡¡stop()
¡¡¡¡hard_start_xmit()
¡¡¡¡hard_header()
¡¡¡¡rebuild_header()
¡¡¡¡set_mac_address()
¡¡¡¡do_ioctl()
¡¡¡¡set_config()
¡¡¡¡hard_header_cache()
¡¡¡¡header_cache_update()
¡¡¡¡change_mtu()
¡¡¡¡tx_timeout()
¡¡¡¡hard_header_parse()
¡¡¡¡neigh_setup()
¡¡¡¡accept_fastpath()
¡¡¡¡¡­¡­¡­
¡¡¡¡}

¡¡¡¡Èç¹ûÍøÂç½Ó¿ÚºËÐIJãÐèÒªÓÉϲ㷢ËÍÊý¾ÝµÄʱºò£¬ÔÚdev_baseÕÒµ½É豸ÒԺ󣬾ÍÖ±½Óµ÷dev->hard_start_xmit()µÄÕâ¸öº¯ÊýÀ´ÈÃϲ㷢Êý¾Ý°ü¡£

¡¡¡¡Çý¶¯³ÌÐòÒªÈÃÍøÂç½Ó¿ÚºËÐIJãÖªµÀ×Ô¼ºµÄ´æÔÚ£¬µ±È»Òª¼ÓÈëdev_baseËùÖ¸ÏòµÄÖ¸ÕëÁ´£¬È»ºó°Ñ×Ô¼ºµÄº¯ÊýÒÔ¼°¸÷ÖÖ²ÎÊýºÍnet_deviceÀïµÄÏàÓ¦µÄÓò¶ÔÓ¦ÆðÀ´¡£¼ÓÈëdev_baseËùÖ¸ÏòµÄÖ¸ÕëÁ´ÊÇͨ¹ýº¯Êýregister_netdev(&dev_3c50)(linux/drivers/net/net_init.c, line 532)

¡¡¡¡½¨Á¢µÄ¡£¶ø°Ñ×Ô¼ºµÄº¯ÊýÒÔºÍnet_deviceÀïµÄÏàÓ¦µÄÓò¼°¸÷ÖÖ²ÎÊý¹ØÏµµÄ½¨Á¢ÊÇÔÚel1_probe1()(Linux/drivers/net/3c501.c)Àï½øÐеģº

¡¡¡¡el1_probe1(){
¡¡¡¡¡­¡­¡­
¡¡¡¡dev->open = &el_open;
¡¡¡¡dev->hard_start_xmit = &el_start_xmit;
¡¡¡¡dev->tx_timeout = &el_timeout;
¡¡¡¡dev->watchdog_timeo = HZ;
¡¡¡¡dev->stop = &el1_close;
¡¡¡¡dev->get_stats = &el1_get_stats;
¡¡¡¡dev->set_multicast_list = &set_multicast_list;
¡¡¡¡¡­¡­¡­
¡¡¡¡ether_setup(dev);
¡¡¡¡¡­¡­¡­

¡¡¡¡}

¡¡¡¡½øÒ»²½µÄ¶ÔÓ¦¹¤×÷ÔÚether_setup(dev) (drivers/net/net_init.c, line 405 )Àï½øÐС£ÎÒÃÇ×¢Òâµ½dev->hard_start_xmit =&el_start_xmit£¬ÕâÑù·¢Ëͺ¯ÊýµÄ¹ØÏµ¾Í½¨Á¢ÁË£¬ÉϲãÖ»ÖªµÀµ÷ÓÃdev->hard_start_xmitÕâ¸öÀ´·¢ËÍÊý¾Ý£¬ÉÏÃæµÄÓï¾ä¾Í°ÑÇý¶¯³ÌÐòʵ¼ÊµÄ·¢Ëͺ¯Êý¸æËßÁËÉϲ㡣

¡¡¡¡ËÄ.ÍøÂç½Ó¿ÚºËÐIJ¿·Ö

¡¡¡¡¸Õ²Å̸ÂÛÁËÇý¶¯³ÌÐòÔõôºÍÍøÂç½Ó¿ÚºËÐIJãÏνӵġ£ÍøÂç½Ó¿ÚºËÐIJãÖªµÀÇý¶¯³ÌÐòÒÔ¼°Çý¶¯³ÌÐòµÄº¯ÊýµÄÈë¿ÚÊÇͨ¹ý*dev_baseÖ¸ÏòµÄÉ豸Á´µÄ£¬¶øÏ²ãÊÇͨ¹ýµ÷ÓÃÕâÒ»²ãµÄº¯Êýnetif_rx()(net/core/dev.c
1214ÐÐ) °ÑÊý¾Ý´«µÝ¸öÕâÒ»²ãµÄ¡£

¡¡¡¡ÍøÂç½Ó¿ÚºËÐIJãµÄÉϲãÊǾßÌåµÄÍøÂçЭÒ飬ϲãÊÇÇý¶¯³ÌÐò£¬ÎÒÃÇÒÔ¼°½â¾öÁËϲãµÄ¹ØÏµ£¬µ«ºÍÉϲãµÄ¹ØÏµÃ»Óнâ¾ö¡£ÏÈÀ´ÌÖÂÛÒ»ÏÂÍøÂç½Ó¿ÚºËÐIJãºÍÍøÂçЭÒé×岿·ÝµÄ¹ØÏµ£¬ÕâÖÖ¹ØÏµ²»ÍâºõÒ²ÊǽÓÊպͷ¢Ë͵ĹØÏµ¡£

¡¡¡¡ÍøÂçЭÒ飬ÀýÈçIP£¬ARPµÈµÄЭÒéÒª·¢ËÍÊý¾Ý°üµÄʱºò»á°ÑÊý¾Ý°ü´«µÝ¸øÕâ²ã£¬ÄÇôÕâÖÖ´«µÝÊÇͨ¹ýʲôº¯ÊýÀ´·¢ÉúµÄÄØ£¿ÍøÂç½Ó¿ÚºËÐIJãͨ¹ýdev_queue_xmit()(net/core/dev.c,line975)Õâ¸öº¯ÊýÏòÉϲãÌṩͳһµÄ·¢Ëͽӿڣ¬Ò²¾ÍÊÇ˵ÎÞÂÛÊÇIP£¬»¹ÊÇARPЭÒ飬ͨ¹ýÕâ¸öº¯Êý°ÑÒª·¢Ë͵ÄÊý¾Ý´«µÝ¸øÕâÒ»²ã£¬Ïë·¢ËÍÊý¾ÝµÄʱºò¾Íµ÷ÓÃÕâ¸öº¯Êý¾Í¿ÉÒÔÁË¡£dev_queue_xmit()×öµÄ¹¤×÷×îºó»áÂäʵµ½dev->hard_start_xmit()£¬¶ødev->hard_start_xmit()»áµ÷ÓÃʵ¼ÊµÄÇý¶¯³ÌÐòÀ´Íê³É·¢Ë͵ÄÈÎÎñ¡£ÀýÈçÉÏÃæµÄÀý×ÓÖУ¬µ÷ÓÃdev->hard_start_xmit()ʵ¼Ê¾ÍÊǵ÷ÓÃÁËel_start_xmit()¡£

¡¡¡¡ÏÖÔÚÌÖÂÛ½ÓÊÕµÄÇé¿ö¡£ÍøÂç½Ó¿ÚºËÐIJãͨ¹ýµÄº¯Êýnetif_rx()(net/core/dev.c 1214ÐÐ)½ÓÊÕÁËÉϲ㷢ËÍÀ´µÄÊý¾Ý£¬Õâʱºòµ±È»Òª°ÑÊý¾Ý°üÍùÉϲãÅÉËÍ¡£ËùÓеÄЭÒé×åµÄϲãЭÒé¶¼ÐèÒª½ÓÊÕÊý¾Ý£¬TCP/IPµÄIPЭÒéºÍARPЭÒ飬SPX/IPXµÄIPXЭÒ飬AppleTalkµÄDDPºÍAARPЭÒéµÈ¶¼ÐèÒªÖ±½Ó´ÓÍøÂç½Ó¿ÚºËÐIJã½ÓÊÕÊý¾Ý£¬ÍøÂç½Ó¿ÚºËÐIJã½ÓÊÕÊý¾ÝÊÇÈçºÎ°Ñ°ü·¢¸øÕâЩЭÒéµÄÄØ£¿ÕâʱµÄÇéÐκÍÓÚϲãµÄ¹ØÏµºÜÏàËÆ£¬ÍøÂç½Ó¿ÚºËÐIJãµÄÏÂÃæ¿ÉÄÜÓÐÐí¶àµÄÍø¿¨µÄÇý¶¯³ÌÐò£¬ÎªÁËÖªµÀÔõôÏòÕâЩÇý¶¯³ÌÐò·¢Êý¾Ý£¬Ç°ÃæÒÔ¼°½²¹ýʱ£¬ÊÇͨ¹ý*dev_baseÕâ¸öÖ¸ÕëÖ¸ÏòµÄÁ´½â¾öµÄ£¬ÏÖÔÚ½â¾öºÍÉϲãµÄ¹ØÏµÊÇͨ¹ýstatic struct packet_ptype_base[16]( net/core/dev.c line 164)Õâ¸öÊý×é½â¾öµÄ¡£Õâ¸öÊý×é°üº¬ÁËÐèÒª½ÓÊÕÊý¾Ý°üµÄЭÒ飬ÒÔ¼°ËüÃǵĽÓÊÕº¯ÊýµÄÈë¿Ú¡£

¡¡¡¡´ÓÉÏÃæ¿ÉÒÔ¿´µ½£¬IPЭÒé½ÓÊÕÊý¾ÝÊÇͨ¹ýip_rcv()º¯ÊýµÄ£¬¶øARPЭÒéÊÇͨ¹ýarp_rcv()µÄ£¬ÍøÂç½Ó¿ÚºËÐIJãֻҪͨ¹ýÕâ¸öÊý×é¾Í¿ÉÒÔ°ÑÊý¾Ý½»¸øÉϲ㺯ÊýÁË¡£

¡¡¡¡Èç¹ûÓÐЭÒéÏë°Ñ×Ô¼ºÌí¼Óµ½Õâ¸öÊý×飬ÊÇͨ¹ýdev_add_pack()(net/core/dev.c, line233)º¯Êý£¬´ÓÊý×éɾ³ýÊÇͨ¹ýdev_remove_pack()º¯ÊýµÄ¡£Ip²ãµÄ×¢²áÊÇÔÚ³õʼ»¯º¯Êý½øÐеÄvoid __init ip_init(void) (net/ipv4/ip_output.c, line 1003)

¡¡¡¡{
¡¡¡¡¡­¡­¡­
¡¡¡¡dev_add_pack(&ip_packet_type);
¡¡¡¡¡­¡­¡­

¡¡¡¡}

¡¡¡¡ÖØÐµ½»ØÎÒÃǹØÓÚ½ÓÊÕµÄÌÖÂÛ£¬ÍøÂç½Ó¿ÚºËÐIJãͨ¹ýµÄº¯Êýnetif_rx()(net/core/dev.c 1214ÐÐ)½ÓÊÕÁËÉϲ㷢ËÍÀ´µÄÊý¾Ý£¬¿´¿´Õâ¸öº¯Êý×öÁËЩʲô¡£

¡¡¡¡ÓÉÓÚÏÖÔÚ»¹ÊÇÔÚÖжϵķþÎñÀïÃæ£¬ËùÓв¢²»Äܹ»´¦ÀíÌ«¶àµÄ¶«Î÷£¬Ê£ÏµĶ«Î÷¾Íͨ¹ýcpu_raise_softirq(this_cpu, NET_RX_SOFTIRQ)

¡¡¡¡½»¸øÈíÖжϴ¦Àí£¬ ´Óopen_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL)¿ÉÒÔÖªµÀNET_RX_SOFTIRQÈíÖжϵĴ¦Àíº¯ÊýÊÇnet_rx_action()(net/core/dev.c, line 1419)£¬net_rx_action()¸ù¾ÝÊý¾Ý°üµÄЭÒéÀàÐÍÔÚÊý×éptype_base[16]ÀïÕÒµ½ÏàÓ¦µÄЭÒ飬²¢´ÓÖÐÖªµÀÁ˽ÓÊյĴ¦Àíº¯Êý£¬È»ºó°ÑÊý¾Ý°ü½»¸ø´¦Àíº¯Êý£¬ÕâÑù¾Í½»¸øÁËÉϲ㴦Àí£¬Êµ¼Êµ÷Óô¦Àíº¯ÊýÊÇͨ¹ýnet_rx_action()ÀïµÄpt_prev->func()ÕâÒ»¾ä¡£ÀýÈçÈç¹ûÊý¾Ý°üÊÇIPЭÒéµÄ»°£¬ptype_base[ETH_P_IP]->func()(ip_rcv()),ÕâÑù¾Í°ÑÊý¾Ý°ü½»¸øÁËIPЭÒé¡£

¡¡¡¡Îå.ÍøÂçЭÒ鲿·Ö

¡¡¡¡Ð­Òé²ãÊÇÕæÕýʵÏÖÊÇÔÚÕâÒ»²ã¡£ÔÚlinux/include/linux/socket.hÀïÃæ£¬LinuxµÄBSD
Socket¶¨ÒåÁ˶àÖÁ32Ö§³ÖµÄЭÒé×壬ÆäÖÐPF_INET¾ÍÊÇÎÒÃÇ×îÊìϤµÄTCP/IPЭÒé×å(IPv4, ÒÔÏÂûÓÐÌØ±ðÉùÃ÷¶¼Ö¸IPv4)¡£ÒÔÕâ¸öЭÒé×åΪÀý£¬¿´¿´Õâ²ãÊÇÔõô¹¤×÷µÄ¡£ÊµÏÖTCP/IPЭÒé×åµÄÖ÷ÒªÎļþÔÚinux/net/ipv4/Ŀ¼ÏÂÃæ£¬Linux/net/ipv4/af_inet.cΪÖ÷ÒªµÄ¹ÜÀíÎļþ¡£

¡¡¡¡ÔÚLinux2.4.16ÀïÃæ£¬ÊµÏÖÁËTCP/IPЭÒé×åÀïÃæµÄµÄIGMP,TCP,UDP,ICMP,ARP,IP¡£ÎÒÃÇÏÈÌÖÂÛÒ»ÏÂÕâЩЭÒéÖ®¼äµÄ¹ØÏµ¡£IPºÍARPЭÒéÊÇÐèÒªÖ±½ÓºÍÍøÂçÉ豸½Ó¿Ú´ò½»µÀµÄЭÒ飬Ҳ¾ÍÊÇÐèÒª´ÓÍøÂçºËÐÄÄ£¿é(core)
½ÓÊÕÊý¾ÝºÍ·¢ËÍÊý¾ÝµÄ¡£¶øÆäËüЭÒéTCP,UDP,IGMP,ICMPÊÇÐèÒªÖ±½ÓÀûÓÃIPЭÒéµÄ£¬ÐèÒª´ÓIPЭÒé½ÓÊÕÊý¾Ý£¬ÒÔ¼°ÀûÓÃIPЭÒé·¢ËÍÊý¾Ý£¬Í¬Ê±»¹ÒªÏòÉϲãSocket²ãÌṩֱ½ÓµÄµ÷Óýӿڡ£¿ÉÒÔ¿´µ½IP²ãÊÇÒ»¸öºËÐĵÄЭÒ飬ÏòÏÂÐèÒªºÍϲã´ò½»µÀ£¬ÓÖÒªÏòÉϲãÌṩËùÒԵĴ«ÊäºÍ½ÓÊյķþÎñ¡£

¡¡¡¡ÏÈÀ´¿´¿´IPЭÒé²ã¡£ÍøÂçºËÐÄÄ£¿é(core) Èç¹û½ÓÊÕµ½IP²ãµÄÊý¾Ý£¬Í¨¹ýptype_base[ETH_P_IP] Êý×éµÄIP²ãµÄÏîÖ¸ÏòµÄIPЭÒéµÄip_packet_type->ip_rcv()º¯Êý°ÑÊý¾Ý°ü´«µÝ¸øIP²ã,Ò²¾ÍÊÇ˵IP²ãͨ¹ýÕâ¸öº¯Êýip_rcv()(linux/net/ipv4/ip_input.c)½ÓÊÕÊý¾ÝµÄ¡£ip_rcv()Õâ¸öº¯ÊýÖ»¶ÔIPÊý¾Ý±£×öÁËһЩchecksumµÄ¼ì²é¹¤×÷£¬Èç¹û°üÊÇÕýÈ·µÄ¾Í°Ñ°ü½»¸øÁËÏÂÒ»¸ö´¦Àíº¯Êýip_rcv_finish()(×¢Òâµ÷ÓÃÊÇͨ¹ýNF_HOOKÕâ¸öºêʵÏÖµÄ)¡£ÏÖÔÚ£¬ip_rcv_finish()Õâ¸öº¯ÊýÕæÕýÒªÍê³ÉһЩIP²ãµÄ¹¤×÷ÁË¡£IP²ãÒª×öµÄÖ÷Òª¹¤×÷¾ÍÊÇ·ÓÉ£¬Òª¾ö¶¨°ÑÊý¾Ý°üÍùÄÇÀïËÍ¡£Â·ÓɵŤ×÷ÊÇͨ¹ýº¯Êýip_route_input()(/linux/net/ipv4/route.c,line 1622)ʵÏֵġ£¶ÔÓÚ½øÀ´µÄ°ü¿ÉÄܵÄ·ÓÉÓÐÕâЩ£º

¡¡¡¡ÊôÓÚ±¾µØµÄÊý¾Ý(¼´ÊÇÐèÒª´«µÝ¸øTCP£¬UDP£¬IGMPÕâЩÉϲãЭÒéµÄ) £»
¡¡¡¡ÐèҪҪת·¢µÄÊý¾Ý°ü(Íø¹Ø»òÕßNAT·þÎñÆ÷Ö®ÀàµÄ)£»
¡¡¡¡²»¿ÉÄÜ·ÓɵÄÊý¾Ý°ü(µØÖ·ÐÅÏ¢ÓÐÎó)£»

¡¡¡¡ÎÒÃÇÏÖÔÚ¹ØÐĵÄÊÇÈç¹ûÊý¾ÝÊDZ¾µØÊý¾ÝµÄʱºòÔõô´¦Àí¡£ip_route_input()µ÷ÓÃip_route_input_slow()(net/ipv4/route.c, line 1312)£¬ÔÚip_route_input_slow()ÀïÃæµÄ1559ÐÐrth->u.dst.input=

¡¡¡¡ip_local_deliver£¬Õâ¾ÍÊÇÅжϵ½IP°üÊDZ¾µØµÄÊý¾Ý°ü£¬²¢°Ñ±¾µØÊý¾Ý°ü´¦Àíº¯ÊýµÄµØÖ··µ»Ø¡£ºÃÁË£¬Â·Óɹ¤×÷Íê³ÉÁË£¬·µ»Øµ½ip_rcv_finish()¡£ip_rcv_finish()×îºóµ÷ÓÃÀ­skb->dst->input(skb)£¬´ÓÉÏÃæ¿ÉÒÔ¿´µ½£¬ÕâÆäʵ¾ÍÊǵ÷ÓÃÁËip_local_deliver()º¯Êý£¬¶øip_local_deliver(),½Óמ͵÷ÓÃÁËip_local_deliver_finish()¡£ÏÖÔÚÕæÕýµ½ÁËÍùÉϲ㴫µÝÊý¾Ý°üµÄʱºòÁË¡£

¡¡¡¡ÏÖÔÚµÄÇéÐκÍÍøÂçºËÐÄÄ£¿é²ã(core) ÍùÉϲ㴫µÝÊý¾Ý°üµÄÇéÐηdz£ÏàËÆ,Ôõô´Ó¶à¸öЭÒéÑ¡ÔñºÏÊʵÄЭÒ飬²¢ÇÒÍùÕâ¸öЭÒé´«µÝÊý¾ÝÄØ£¿ÍøÂçÍøÂçºËÐÄÄ£¿é²ã(core) ͨ¹ýÒ»¸öÊý×éptype_base[16]±£´æÁË×¢²áÁ˵ÄËùÓпÉÒÔ½ÓÊÕÊý¾ÝµÄЭÒ飬ͬÑùÍøÂçЭÒé²ãÒ²¶¨ÒåÁËÕâÑùÒ»¸öÊý×éstruct net_protocol*inet_protos[MAX_INET_PROTOS](/linux/net/ipv4/protocol.c#L102),Ëü±£´æÁËËùÓÐÐèÒª´ÓIPЭÒé²ã½ÓÊÕÊý¾ÝµÄÉϲãЭÒé(IGMP£¬TCP£¬UDP£¬ICMP)µÄ½ÓÊÕ´¦Àíº¯ÊýµÄµØÖ·¡£ÎÒÃÇÀ´¿´¿´TCPЭÒéµÄÊý¾Ý½á¹¹ÊÇÔõôÑùµÄ£º

¡¡¡¡linux/net/ipv4/protocol.c line67
¡¡¡¡static struct inet_protocol tcp_protocol = {
¡¡¡¡handler: tcp_v4_rcv,// ½ÓÊÕÊý¾ÝµÄº¯Êý
¡¡¡¡err_handler: tcp_v4_err,// ³ö´í´¦ÀíµÄº¯Êý
¡¡¡¡next: IPPROTO_PREVIOUS,
¡¡¡¡protocol: IPPROTO_TCP,
¡¡¡¡name: "TCP"
¡¡¡¡};

¡¡¡¡µÚÒ»Ïî¾ÍÊÇÎÒÃÇ×î¹ØÐĵÄÁË£¬IP²ã¿ÉÒÔͨ¹ýÕâ¸öº¯Êý°ÑÊý¾Ý°üÍùTCP²ã´«µÄ¡£ÔÚlinux/net/ipv4/protocol.cµÄÉϲ¿£¬ÎÒÃÇ¿ÉÒÔ¿´µ½ÆäËüЭÒé²ãµÄ´¦Àíº¯ÊýÊÇigmp_rcv(),
udp_rcv(), icmp_rcv()¡£Í¬ÑùÔÚlinux/net/ipv4/protocol.c£¬ÍùÊý×éinet_protos[MAX_INET_PROTOS] ÀïÃæÌí¼ÓЭÒéÊÇͨ¹ýº¯Êýinet_add_protocol()ʵÏֵģ¬É¾³ýЭÒéÊÇͨ¹ý inet_del_protocol()ʵÏֵġ£inet_protos[MAX_INET_PROTOS]³õʼ»¯µÄ¹ý³ÌÔÚlinux/net/ipv4/af_inet.c inet_init()³õʼ»¯º¯ÊýÀïÃæ¡£

¡¡¡¡inet_init(){
¡¡¡¡¡­¡­
¡¡¡¡printk(KERN_INFO "IP Protocols: ");
¡¡¡¡for (p = inet_protocol_base; p != NULL;) {
¡¡¡¡struct inet_protocol *tmp = (struct inet_protocol *) p->next;
¡¡¡¡inet_add_protocol(p);// Ìí¼ÓЭÒé
¡¡¡¡printk("%s%s",p->name,tmp?", ":"\n");
¡¡¡¡p = tmp;
¡¡¡¡¡­¡­¡­
¡¡¡¡}


¡¡¡¡Èç¹ûÄãÔÚLinuxÆô¶¯µÄʱºòÓÐÁôÒâÆô¶¯µÄÐÅÏ¢, »òÕßÔÚlinuxÏ´òÃüÁîdmesg¾Í¿ÉÒÔ¿´µ½ÕâÒ»¶Î³ÌÐòÊä³öµÄÐÅÏ¢£º
¡¡¡¡IP Protocols£º ICMP£¬UDP£¬TCP£¬IGMPÒ²¾ÍÊÇ˵ÏÖÔÚÊý×éinet_protos[]ÀïÃæÓÐÁËICMP£¬UDP£¬TCP£¬IGMPËĸöЭÒéµÄinet_protocolÊý¾Ý½á¹¹£¬Êý¾Ý½á¹¹°üº¬ÁËËüÃǽÓÊÕÊý¾ÝµÄ´¦Àíº¯Êý¡£

¡¡¡¡Linux 2.4.16ÔÚlinux/include/linux/socket.hÀﶨÒåÁË32ÖÖÖ§³ÖµÄBSDsocketЭÒ飬³£¼ûµÄÓÐTCP/IP,IPX/SPX,X.25µÈ£¬¶øÃ¿ÖÖЭÒ黹Ìṩ²»Í¬µÄ·þÎñ£¬ÀýÈçTCP/IPЭÒéͨ¹ýTCPЭÒéÖ§³ÖÁ¬½Ó·þÎñ£¬¶øÍ¨¹ýUDPЭÒéÖ§³ÖÎÞÁ¬½Ó·þÎñ£¬Ãæ¶ÔÕâô¶àµÄЭÒ飬ÏòÓû§ÌṩͳһµÄ½Ó¿ÚÊDZØÒªµÄ£¬ÕâÖÖͳһÊÇͨ¹ýsocketÀ´½øÐеġ£

¡¡¡¡ÔÚBSD socketÍøÂç±à³ÌµÄģʽÏ£¬ÀûÓÃһϵÁеÄͳһµÄº¯ÊýÀ´ÀûÓÃͨÐŵķþÎñ¡£ÀýÈçÒ»¸öµäÐ͵ÄÀûÓÃTCPЭÒéͨÐųÌÐòÊÇÕâÑù£º

¡¡¡¡sock_descriptor = socket(AF_INET,SOCK_STREAM,0);
¡¡¡¡connect(sock_descriptor, µØÖ·£¬) £»
¡¡¡¡send(sock_descriptor,¡±hello world¡±);
¡¡¡¡recv(sock_descriptor,buffer,1024,0);

¡¡¡¡µÚÒ»¸öº¯ÊýÖ¸¶¨ÁËЭÒéInetЭÒ飬¼´TCP/IPЭÒ飬ͬʱÊÇÀûÓÃÃæÏòÁ¬½ÓµÄ·þÎñ£¬ÕâÑù¾Í¶ÔÓ¦µ½TCPЭÒ飬ÒÔºóµÄ²Ù×÷¾ÍÊÇÀûÓÃsocketµÄ±ê×¼º¯Êý½øÐеġ£

¡¡¡¡´ÓÉÏÃæÎÒÃÇ¿ÉÒÔ¿´µ½Á½¸öÎÊÌ⣬Ê×ÏÈsocket²ãÐèÒª¸ù¾ÝÓû§Ö¸¶¨µÄЭÒé×å(ÉÏÃæÊÇAF_INET)
´ÓÏÂÃæ32ÖÖЭÒéÖÐÑ¡ÔñÒ»ÖÖЭÒéÀ´Íê³ÉÓû§µÄÒªÇ󣬵±Ð­Òé×åÈ·¶¨ÒԺ󣬻¹Òª°ÑÌØ¶¨µÄ·þÎñÓ³É䵽ЭÒé×åϵľßÌåЭÒ飬ÀýÈçµ±Óû§Ö¸¶¨µÄÊÇÃæÏòÁ¬½ÓµÄ·þÎñʱ£¬InetЭÒé×å»áÓ³Éäµ½TCPЭÒé¡£

¡¡¡¡´Ó¶à¸öЭÒéÖÐÑ¡ÔñÓû§Ö¸¶¨µÄЭÒ飬²¢°Ñ¾ßÌåµÄ³öÀí½»¸øÑ¡ÖеÄЭÒ飬ÕâºÍÒ»ÆðÍøÂçºËÐIJãÏòÉϺÍÏòÏÂÏνӵÄÎÊÌâ±¾ÖÊÉÏÊÇÒ»ÑùµÄ£¬ËùÒÔ½â¾öµÄ·½·¨Ò²ÊÇÒ»ÑùµÄ£¬Í¬Ñù»¹ÊÇͨ¹ýÊý×é¡£ÔÚLinux/net/socket.c¶¨ÒåÁËÕâ¸öÊý×éstaticstruct net_proto_family *net_families[NPROTO] ¡£Êý×éµÄÔªËØÒѾ­È·¶¨ÁË£¬net_families[2] ÊÇTCP/IPЭÒ飬net_families[3]

¡¡¡¡ÊÇX.25ЭÒ飬¾ßÌåÄÇÒ»Ïî¶ÔӦʲôЭÒ飬ÔÚinclude/linux/socket.hÓж¨Òå¡£µ«ÊÇÿһÏîµÄÊý¾Ý½á¹¹net_proto_familyµÄopsÊǿյģ¬Ò²¾ÍÊǾßÌåЭÒé´¦Àíº¯ÊýµÄµØÖ·ÊDz»ÖªµÀµÄ¡£Ð­ÒéµÄ´¦Àíº¯ÊýºÍops½¨Á¢ÁªÏµÊÇͨ¹ýsock_register()(Linux/net/socket.c)Õâ¸öº¯Êý½¨Á¢µÄ£¬ÀýÈçTCP/IPЭÒéµÄÊÇÕâÑù½¨Á¢¹ØÏµµÄ£º

¡¡¡¡int __init inet_init(void) (net/ipv4/af_inet.c)
¡¡¡¡{
¡¡¡¡(void) sock_register(&inet_family_ops);

¡¡¡¡}

¡¡¡¡Ö»Òª¸ø³öAF_INET(ÔÚºêÀﶨÒåÊÇ2)£¬¾Í¿ÉÒÔÕÒµ½net_failies[2] ÀïÃæµÄ´¦Àíº¯ÊýÁË¡£

¡¡¡¡Ð­ÒéµÄÓ³ÉäÍê³ÉÁË£¬ÏÖÔÚÒª½øÐзþÎñµÄÓ³ÉäÁË¡£Éϲ㵱Ȼ²»¿ÉÄÜÖªµÀϲãµÄʲôЭÒéÄܶÔÓ¦ÌØ¶¨µÄ·þÎñ£¬ËùÒÔÕâÖÖÓ³Éä×ÔÈ»ÓÉЭÒé×å×Ô¼ºÍê³É¡£ÔÚTCP/IPЭÒé×åÀÕâÖÖÓ³ÉäÊÇͨ¹ýstruct
list_head inetsw[SOCK_MAX]( net/ipv4/af_inet.c)

¡¡¡¡Õâ¸öÊý×é½øÐÐÓ³ÉäµÄ£¬ÔÚ̸ÂÛÕâ¸öÊý×é֮ǰÎÒÃÇÀ´¿´ÁíÍâÒ»¸öÊý×éinetsw_array[](net/ipv4/af_inet.c)

¡¡¡¡static struct inet_protosw inetsw_array[] =
¡¡¡¡{
¡¡¡¡{
¡¡¡¡type: SOCK_STREAM,
¡¡¡¡protocol: IPPROTO_TCP,
¡¡¡¡prot: &tcp_prot,
¡¡¡¡ops: &inet_stream_ops,
¡¡¡¡capability: -1,
¡¡¡¡no_check: 0,
¡¡¡¡flags: INET_PROTOSW_PERMANENT,
¡¡¡¡},

¡¡¡¡{
¡¡¡¡type: SOCK_DGRAM,
¡¡¡¡protocol: IPPROTO_UDP,
¡¡¡¡prot: &udp_prot,
¡¡¡¡ops: &inet_dgram_ops,
¡¡¡¡capability: -1,
¡¡¡¡no_check: UDP_CSUM_DEFAULT,
¡¡¡¡flags: INET_PROTOSW_PERMANENT,
¡¡¡¡},

¡¡¡¡{
¡¡¡¡type: SOCK_RAW,
¡¡¡¡protocol: IPPROTO_IP, /* wild card */
¡¡¡¡prot: &raw_prot,
¡¡¡¡ops: &inet_dgram_ops,
¡¡¡¡capability: CAP_NET_RAW,
¡¡¡¡no_check: UDP_CSUM_DEFAULT,
¡¡¡¡flags: INET_PROTOSW_REUSE,
¡¡¡¡}
¡¡¡¡};


¡¡¡¡ÎÒÃÇ¿´µ½£¬SOCK_STREAMÓ³Éäµ½ÁËTCPЭÒ飬SOCK_DGRAMÓ³Éäµ½ÁËUDPЭÒ飬SOCK_RAWÓ³Éäµ½ÁËIPЭÒé¡£ÏÖÔÚÖ»Òª°Ñinetsw_arrayÀïµÄÈýÏîÌí¼Óµ½Êý×éinetsw[SOCK_MAX]¾Í¿ÉÒÔÁË£¬Ìí¼ÓÊÇͨ¹ýº¯Êýinet_register_protosw()ʵÏֵġ£ÔÚinet_init()

¡¡¡¡(net/ipv4/af_inet.c) ÀïÍê³ÉÁËÕâЩ¹¤×÷¡£

¡¡¡¡»¹ÓÐÒ»¸öÐèÒªÓ³ÉäµÄ¾ÍÊÇsocketÆäËüÖîÈçaccept,send(),

¡¡¡¡connect(),release(),bind()µÈµÄ²Ù×÷º¯ÊýÊÇÔõôӳÉäµÄÄØ£¿ÎÒÃÇÀ´¿´Ò»ÏÂÉÏÃæµÄÊý×éµÄTCPµÄÏî
¡¡¡¡{
¡¡¡¡type: SOCK_STREAM,
¡¡¡¡protocol: IPPROTO_TCP,
¡¡¡¡prot: &tcp_prot,
¡¡¡¡ops: &inet_stream_ops,
¡¡¡¡capability: -1,
¡¡¡¡no_check: 0,
¡¡¡¡flags: INET_PROTOSW_PERMANENT,
¡¡¡¡},

¡¡¡¡ÎÒÃÇ¿´µ½ÕâÖÖÓ³ÉäÊÇͨ¹ýops£¬ºÍprotÀ´Ó³ÉäµÄ£¬ÎÒÃÇÔÙÀ´¿´¿´ tcp_protÕâÒ»Ï

¡¡¡¡struct proto tcp_prot = {
¡¡¡¡name: "TCP",
¡¡¡¡close: tcp_close,
¡¡¡¡connect: tcp_v4_connect,
¡¡¡¡disconnect: tcp_disconnect,
¡¡¡¡accept: tcp_accept,
¡¡¡¡ioctl: tcp_ioctl,
¡¡¡¡init: tcp_v4_init_sock,
¡¡¡¡destroy: tcp_v4_destroy_sock,
¡¡¡¡shutdown: tcp_shutdown,
¡¡¡¡setsockopt: tcp_setsockopt,
¡¡¡¡getsockopt: tcp_getsockopt,
¡¡¡¡sendmsg: tcp_sendmsg,
¡¡¡¡recvmsg: tcp_recvmsg,
¡¡¡¡backlog_rcv: tcp_v4_do_rcv,
¡¡¡¡hash: tcp_v4_hash,
¡¡¡¡unhash: tcp_unhash,
¡¡¡¡get_port: tcp_v4_get_port,
¡¡¡¡};


¡¡¡¡ËùÒÔµÄÓ³Éä¶¼ÒѾ­Íê³ÉÁË£¬Óû§µ÷ÓÃconnect()º¯Êý£¬Æäʵ¾ÍÊǵ÷ÓÃÁËtcp_v4_connect()º¯Êý£¬°´ÕÕÕâ·ùͼ£¬¶ÁÆðÔ´ÂëÀ´¾Í¼òµ¥Á˺ܶàÁË¡£

¡¡¡¡Áù Socket²ã

¡¡¡¡ÉÏÒ»½Ú°Ñsocket²ã´ó¶àÊýÒªÌÖÂ۵Ķ«Î÷¶¼Ì¸ÂÛÁË£¬ÏÖÔÚÖ»½²½²socket ²ãºÍÓû§µÄÏνӡ£

¡¡¡¡ÏµÍ³µ÷ÓÃsocket(),bind(),connect(),accept,send(),release()µÈÊÇÔÚLinux/net/socket.cÀïÃæµÄʵÏÖµÄ,ϵͳµ÷ÓÃʵÏֵĺ¯ÊýÊÇÏàÓ¦µÄº¯ÊýÃû¼ÓÉÏsys_µÄǰ׺¡£

¡¡¡¡ÏÖÔÚ¿´¿´µ±Óû§µ÷ÓÃsocket()Õâ¸öº¯Êý£¬µ½µ×ÏÂÃæ·¢ÉúÁËʲô¡£

¡¡¡¡Socket(AF_INET,SOCK_STREAM,0)µ÷ÓÃÁËsys_socket(),sys_socket()½Ó×ŵ÷ÓÃsocket_creat(),socket_creat()¾ÍÒª¸ù¾ÝÓû§ÌṩµÄЭÒé×å²ÎÊýÔÚnet_families[]ÀïѰÕÒºÏÊʵÄЭÒé×壬Èç¹ûЭÒé×åûÓб»°²×°¾ÍÒªÇëÇó°²×°¸ÃЭÒé×åµÄÄ£¿é£¬È»ºó¾Íµ÷ÓøÃЭÒé×åµÄcreate()º¯ÊýµÄ´¦Àí¾ä±ú¡£¸ù¾Ý²ÎÊýAF_INET£¬inet_creat()¾Í±»µ÷ÓÃÁË£¬ÔÚinet_creat()¸ù¾Ý·þÎñÀàÐÍÔÚinetsw[SOCK_MAX]

¡¡¡¡Ñ¡ÔñºÏÊʵÄЭÒ飬²¢°ÑЭÒéµÄ²Ù×÷¼¯¸³¸øsocket¾ÍÊÇÁË£¬¸ù¾ÝSOCK_STREAM£¬TCPЭÒ鱻ѡÖУ¬
¡¡¡¡inet_creat(){
¡¡¡¡answer=inetsw [Óû§ÒªÇó·þÎñ·þÎñ] £»
¡¡¡¡sock->ops = answer->ops;
¡¡¡¡sk->prot = answer->prot
¡¡¡¡}

¡¡¡¡µ½´ËΪֹ£¬ÉÏ϶¼´òͨÁË£¬¸ÃÊÇ´ó¼Ò¶¼Ô´ÂëµÄʱºòÁË¡£

    
        
    

 

 

 

 

 

²©¿ÍÍÆ¼öÎÄÕÂ
Ç×£¬Äú»¹Ã»ÓеǼ,Çë[µÇ¼]»ò[×¢²á]ºóÔÙ½øÐÐÆÀÂÛ