tcp/ip
是一種儲存
/**的協議,因此,在
stack
中必然存在資料報的佇列(
sk_buff queue
)。正是這些佇列,將
stack
的處理邏輯比較清晰的劃分成幾個部分。
資料報接收路徑上的佇列:
1、網路層佇列:
softnet_data[this_cpu]. input_pkt_queue 每個
cpu
有乙個這樣的佇列。此佇列將網絡卡驅動的處理邏輯與協議分析(網路層、傳輸層)的處理邏輯區分開來。
當網絡卡驅動處理資料的時候,工作在中斷上下文,它的處理結果就是將資料報盡快的送入此佇列。
而真正的網路層、傳輸層協議分析和處理邏輯是在
net_rx_action
軟中斷中完成的。
當net_rx_action
被cpu
排程後,從此佇列中接收資料報,進行網路層和傳輸層的協議分析和處理。
2、bsd socket
層佇列:
sock-> receive_queue 每個
struct socket
對應乙個這樣的佇列。此佇列將
net_rx_action
軟中斷與
socket
層的處理邏輯區分開來。
當net_rx_action
完成了網路層和傳輸層的處理後,需要將資料報送到對應的
struct socket
結構的此佇列中。
而應用層則通過
read
、recvfrom
等系統呼叫從此隊禮中取走資料。
資料報傳送路徑上的佇列:1、
bsd socket
層佇列:
sock->write_queue 當從
user space
呼叫write()
或sendto()
或sendmsg()
等系統呼叫傳送資料的時候,
tcp
和udp
的處理過程有所不同。
對於udp
來說,在這一層不需要通過佇列來緩衝資料。
sendto
或者sendmsg
將原始資料拆分成
sk_buff
結構,然後進行傳輸層、網路層處理,最後送到相應的
device
對應的輸出佇列。
但是tcp
是一種流協議,具有擁塞控制的功能,因此可能需要在這一層緩衝資料。這個佇列就是
struct socket
結構中的
write_queue。
為什麼說可能需要用到這個佇列了。因為write 或者sendmsg 在將原始資料拆分成sk_buff 結構後,就嘗試將這些資料報傳送出去並等待對端的ack。如果網路足夠流暢,那麼就不需要將資料緩衝在佇列中。如果網路比較繁忙,在設定時間內等不到ack,或者對端的tcp 視窗不允許接收資料,那麼就必須先緩衝到佇列中,留到合適的時機再發。(顯然會有乙個定時器來幹這個事情)。 2
、網路裝置的佇列:
dev->qdisc
每個網路裝置對應乙個此佇列(也可以沒有,例如
lo)。它將網路層與裝置驅動區分開來。
資料報在網路層處理完之後,可能會緩衝到此佇列中。
這裡也只是可能會緩衝,因為資料報被送到此佇列後,如果條件允許,立刻就被傳送出去。
此佇列是
linux
核心中實現
qos
的關鍵。不同的
qos
策略採用不同的方式對此佇列中的資料報進行處理,預設的方式是
fifo
。如果底層
driver
處理速度跟不上傳送資料報的速度,那麼當佇列滿了以後,後續的資料報就會被丟棄。
資料報在Linux中的流程
1.中斷處理函式中 網絡卡收到一幀 引發中斷 cpu呼叫相應的中斷處理函式 指向此網絡卡驅動中的相應的處理函式 把此packet讀到ram中 呼叫netif rx函式來打上timestamp,並把此skb放入到cpu設定的佇列中 標記軟中斷 cpu raise softirq 中斷完成。2 當軟中斷...
資料報在網路中的流轉
文分為兩部分 基礎概念介紹 和資料報在網路中流轉的過程 1.啥是集線器 從0開始,當一台機器a想與機器b發訊息,連一根實體線即可完成 假設這根線很牛逼,連上就能通資訊 兩台機器互動沒有問題,如果一台機器a想與b,c,d,e,f五颱機器通訊,他就需要扯五根線,如果六臺機器想互相通訊那就得扯十五條,十分...
資料報格式 USB資料報解析
由域構成的包有四種型別,分別是令牌包 資料報 握手包和特殊包,前面三種是重要的包,不同包的域結構不同,介紹如下 1 令牌包 分為輸入包 輸出包 設定包和幀起始包 注意這裡的輸入包是用於設定輸入命令的,輸出包是用來設定輸出命令的,而不是放資料的 其中輸入包 輸出包和設定包的格式都是一樣的 sync p...