1. 程式人生 > >網路協議棧深入分析(二)--sk_buff的操作函式

網路協議棧深入分析(二)--sk_buff的操作函式

1、alloc_skb()函式

該函式的作用是在上層協議要傳送資料包的時候或網路裝置準備接收資料包的時候會呼叫alloc_skb()函式分配sk_buff結構體,需要釋放時呼叫kfree_skb()函式。

  1. staticinlinestruct sk_buff *alloc_skb(unsigned int size,  
  2.                     gfp_t priority)  
  3. {  
  4.     return __alloc_skb(size, priority, 0, NUMA_NO_NODE);  
  5. }  

這裡使用行內函數,非行內函數呼叫會進堆疊的切換,造成額外的開銷,而行內函數可以解決這一點,可以提高執行效率,只是增加了程式的空間開銷。

        函式呼叫需要時間和空間開銷,呼叫函式實際上將程式執行流程轉移到被調函式中,被調函式的程式碼執行完後,再返回到呼叫的地方。這種呼叫操作要求呼叫前保護好現場並記憶執行的地址,返回後恢復現場,並按原來儲存的地址繼續執行。對於較長的函式這種開銷可以忽略不計,但對於一些函式體程式碼很短,又被頻繁呼叫的函式,就不能忽視這種開銷。引入行內函數正是為了解決這個問題,提高程式的執行效率。

  1. /*  Allocate a new skbuff. We do this ourselves so we can fill in a few 
  2.  *  'private' fields and also do memory statistics to find all the
     
  3.  *  [BEEP] leaks. 
  4.  * 
  5.  */
  6. /** 
  7.  *  __alloc_skb -   allocate a network buffer 
  8.  *  @size: size to allocate 
  9.  *  @gfp_mask: allocation mask 
  10.  *  @fclone: allocate from fclone cache instead of head cache 
  11.  *      and allocate a cloned (child) skb 
  12.  *  @node: numa node to allocate memory on 
  13.  *
     
  14.  *  Allocate a new &sk_buff. The returned buffer has no headroom and a 
  15.  *  tail room of size bytes. The object has a reference count of one. 
  16.  *  The return is the buffer. On a failure the return is %NULL. 
  17.  * 
  18.  *  Buffers may only be allocated from interrupts using a @gfp_mask of 
  19.  *  %GFP_ATOMIC. 
  20.  */
  21. struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,  
  22.                 int fclone, int node)  
  23. {  
  24.     struct kmem_cache *cache;  
  25.     struct skb_shared_info *shinfo;  
  26.     struct sk_buff *skb;  
  27.     u8 *data;  
  28.     cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;  
  29.     /* Get the HEAD */
  30.     skb = kmem_cache_alloc_node(cache, gfp_mask & ~__GFP_DMA, node);//分配儲存空間
  31.     if (!skb)  
  32.         goto out;//分配失敗,返回NULL
  33.     prefetchw(skb);  
  34.     /* We do our best to align skb_shared_info on a separate cache 
  35.      * line. It usually works because kmalloc(X > SMP_CACHE_BYTES) gives 
  36.      * aligned memory blocks, unless SLUB/SLAB debug is enabled. 
  37.      * Both skb->head and skb_shared_info are cache line aligned. 
  38.      */
  39.     size = SKB_DATA_ALIGN(size);//調整skb大小
  40.     size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));  
  41.     data = kmalloc_node_track_caller(size, gfp_mask, node);//分配資料區
  42.     if (!data)  
  43.         goto nodata;  
  44.     /* kmalloc(size) might give us more room than requested. 
  45.      * Put skb_shared_info exactly at the end of allocated zone, 
  46.      * to allow max possible filling before reallocation. 
  47.      */
  48.     size = SKB_WITH_OVERHEAD(ksize(data));  
  49.     prefetchw(data + size);  
  50.     /* 
  51.      * Only clear those fields we need to clear, not those that we will 
  52.      * actually initialise below. Hence, don't put any more fields after 
  53.      * the tail pointer in struct sk_buff! 
  54.      */
  55.      //sk_buff結構體中最後6個屬性不能改變位置,只能在最後
  56.     memset(skb, 0, offsetof(struct sk_buff, tail));//將sk_buff結構體中tail屬性之前的屬性清零
  57.     /* Account for allocated memory : skb + skb->head */
  58.     skb->truesize = SKB_TRUESIZE(size);//計算緩衝區的尺寸
  59.     atomic_set(&skb->users, 1);  
  60.     //初始化資料區的指標
  61.     skb->head = data;  
  62.     skb->data = data;  
  63.     skb_reset_tail_pointer(skb);  
  64.     skb->end = skb->tail + size;  
  65. #ifdef NET_SKBUFF_DATA_USES_OFFSET
  66.     skb->mac_header = ~0U;  
  67. #endif
  68.     /* make sure we initialize shinfo sequentially */
  69.     //初始化skb_shared_info
  70.     shinfo = skb_shinfo(skb);  
  71.     memset(shinfo, 0, offsetof(struct skb_shared_info, dataref));  
  72.     atomic_set(&shinfo->dataref, 1);  
  73.     kmemcheck_annotate_variable(shinfo->destructor_arg);  
  74.     if (fclone) {  
  75.         struct sk_buff *child = skb + 1;  
  76.         atomic_t *fclone_ref = (atomic_t *) (child + 1);  
  77.         kmemcheck_annotate_bitfield(child, flags1);  
  78.         kmemcheck_annotate_bitfield(child, flags2);  
  79.         skb->fclone = SKB_FCLONE_ORIG;  
  80.         atomic_set(fclone_ref, 1);  
  81.         child->fclone = SKB_FCLONE_UNAVAILABLE;  
  82.     }  
  83. out:  
  84.     return skb;  
  85. nodata:  
  86.     kmem_cache_free(cache, skb);  
  87.     skb = NULL;  
  88.     goto out;  
  89. }  
函式執行完成後,sk_buff的資料指標的形式如下:



2、kfree_skb()函式

該函式就是釋放不被使用的sk_buff結構

  1. /** 
  2.  *  kfree_skb - free an sk_buff 
  3.  *  @skb: buffer to free 
  4.  * 
  5.  *  Drop a reference to the buffer and free it if the usage count has 
  6.  *  hit zero. 
  7.  */
  8. void kfree_skb(struct sk_buff *skb)  
  9. {  
  10.     if (unlikely(!skb))  
  11.         return;  
  12.     if (likely(atomic_read(&skb->users) == 1))  
  13.         smp_rmb();  
  14.     elseif (likely(!atomic_dec_and_test(&skb->users)))  
  15.         return;  
  16.     trace_kfree_skb(skb, __builtin_return_address(0));  
  17.     __kfree_skb(skb);  
  18. }  
再呼叫__kfree_skb函式
  1. void __kfree_skb(struct sk_buff *skb)  
  2. {  
  3.     skb_release_all(skb);//釋放除了skb本身佔用的記憶體
  4.     kfree_skbmem(skb);  
  5. 相關推薦

    網路協議深入分析()--sk_buff操作函式

    1、alloc_skb()函式 該函式的作用是在上層協議要傳送資料包的時候或網路裝置準備接收資料包的時候會呼叫alloc_skb()函式分配sk_buff結構體,需要釋放時呼叫kfree_skb()函式。 staticinlinestruc

    Linux 網路協議開發(一)—— 網路協議核心分析

    1.1 傳送端 1.1.1 應用層 (1) Socket 應用層的各種網路應用程式基本上都是通過 Linux Socket 程式設計介面來和核心空間的網路協議棧通訊的。Linux Socket 是從 BSD Socket 發展而來的,它是 Linux 作業系統的重要組成部分之一,它是網路應用程式

    Linux核心網路協議程式碼分析

    ^ |       sys_read                fs/read_write.c |       sock_read               net/socket.c |       sock_recvmsg            net/socket.c |       inet_re

    Linux 網路協議開發基礎篇(十)—— 使用wireshark分析TCP/IP協議中TCP包頭的格式

    摘要: 本文簡單介紹了TCP面向連線理論知識,詳細講述了TCP報文各個欄位含義,並從Wireshark俘獲分組中選取TCP連線建立相關報文段進行分析。 一、概述 TCP是面向連線的可靠傳輸協議,兩個程序互發資料之前需要建立連線,這裡的連線只不過是端系統中分配的一些快

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

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

    網路協議分析——從裝置驅動到鏈路層

    對應我們上面的網絡卡驅動分析。接收到的資料是存放在data至tail之間的區域。 Skb通常還有常用的幾個函式,一一列舉分析如下: struct sk_buff *alloc_skb(unsigned int size,int gfp_mask) 分配儲存空間為sixe的skb,記憶體分配級別為gf

    linux網路協議分析筆記14-路由4-FIB3

    看完fib的查詢,弄清了一些資料結構的組織,我們再來看看路由表是如何建立的 從ip_fib_init註冊的兩個通知鏈來看,在IP地址傳送變動時會觸發通知鏈的處理函式,都會呼叫fib_add_ifaddr()來新增地址到路由中 這個裡面由呼叫了fib_magic來進行路由地址的操作。 static void

    Linux 核心網路協議 ------sk_buff 結構體 以及 完全解釋 (2.6.16)

    在2.6.24之後這個結構體有了較大的變化,此處先說一說2.6.16版本的sk_buff,以及解釋一些問題。 一、 先直觀的看一下這個結構體~~~~~~~~~~~~~~~~~~~~~~在下面解釋每個欄位的意義~~~~~~~~~~~ struct sk_buff {

    Linux網路協議()——套接字快取(socket buffer)

    Linux網路核心資料結構是套接字快取(socket buffer),簡稱skb。它代表一個要傳送或處理的報文,並貫穿於整個協議棧。 1、    套接字快取 skb由兩部分組成: (1)    報文資料:它儲存了實際在網路中傳輸的資料; (2)    管理資料:供核心處理報

    Linux 網路協議開發程式碼分析篇之VLAN(三)—— VLAN收發處理

            以一個例子來說明,當主機收到報文,交由vlan協議模組處理後(vlan_rcv),此時需要更換skb->dev所指向的裝置,以使上層協議認為報文是來自於虛擬網絡卡(比如eth1.1),而不知道網絡卡eth1的存在。更換裝置就需要知道skb->dev更換的目標。這由兩個因素決定:sk

    Linux 網路協議開發(六)—— 層橋轉發藍圖(下)

    struct sk_buff *br_handle_vlan(struct net_bridge *br,                      struct net_bridge_vlan_group *vg,                      struct sk_b

    BACnet協議移植分析:rs485.mak

    rs485.mak是VC平臺可以轉換dsp檔案的makefile。原始檔是rs485.c,目標檔案是rs485。 Makefile to build test case CC      = gcc BASEDIR = . # -g for debugging with

    異數OS TCP協議測試()--短連線篇

    異數OS TCP協議棧測試(二)--短連線篇 本文來自異數OS社群   github:  https://github.com/yds086/HereticOS 異數OS社群QQ群:  652455784 異數OS-織夢師(訊息中介軟體)群: 47626038

    ZigBee協議開發(

    1、掌握ZigBee無線模組基本工作電路(官方): 在實際做東西的時候要加一些其他的東西,讓我們更好地應用這個基本電路。 復位電路:20腳如下接(1us低電平) 程式下載電路(五根線): 2、隨心所欲的控制io的輸入輸出 40腳,但晶片背面有額外的一個接地腳。 共有21個通用

    SylixOS 網路協議lwip介紹3-----udp資料接收

    資料包接收包括兩個部分。首先網絡卡獲取一個數據包並使用中斷通知系統,系統解析這個資料包放入緩衝佇列中。再由應用層呼叫介面recv()或recvfrom()獲取這個資料包。 1、中斷接收 (1)    系統在初始化時會註冊網絡卡中斷,處理函式為dm9000IntI

    SylixOS 網路協議lwip介紹2-----UDP資料傳送流程

    UDP資料包的傳送是通過sendto()發起的(其他介面類似),整體實現流 程如下: (1)    通過檔案描述符fd獲取檔案結構,並提取lwipfd。再通過lwipfd從socket表中獲取socket結構。Socket結構中包含了此udp連結中的connec

    SylixOS 網路協議lwip介紹1-----pbuf結構

        SylixOS網路協議棧使用目前非常流行的嵌入式TCP/IP協議棧lwip。lwip是瑞典電腦科學院(SICS)的AdamDunkels 開發的一個小型開源的TCP/IP協議棧。lwip特點是對RAM與ROM的佔用非常少,只需十幾KB的RAM和40

    關於各種 網路協議 抓包分析 的一些文章

    各協議埠號 https://blog.csdn.net/ypt523/article/details/79636647   TCP/IP/UDP/ICMP/ARP/ethernet 各種協議頭部結構體 https://blog.csdn.net/xiexievv/art

    Linux 核心網路協議 ------ 擁塞避免處理函式 tcp_reno_cong_avoid

    慢啟動和快速重傳擁塞避免演算法,函式tcp_reno_cong_avoid 在“慢開始”階段,每收到一個ACK,cwnd++一次,那麼一個RTT之後,cwnd就會加倍 擁塞避免階段,其實就是在一個RTT時間內將cwnd++一次( 注意在不丟包的情況下 ) /* *

    學習Linux-4.12核心網路協議(1.6)——協議的初始化(inet_init實現過程)

    這篇文章主要分析inet_init()函式的實現過程: 1796 static int __init inet_init(void) 1797 { 1798 struct inet_protosw *q; 1799 struct list_head *r;