1. 程式人生 > >Linux 核心網路協議棧 -sk_buff結構體

Linux 核心網路協議棧 -sk_buff結構體

sk_buff結構體是linux網路程式碼中最重要的資料結構,是整個網路傳輸載體。所以sk_buff結構體裡面有很多關於其他功能的成員欄位,比如:防火牆,子路由系統,多播等。這些欄位並不是一定有的,只有在滿足特點條件才有的。

 sk_buff結構體是雙鏈表結構,sk_buff結構體關聯多個其他結構體:

第一是資料區:由sk_buff中head和end指向的資料塊,用來儲存sk_buff結構的資料也即是儲存資料包的內容和各層協議頭。

第二是分片結構:用來表示IP分片的一個結構體,實則上是和sk_buff結構的資料區相連的,即是end指標的下一個位元組開始就是分片結構。也正是此原因,所以分片結構和sk_buff資料區記憶體分配及銷燬時都是一起的。

第三是分片結構指向的資料區,即是IP分片內容。

資料包在各層間傳輸時,data指標的變化:sk_buff在各層間傳輸時,只改變指標和新增協議頭,不拷貝也不刪除協議頭。

 假設從收包開始:

       (1)開始進入第二層時,這時data指標指向幀頭。mac = data,然後操作mac指標已經資料包。當二層操作完後把包往三層傳送時,會呼叫一個函式(具體什麼函式後面會詳細講)讓data指標指向三層的IP頭;

       (2)當包進入第三層時,這時data指標已經指向了IP頭,讓nh = data,然後操作nh指標已經資料包,當三層操作完後把包往四層傳送時,同樣呼叫一個函式把data指向四層的TCP頭;同理,四層也是一樣處理的,只移動指標,不刪除協議頭。發包時就相反了,只是變成了為每一層新增協議頭了。下面是書上的圖,供參考。

 sk_buff_head結構體和sk_buff結構體關係:

sk_buff結構體資料區:

  sk_buff結構體只是網路資料包中的一些配置,真正包含傳輸內容和傳輸協議的都是在sk_buff結構體中幾個指標所指向的資料區中。這裡先簡稱資料區,資料區的大小是:(skb->end  - skb->head);對於每個資料包來說這個大小都是固定的,而且在傳輸過程中skb->end和skb->head所指向的地址都是不變的。這塊資料區是用來存放應用層發下來的資料和各層的協議資訊。但在計算資料長度或者操作協議資訊時,一般都要和實際的資料存放指標為準。實際資料指標為data和tail,data指向實際資料開始的地方,tail指向實際資料結束的地方。         下面來看下sk_buff結構體中的指標和資料區關係:

 (1)sk_buff結構資料區剛被申請好,此時head指標、data指標、tail指標都是指向同一個地方。記住前面講過的:head指標和end指標指向的位置一直都不變,而對於資料的變化和協議資訊的新增都是通過data指標和tail指標的改變來表現的。         (2)開始準備儲存應用層下發過來的資料,通過呼叫函式skb_reserve()來使data指標和tail指標同時向下移動,空出一部分空間來為後期新增協議資訊。         (3)開始儲存資料了,通過呼叫函式skb_put()來使tail指標向下移動空出空間來新增資料,此時skb->data和skb->tail之間存放的都是資料資訊,無協議資訊。         (4)這時就開始呼叫函式skb_push()來使data指標向上移動,空出空間來新增各層協議資訊。直到最後到達二層,新增完幀頭然後就開始發包了。

另外一篇文章介紹sk_buff結構體講解的特別詳細

IP資料包協議的講解: