報文接收方式【總結】

報文接收步驟:

一、舊的接收過程

1、當網卡中斷產生後,內核的中斷處理部分會根據網卡驅動註冊的中斷號找到相應網卡驅動中的中斷處理函數。
2、中斷處理函數首先禁用網卡的接收報文中斷。
3、接着負責在內存中申請一個skb,把網卡硬件緩存中的報文拷貝到skb中。
初始化skb的一些字段,根據報文內容給skb->protocol字段賦值,例如ip報文會賦爲0x0800。
4、接着調用netif_rx()把skb放入本地CPU的接收隊列softnet_data->input_pkt_queue。
如果本地CPU的接收隊列softnet_data->input_pkt_queue爲空,會把特殊的napi backlog(初始化:dev.c/net_dev_init())掛到softnet_data->poll_list上。
5、接着使能網卡收包中斷。中斷處理函數退出。在中斷處理函數退出時會調度報文接收軟中斷進行處理CPU上的接收隊列softnet_data->input_pkt_queue中的報文。
6、在收包軟中斷中會找到本地CPU的softnet_data的poll_list鏈表,調用特殊napi backlog的輪詢函數process_backlog()來處理報文。

7、輪詢函數process_backlog()循環從softnet_data的輸入隊列input_pkt_queue取報文並將其送到協議棧相關協議模塊進行處理(netif_receive_skb(skb)),直到隊列中沒有報文了,或處理的報文數大於了允許的上限值了,或輪詢函數執行時間大於一個jiffies了。

從網卡硬件緩存中把報文拷貝到內存放在硬件中斷處理中做,把協議棧處理報文的工作放在軟中斷做,這樣提高了對硬件中斷的響應速度

二、NAPI方式接收

1、當網卡中斷產生時,找到網卡驅動中中斷處理函數。
2、中斷處理函數禁用網卡接收報文中斷。
3、把網卡對應的napi掛到本地CPU的softnet_data的poll_list鏈表上。表示網卡上有報文要處理。
4、接着調度報文接收的軟中斷來處理該CPU上掛着的napi。
5、在收包軟中斷中會找到本地CPU的softnet_data的poll_list鏈表,調用相應網卡驅動的輪詢函數來處理報文。
6、網卡驅動的輪詢函數會讀取報文,初始化skb,調用netif_receive_skb(skb)把skb直接送到協議棧進行處理。
每次輪詢處理的報文個數有一個限制,防止輪詢函數長時間佔用cpu。
如果讀取完全部報文,就使能網卡收報文的中斷。中斷返回。
如果處理的報文到了限制個數,但沒處理完全部的報文,就把網卡對應的napi再次掛到本地cpu的softnet_data的pool鏈表上,不用使能中斷。報文接收軟中斷接着處理。
一個報文會在輪詢函數中走完協議棧並被處理完成,不用再被緩存到相應的隊列中。
NAPI的另一個優點是設備處理更爲公平,因爲軟中斷順序執行每個需要處理的設備的輪詢函數,每個輪詢函數執行時間是有限制的,允許執行時間到了後就會執行下一個設備的輪詢函數。這樣就保證負載低的和負載高的設備被處理的機會一樣




參考:

1、報文的接收方式(linux網絡子系統學習 第二節 )

2、NAPI 方式的實現 (linux網絡子系統學習 第三節 )

3、收包軟中斷和netif_rx (linux網絡子系統學習 第四節 )

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章