歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux綜合 >> Linux內核 >> Linux內核的netpoll框架與netconsole

Linux內核的netpoll框架與netconsole

日期:2017/2/28 14:01:33   编辑:Linux內核

雖然和網絡相關,但是它卻不是網絡協議棧的一部分,這就是netpoll。

它只是一個出入口的處理框架。所謂的網絡,它的終端節點就是主機,數據從主機的網卡發出,經過一個出口處理過程,網卡接收到一個數據包,經過一個入口處理過程,這一出一入的過程處理分為兩種方式:

1.中斷的方式

出口處理過程-數據排入發送隊列,讀取特定寄存器值,待網卡狀態適合發送式,發送,等待發送後的中斷通知,繼續。

入口處理過程-數據被網卡收到,網卡中斷CPU,CPU進而處理數據接收的過程。

網絡協議棧下接的就是這種中斷的出入口處理方式。

2.poll的方式

出口處理過程-數據排入發送隊列,讀取特定寄存器值,待網卡狀態適合發送式,發送,不等待發送後的中斷通知,繼續讀取寄存器以及根據隊列情況權衡是否適合發送。

入口處理過程-數據被網卡收到,等待poll邏輯在適當的時候去主動poll網卡,若有數據,則將其從特定的網卡緩存讀出。

Linux netpoll就是利用的這種方式。這種方式完全不依賴中斷。

事實總是比說起來更麻煩。

要講清楚這個有點混亂的主題,不得不引入第三種出入口處理方式,那就是中斷和poll結合的方式,這就是NAPI方式。我把三種方式的圖示先給出:

a.中斷方式

b.poll方式

c.NAPI方式

理解了這個,剩下的就都理解了。至於為何會有NAPI,在本文中只能簡單說一句:在高速高帶寬網絡中,數據包持續到來,每一個包中斷一次CPU的話,CPU有點吃不消,反而耽誤了CPU處理這些數據包,如果之前的數據包還沒有處理完,最好的辦法就是將數據包排入一個隊列,然後沉默,不要打擾CPU,等CPU空下來的時候,自己去poll這些隊列裡面的數據包,這就是NAPI。

純中斷的方式我們都很熟悉,也是最直接的方式。然而為何要有純poll的方式呢?使用純poll的場合在中斷完全不起作用的情況下。舉一個例子,系統panic之後。此時中斷控制器將可能被disable掉,無論如何,此時的機器已經和外界失聯了,然而如果此時必須需要一個方式對外界通告自己的死因的話,這種netpoll的方式就派上用場了,因為它是純手工的,完全不依賴系統的中斷機制。另外一種場合比panic好一些,那就是協議棧故障,如果使用中斷或者NAPI的方式,由於它上接的就是協議棧,netif_receive_skb中又沒有什麼HOOK點,此時使用netpoll可以改變數據包的處理路徑,通過一個agent可以實現遠程debug。

不要把中斷想象的太神秘。它無非也就是一個通知機制,告訴CPU,現在請查詢我的狀態,該干啥就干啥。事實上,當CPU收到網卡中斷的時候,它也不知道該干啥,它只會調用中斷處理函數,其內部會去讀取一寫寄存器的狀態,然後才能知道現在該干什麼,比如可以發送數據包,比如收到一個數據包等。既然如此,即使在關中斷的情形下,如果不依靠中斷,CPU擇機主動調用一下網卡的中斷處理函數,讀取一寫寄存器的狀態,是不是也能知道該干什麼呢?答案當然是肯定的了!這就是netpoll的邏輯,它使用兩步完成任務:

1.主動調用網卡的中斷處理函數,獲取當前該發送數據包還是接收到一個數據包;

2.直接hard_xmit數據包或者使用NAPI的接口去poll網卡的數據。

Linux netpoll的總體圖示如下:

這個圖示中附帶了netconsole的原理,沒想到他是如此的簡單。我記得我曾經寫過一個模塊,將panic後的信息發到遠端,這個是受到了一個xtables-addons模塊的啟發,起初失敗了,但是最後我仔細debug了內核代碼後,成功了。在成功的過程中,發現了很多以前不知道的東西。但是現在看看netconsole吧,它什麼復雜的東西都不需要,只需要兩步:

1.注冊一個console,此後內核buffer的信息就會發到這個console;

2.該console下接netpoll的netpoll_send_skb,此後由netpoll邏輯來處理。

即便在panic後,中斷已經被關了,甚至中斷控制器都關閉的情況下,只要網卡沒有進水,數據依然可以收發,它完全不依賴中斷和協議棧。這簡直太棒了!關於netconsole,我寫多少都不如內核的Document來的好:$kernel/Documentation/networking/netconsole.txt.

netpoll是Linux內核中的一種在協議棧不可用或者中斷機制異常的情況下與外界通訊的手段,當然它也是一種繞開協議棧的方法。這個位置足夠底層,寫出來的東西也肯定比基於Netfilter的更好玩。Netfilter是在協議棧的特殊點捕獲數據包的,而netpoll卻可以在網卡之上直接捕獲數據包,它們甚至連協議棧的最底端都到不了。以後,如果想在內核態直接發包,再也不用PACKET套接字從用戶態開始了,構造一個數據包,直接通過netpoll接口發出。問題是,它采用手工觸發中斷處理函數的方式,效率如何待測試。因此這種機制最好還是限制於調試和少量內核審計信息的發送吧。用它做VPN,我覺得懸...

Copyright © Linux教程網 All Rights Reserved