網卡工作原理


網卡工作原理

Linux操作系統的功能可以概括為進程管理、內存管理、文件系統管理、設備管理、網絡等幾部分。所有的系統操作最終都可以映射到對物理設備的操作。除去對CPU、內存以及其他少數幾個物理實體的操作之外,系統對其他設備的所有操作都通過專門的稱為驅動程序的代碼完成。系統中存在的每種外設在內核中都必須有對應的設備驅動程序對其進行處理。所以分析網卡的工作原理即是分析網卡的驅動程序。

網絡是獨立的一個模塊。為了屏蔽網絡環境中物理網絡設備的多樣性,Linux對所有的設備進行抽象並定義了一個統一的概念,稱之為接口。所有對網絡硬件的訪問都是通過接口進行的,接口提供了一個對所有類型的硬件一致化的操作集合來處理基本數據發送和接收。一個網絡接口被看作是一個發送和接收數據包的實體。對於每個網絡接口,都用一個net_device的數據結構來表示。net_device中有很多提供系統訪問和協議層調用的設備方法,包括提供設備初始化和往系統注冊用的init函數,打開和關閉網絡設備的open和stop函數,處理數據包發送的函數hard_start_xmit,以及中斷處理函數。

所有被發送和接收的包都用數據結構sk_buff表示。要發送數據時,網絡系統將分局系統路由表選擇相應的網絡接口進行數據傳輸;當接收數據包時,通過驅動程序登記的中斷服務程序進行數據的接口處理。

Linux網絡驅動程序崇尚倒下分為四層:協議接口層、網絡設備接口層、設備驅動功能層、網絡設備和網絡媒介層。如下圖所示:

 

 

網卡初始化

網絡設備初始化主要工作時檢測設備的存在、初始化描述設備的net_device結構及在系統中登記該設備。在系統初始化完成以后,系統檢測到的網絡設備將保存在鏈表dev_base中,其中每個鏈表單元net_device對應一個存在的物理網絡設備。

初始化過程首先檢測網絡物理設備是否存在,這是通過檢測物理設備的硬件特征來完成;然后對設備進行資源配置,這些完成之后就要構造設備的net_device數據結構,用檢測到值對net_device中的變量初始化;最后Linux內核中注冊該設備並申請內存空間。

 

網卡的打開與關閉

為了使用網絡設備,需要打開網卡,打開和關閉的一個接口是由shell命令ifconfig調用的,而ifconfig則要調用一個通用的設備打開函數dev_open(net/core/dev.c),相應的還有一個dev_close函數,這兩個函數提供獨立於設備的操作接口的打開和關閉功能。一般打開函數執行的操作包括注冊中斷函數,分配並初始化網卡所需要的接收與發送緩沖區,啟動硬件檢查網絡連接線狀態等。

 

數據包的發送與接收

數據包的發送和接收是實現Linux網絡驅動程序中兩個最關鍵的過程。

當物理網絡設備接收到數據是,系統通過兩種途徑解決這個問題。一種方法是輪詢方式,另一種方式是中斷法師。

在輪詢方式中,系統每隔一定的時間間隔就去檢查一次物理設備,若設備有數據到達,就調用讀取數據的程序。Linux中通過定時器實現,但是此法有一個明顯的缺點:不管設備是否有數據,系統總是要固定的消耗CPU資源去查看設備,並且可能對一些緊急數據處理予以延遲。從資源的利用率以及工作的效率上看都不是最優的。

中斷方式利用硬件體系結構的中斷機制實現設備和系統的應答對話,即當物理設備需要CPU處理數據時,就向CPU發送一個終端信號,系統則在收到信號后調用相應的中斷服務程序響應對設備中斷的處理。因此,基本在所有的網絡設備驅動程序中都是用中斷方式的。

每一個網卡上都有一塊FIFO存儲器,對於NIC(Network Interface Controller),FIFO存儲器是用來通過系統總線傳送數據到系統存儲器之前,緩存從LAN上接收到的數據。對與快速以太網還有一個直接內存存取(DMA:Directly Memory Access)控制器,用於提供對系統存儲器的可靠訪問。

驅動為網卡分配一個環形緩沖區,在一段連續的物理內存中實現。

1、  數據接收

(1)       接收來自MAC的數據包,先暫存於片內FIFO接收隊列;

(2)       當接收器達到早期接收上線時就移至環形緩沖區;

(3)       待整個數據包全部從FIFO移至緩存后,將接收狀態寄存器和包長度寫入接收的數據包頭部,並更新CBA(Current Buffer Address)寄存器的值;

(4)       CMD(Command)寄存器中的BufferEmpty位和ISR(中斷狀態寄存器)寄存器的ROK位置1,並發出ROK的中斷;

(5)       ISR中斷調用完成后,清除ISR(ROK)並更新CAPR(Current Address of Packet Read,指向接收緩存的已讀取包的地址),完成本次接收。

2、  數據發送

(1)       將待傳送的數據寫入主存中一段連續的緩存空間,由OS配合驅動程序完成;

(2)       找到一個可用的描述器,並寫入內容,包括該數據包的開始物理地址和傳輸狀態字(包的大小、可傳送下限、OWN位);

(3)       OWN位有效,將數據從緩存移至片內FIFO隊列;

(4)       當FIFO隊列中的數據達到早期傳送下限,NIC的傳送單元就會啟動,將數據順序輸出至線路;

(5)       當整個數據包都已經傳至FIFO,OWN位置1;

(6)       當整個數據包都已經傳至線路上, TOK寄存器置1;

(7)       當TOK(IMR)和TOK(ISR)多置1,就發出TOK中斷;

(8)       TOK中斷調用完成以后,清除TSD狀態字,完成本次傳送。

 

可以看出,網卡需要發送/接收數據,都必須以中斷的方式告訴系統,系統處理中斷后做出相應操作。

網卡存在一定大小的FIFO存儲器,同時還有緩沖區,緩沖區是由系統以及驅動共同分配一段連續的物理內存,所有的發送/接收的數據,都必須通過FIFO已經緩沖區,只有一包數據都發送成功后,才能繼續發送下一包數據。系統維護緩沖區,只有當緩沖區有空間時才會接受上層來的數據,而網卡處理數據的速率遠高於接收數據的最大速率,因此在網卡上不會存在堵塞情況。

對編程而言,在應用層調用傳輸層函數send/sendto,使用套接字傳送數據,屏蔽了底層的所有實現。此時,send/sendto函數是沒有阻塞的,只要調用,必然有返回值,成功返回發送數據的長度,失敗則返回負值(失敗的主要原因是網絡連接的問題),因此可能存在數據丟失的現象,需要寫程序的時候保證數據的傳輸成功。但是只有send/sendto函數返回后,程序才會執行下一次發送,因此編程時沒必要考慮數據會在傳輸層上出現阻塞。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM