sk buff的資料預留和對齊

2021-09-07 10:17:24 字數 1724 閱讀 4726

**:

資料預留和對齊主要由skb_reserve()、skb_put()、skb_push()以及skb_pull()這幾個函式來完成。

1.skb_reserve()

skb_reserve()在資料快取區頭部預留一定的空間,通常被用來在資料快取區中插入協議首部或者在某個邊界上對齊。它並沒有把資料移出或移入資料快取區,而只是簡單地更新了資料快取區的兩個指標-分別指向負載起始和結尾的data和tail指標,圖3-15 展示了呼叫skb_reserve()前後這兩個指標的變化。

請注意:skb_reserve()只能用於空的skb,通常會在分配skb之後就呼叫該函式,此時data和tail指標還一同指向資料區的起始位置,如圖3-15a所示。例如,某個乙太網裝置驅動的接收函式,在分配skb之後,向資料快取區填充資料之前,會有這樣的一條語句skb_reserve(skb, 2),這是因為乙太網頭長度為14b,再加上2b就正好16位元組邊界對齊,所以大多數乙太網裝置都會在資料報之前保留2b。

當skb在協議棧中向下傳遞時,每一層協議都把skb->data指標向上移動,然後複製本層首部,同時更新skb->len。這些操作都使用圖3-15 中所示的函式完成。 

skb_push()在資料快取區的前頭加入一塊資料,與skb_reserve()類似,也並沒有真正向資料快取區中新增資料,而只是移動資料快取區的頭指標data和尾指標tail。資料由其他函式複製到資料快取區中。

函式執行步驟如下:

1)當tcp傳送資料時,會根據一些條件,如tcp最大分段長度mss、是否支援聚合分散i/o等,分配乙個skb。

2)tcp需在資料快取區的頭部預留足夠的空間,用來填充各層首部。max_tcp_header是各層首部長度的總和,它考慮了最壞的情況:由於tcp層不知道將要用哪個介面傳送包,它為每一層預留了最大的首部長度,甚至還考慮了出現多個ip首部的可能性,因為在核心編譯支援ip over ip的情況下,會遇到多個ip首部。

3)把tcp負載複製到資料快取區。需要注意的是,圖3-16 只是乙個例子,tcp負載可能會被組織成其他形式,例如分片。 

4)tcp層新增tcp首部。

5)skb傳遞到ip層,ip層為資料報新增ip首部。

6)skb傳遞到鏈路層,鏈路層為資料報新增鏈路層首部。

3.skb_put()

skb_put()修改指向資料區末尾的指標tail,使之往下移len位元組,即使資料區向下擴大len位元組,並更新資料區長度len。呼叫skb_put()前後,skb結構變化如圖3-17所示。 

skb_pull()通過將data指標往下移動,在資料區首部忽略len位元組長度的資料,通常用於接收到資料報後在各層間由下往上傳遞時,上層忽略下層的首部。呼叫skb_pull()前後,skb結構變化如圖3-18所示。 

資料的對齊

linux沿用的對齊策略是2位元組資料型別 例如 short 的位址必須是2的倍數,而較大的資料型別 例如 int int float 和 double 的位址必須是4的倍數。注意,這個要求就意味著乙個short型別物件的位址的最低位必須等於0。類似地,任何 int 型別的物件或指標的位址的最低兩位...

關於資料對齊和儲存器讀寫

資料對齊是跟資料在記憶體中的位置相關的話題。如果乙個變數的記憶體位址正好是他長度的整數倍,那麼它就叫做自然對齊。舉例來說,乙個32位的整型資料,如果他在記憶體中的位址剛好可以被4整除,我們就說這個整型數是自然對齊的。在編譯過程中,可以通過編譯器來調整資料對齊。一般在預設情況下,對於標準資料型別來說,...

VB控制項的左對齊和上對齊Sub

vb控制項的左對齊和上對齊sub 這兩個通用過程 左對齊和上對齊 可以很方便的設定控制項的位置和大小,節省了很多 也不需要在設計階段就把每個控制項都設定好。在form load過程或者其他過程都可以呼叫。sub ctrleftalignment ctra as control,ctrb as con...