• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • Linux內核2.4.x的網絡接口源碼的結構(1)

    發表于:2007-05-26來源:作者:點擊數: 標簽:
    Linux 內核2.4.x的 網絡 接口源碼的結構 一.前言 Linux的源碼里,網絡接口的實現部份是非常值得一讀的,通過讀源碼,不僅對網絡協議有更深的了解,也有助于在網絡編程的時候,對應用函數有更精確的了解和把握。 本文把重點放在網絡接口程序的總體結構上,希
    Linux內核2.4.x的網絡接口源碼的結構
    一.前言
      Linux的源碼里,網絡接口的實現部份是非常值得一讀的,通過讀源碼,不僅對網絡協議有更深的了解,也有助于在網絡編程的時候,對應用函數有更精確的了解和把握。
      本文把重點放在網絡接口程序的總體結構上,希望能作為讀源碼時一些指導性的文字。
      本文以Linux2.4.16內核作為講解的對象,內核源碼可以在[http://www.kernel.org/]上下載。我讀源碼時參考的是[lxr.linux.no]這個交差參考的網站,我個人認為是一個很好的工具,如果有條件最好上這個網站。

    二.網絡接口程序的結構
      Linux的網絡接口分為四部份:網絡設備接口部份,網絡接口核心部份,網絡協議族部份,以及網絡接口socket層。
      網絡設備接口部份主要負責從物理介質接收和發送數據。實現的文件在linu/driver.net目錄下面。
      網絡接口核心部份是整個網絡接口的關鍵部位,它為網絡協議提供統一的發送接口,屏蔽各種各樣的物理介質,同時又負責把來自下層的包向合適的協議配送。它是網絡接口的中樞部份。它的主要實現文件在linux/net/core目錄下,其中linux/net/core/dev.c為主要管理文件。
      網絡協議族部份是各種具體協議實現的部份。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行)函數實現的,驅動程序通過這個函數把接到的數據交給上層,請注意所有的網卡驅動程序都需要調用這個函數的,這是網絡接口核心層和網絡接口設備聯系的橋梁。
     由上往下的關系就復雜點。網絡接口核心層需要知道有多少網絡設備可以用,每個設備的函數的入口地址等都要知道。網絡接口核心層會大聲喊,“嘿,有多少設備可以幫我發送數據包?能發送的,請給我排成一隊!”。這一隊就由dev_base開始,指針structnet_device *dev_base(Linux/include/linux/netdevice.h 436行)就是保存了網絡接口核心層所知道的所有設備。對于網絡接口核心層來說,所有的設備都是一個net_device結構,它在 include/linux/netdevice.h,line 233里被定義,這是從網絡接口核心層的角度看到的一個抽象的設備,我們來看看網絡接口核心層的角度看到的網絡設備具有的功能:
      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()
      aclearcase/" target="_blank" >ccept_fastpath()
      ………
      }
      如果網絡接口核心層需要由下層發送數據的時候,在dev_base找到設備以后,就直接調dev->hard_start_xmit()的這個函數來讓下層發數據包。
      驅動程序要讓網絡接口核心層知道自己的存在,當然要加入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這個來發送數據,上面的語句就把驅動程序實際的發送函數告訴了上層。

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>