標籤:linux核心 資料結構 網路
承接上一篇:sk_buff整理筆記(一、資料結構)這一篇要講的是核心為sk_buff結構提供的一些操作函數。
第一、首先要講的是sk_buff中的四大指標:
四大指標分別是:head、data、tail、end;這四個指標都是指向了資料區的,資料區中存放的是協議頭和資料。head和end指標是每個資料包一樣的,也是有這兩個指標來確定資料區的大小的。最開始的時候head、data、tail三個指標都是指向一起的,當有協議資料加進來時才更改。
再來說下包的形成,首先是應用程式層的資料,然後到四層加上四層的TCP協議頭(假設為TCP包),然後發往三層;在三層時把四層發來的資料都當作是負載,然後再往負載前加上一個三層IP協議頭,發往二層;最後二層加上個幀頭就可以發送了。所以在包形成時,這幾個指標起到了非常關鍵的作用。下面來看下四個指標的指向地址大小,這也有利於對下面要講到一些操作函數的理解。
最後一句的意思是:當資料包在二層(即data指標指向二層協議頭)時,擷取到三層協議頭指標的一種方法。當然也可以直接用內建的擷取三層協議頭指標的函數(其實函數裡面也是用上面這句代碼實現的),這裡只是為了顯示data增加時,是往下移動的。方便後面的幾個函數理解。
第二、幾個操作sk_buff指標的函數:
首先來說下三個空間,方便下面介紹函數時理解。第一個是:headroom,就是skb->head和skb->data之間的空間;第二個是:data,就是skb->data和skb->tail之間的空間;第三個是:tailroom,就是skb->tail和skb->end之間的空間。如:
接下來說下四個操作sk_buff結構中指標的函數:(a)skb_put(), (b)skb_push(), (c)skb_pull(), and (d)skb_reserve();這四個函數在資料包在各層之間傳輸時,起到了至關
重要。
(a)skb_put():向後擴大資料區空間,headroom空間不變,tailroom空間減少,skb->data指標不變,skb->tail指標下移;
(b)skb_push():向前擴大資料區空間,headroom空間減少,tailroom空間不變,skb->tail指標不變,skb->data指標上移;
(c)skb_pull():縮小資料區空間,headroom空間增大,tailroom空間不變,skb->data指標下移,skb->tail指標不變;
(d)skb_reserve():資料區不變,headroom空間增大,tailroom空間減少,skb->data和skb->tail同時下移;
大家也可以照著源碼來分析,還有個當大家看源碼時,會發現好多函數都有個同名的,比如:skb_push()函數,就有兩個:static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len);和unsigned char *skb_push(struct sk_buff *skb, unsigned int len);第一個函數是具體內容的實現(關鍵函數),第二個函數只是在第一個函數的基礎上進行一些合法性檢查。
第三、其他簡單的操作函數:
擷取/設定協議頭指標等一系列函數,如:擷取IP頭指標,unsigned char *skb_network_header(const struct sk_buff *skb);還有其他些函數(skb記憶體申請、skb複製和複製、skb隊列操作)將到後面做詳細分析。