|
¡¡¡¡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 ¡¡¡¡}
¡¡¡¡µ½´ËΪֹ£¬ÉÏ϶¼´òͨÁË£¬¸ÃÊÇ´ó¼Ò¶¼Ô´ÂëµÄʱºòÁË¡£
|