Tcp的處理中使用了三個隊列,receive_queue,backlog_queue,pre_queue,在數據包到達tcp協議棧時,持有sk自旋鎖,
然後檢查當前使用有進程上下文操作sk的邏輯,通過sock_owned_by_user判斷,如果sk_lock.owned被賦值說明進程持有sk,
如果為0則可以在當前軟中斷上下文中,繼續數據報文的處理。
當sk_lock.owned賦值時,skb通過sk_add_backlog被放在了sk_backlog隊列的尾部,等待進程release_sock時處理,在
release_sock時,會將sk_backlog臨時保存(私有化,與sock脫離),然後逐一進行skb的處理。這個過程是調用sk_backlog_rcv
實現的,實際上是tcp_v4_do_rcv函數。這裏的函數使用是在進程上下文中(關了bh),每處理結束一個skb後,都會檢查是
否需要調度,如果需要調度,則打開bh,調度,等到重新執行時關閉bh,因此整個過程中可能會產生睡眠。
當sk_lock.owned沒有賦值時,說明當前沒有進程/用戶在操作sk,會首先調用tcp_prequeue嘗試將數據報文加入pre_queue,
如果無法加入pre_queue時,則走普通流程在軟中斷上下文中調用tcp_v4_do_rcv進行後續處理,後續動作與進程/用戶在
release_sock中執行的sk_backlog_rcv(tcp_v4_do_rcv)相同。
tcp_prequeue函數負責向pre_queue中添加skb,無法添加的原因只有兩個:
一是用戶為了降低延遲,全局關閉了pre_queue的功能(通過sysctl_tcp_low_latency開關)
二是當前沒有進程/用戶等待處理該sk上的報文,即tp->ucopy.task為0時,也不能使用pre_queue。
下面這篇文章對prequeue做出了評價,可以參考一下,http://www.oschina.net/question/234345_47740,其中對一些概念的澄清,摘錄如下
tcp中分為快速路徑(fast path)和慢速路徑(slow path),讓我想到了網絡設備的control path和data path(其實不挨著),
所謂fast path不是指pre_queue path,slow path也不是指處理backlog_queue和receive_queue的path。fast path需要一些附加條件,
其含義是復制到用戶空間或者按序進入receive_queue的處理路徑,slow path指的是亂序報文的處理以及其他不符合fast path的數據
包的處理方式。這些path與數據報文進入那個隊列沒有關系,一般是將fast path分為兩類:
直接復制進用戶空間的路徑是most-fast-path,沒有進程上下文導致按序的skb進入receive_queue的是more-fast-path。
由於處理亂序包或緩沖區用盡這些情況很麻煩,因此處理這些情況的path就是slow-path,具體是什麽path是根據tcp語義和數據包
特性來確定的,和具體協議棧的實現沒有關系。
- Jul 07 Tue 2015 17:47
linux中tcp的隊列
close
全站熱搜
留言列表