深入理解Linux網路技術內幕-關鍵資料結構(一)

來源:互聯網
上載者:User

 Linux網路子系統中存在一些很重要的資料結構,貫穿整個子系統,主要有以下兩個:

    struct sk_buff:資料封包結構。所有的網路分層都會使用這個結構來儲存其前序、有關使用者資料,以及協調其他工作的其他內部資訊。    struct net_device:在Linux核心中,每種網路裝置都用這個資料結構表示,包括軟硬體的配置資訊。
一、通訊端緩衝區:sk_buff結構    這可能是Linux網路代碼中最重要的資料結構,表示資料報文。這個結構定義在<include/linux/skbuff.h>標頭檔中,由巨大的變數堆組成,試圖滿足所有人的所有需求。    這個結構的欄位大致分為以下幾個類型:    網路層次    通用欄位    功能專用    管理函數    在網路系統的不同網路層都會使用這個結構,而當這個結構從一個分層傳到另一個分層時,其不同的欄位會隨之發生改變。如L4層在傳遞給L3之前會附加一個前序,通用L3到L2之前也會加上自己的前序。附加前序比把資料從一個分層拷貝到另一個分層更有效率。    由於要在一個緩衝區開端新增空間(也就是修改指向緩衝區頭部的指標),核心提供了skb_reserve函數來執行這個操作。所以,當緩衝區往下傳遞給每個網路層時,每層的協議首先要做的就是調用skb_reserve函數為該協議的前序預留空間。    而在緩衝區向上傳遞給上層網路時,並沒有本層前序從緩衝區中刪除,二是將直線有效資料的指標向前移到上層的前序位置。    由於網路代碼提供了大量的選項性功能,不一定總是需要,如防火牆、多播、串連跟蹤等,這些功能都會在sk_buff結構豬附加上欄位。因此,sk_buff結構中有許多由C預先處理#ifdef指令附加的欄位。一般而言,任何引起核心資料結構改變的選項,都不適合編譯成一個模組進行動態載入。      sk_buff中的某些欄位是為了組織資料結構本身: 


  1. struct sk_buff {
  2.     /* These two members must be
    first. */
  3.     struct sk_buff        *next;
  4.     struct sk_buff        *prev;

    同時為了迅速找到整個表的頭,在表的開端額外增加一個sk_buff_head結構作為一種啞元元素,sk_buff_head結構是:


  1. struct sk_buff_head {
  2.     /* These two members must be first. */
  3.     struct sk_buff    *next;
  4.     struct sk_buff    *prev;

  5.     __u32        qlen;
  6.     spinlock_t    lock;
  7. };

    qlen是表中元素的數目,lock是用於防止對錶的並發訪問。    sk_buff和sk_buff_head結構的前兩個元素是相同的,所以同樣的函數也可用於操作sk_buff和sk_buff_head二者。   sk_buff結構中的list欄位指向表頭:sk_buff中的其他欄位:
struct sock *sk:指向擁有此緩衝區的通訊端的sock資料結構。當資料在本地產生或者正在由本地進程接收時,就需要這個指標,因為該資料以及通訊端相關的資訊會由L4層(TCP或UDP)以及使用者應用程式使用。當緩衝區只是被轉寄時,該指標就是NULL。
unsigned int len:這是指緩衝區豬資料區塊的大小。這個長度包括主要緩衝區(由head所指)的資料以及一些片段(fragment)的資料。當緩衝區從一個網路層傳遞給下一個網路層時,其值會發生變化。因為在協議棧中往上移動時,前序會被丟棄。但是往下移動時,前序會被添加進來,len會將協議前序長度算在裡面。
unsigned int data_len:與len不同,data_len只計算片段中的資料大小
unsigned int mac_len:MAC前序的大小
atomic_t users:引用計數,或者使用這個sk_buff緩衝區的執行個體的數目。這個參數的的主要用途是避免這個結構仍在使用時,被另一個執行個體釋放掉。users有時直接使用atimic_inc和atomic_dec函數遞增和遞減,但在大多數時候,採用skb_get和kfree_skb進行處理。
unsigned int truesize:表示此緩衝區的總大小,包括sk_buff結構本身。當此緩衝區得到所分配的len個位元組的資料請求空間時,此欄位的初始化由alloc_skb函數設定為len+sizeof(sk_buff)。每當skb->len的值增加時,此欄位就會得到更新。
sk_buff_data_t tailsk_buff_data_t endunsigned char *headunsigned char *data這些欄位代表緩衝區的邊界以及其中的資料。當每一層為其工作而準備緩衝區時,可能會為了一個前序或更多的資料分配更多的空間。head和end指向已指派空間的開端和尾端,而data和tail指向實際資料的開端和尾端。因此,可以再head和data直接填充報文頭,在tail和end之間增加新的資料。其中tail和end根據系統是否使用NET_SKBUFF_DATA_USES_OFFSET來決定使用位移地址還是指標

  1. #ifdef NET_SKBUFF_DATA_USES_OFFSET
  2. typedef unsigned int sk_buff_data_t;
  3. #else
  4. typedef unsigned char *sk_buff_data_t;
  5. #endif

void (*destructor)(struct sk_buff *skb):此函數指標所指的函數在緩衝區被刪除時,完成某些工作。當此緩衝區不屬於一個通訊端時,destructor通常不會被初始化。但若屬於一個通訊端時,通常被設定為sock_rfree或sock_wfree。這兩個函數可用於更新通訊端隊列豬所持有的記憶體。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.