1. 程式人生 > >有關SKB連結串列管理和資料操作的幾個函式

有關SKB連結串列管理和資料操作的幾個函式

核心中,SKB是以雙向迴圈連結串列的形式儲存的,並且,為了使特定的skb被快速找到,在連結串列的頭部增加了一個新的資料結構sk_buff_head,該結構只是一個輔助節點,不含有資料。

在對SKB連結串列進行操作的時候,首先必須取得sk_buff_head結構中的自旋鎖,這樣才能安全的操作SKB連結串列。

下面以linux-2.6.20核心為例,對有關操作進行說明,以下涉及到的函式定義均在skbuff.c檔案中。

對連結串列的操作主要有以下幾個方面:

1.連結串列初始化,skb_queue_head_init()

2.新增skb到連結串列頭部,skb_queue_head()

3.新增skb

到連結串列尾部,skb_queue_tail()

4.從連結串列頭部取下一個skbskb_dequeue()

5.從連結串列尾部取下一個skbskb_dequeue_tail()

6.清空連結串列,skb_queue_purge()

7.遍歷skb連結串列,skb_queue_walk(這是一個巨集)

(從這幾個名字中看出,核心程式碼也不過如此嘛,起碼函式名字起的不是很好,含義模糊,哈哈)

對資料的操作主要有以下幾個方面:

新增資料

將使用者空間資料新增到skb尾部,skb_add_data()

刪除資料

刪除線性資料區的資料,  skb_trim()

刪除非線性資料區的資料,pskb_trim()

拆分資料

skb_spilt()函式是拆分資料的函式,該函式中有一個引數lenlen表示拆分後原來skb中剩餘的資料的長度,因此就有兩種情況:

假設原來的skb中線性資料區的長度為n.因此lenn之間的大小就存在三種關係,大於,小於,等於,相等的情況暫且放入到小於的情形中,一起考慮。因此剩餘兩種情況:

len<=nlen > n;

如果len<=n,比較容易,因為此時舊的skb中剩餘的資料區比原來的資料區要小(最大相等),也就是說僅僅是對線性資料區進行了拆分。

如果len > n,則表明舊的skb中剩餘的資料大於了原來的線性資料的長度,即把非線性資料區進行了拆分。

重新分配skb的線性資料區。

一個skb一旦分配完成,即呼叫skb_alloc()函式之後,該skb的大小就固定了,即指標headend之間的長度就是固定的了。有時候需要增加線性資料區的長度,該怎麼辦?答案:重新分配skb

核心中負責重新分配skb線性區的函式為pskb_expand_head().當然該函式不是隨便分配一個skb,而是在原來skb的基礎上,對headroom 空間和 tailroom 空間進行了擴充套件。分配完新的skb之後,原來的skb被釋放。

檢測SKB佇列是否為空 : skb_queue_empty()