alloc_skb函数的作用

打印 上一主题 下一主题

主题 1042|帖子 1042|积分 3130

alloc_skb是linux内核网络子体系中用于分配socket Buffer的核心函数,它是网络协议栈中数据包内存管理的核心接口
一、核心作用

   

  • 分配sk_buff结构体   

    • 创建一个新的sk_buff结构体实例,用于描述网络数据包的元数据和数据缓冲区。
    • sk_buff是内核网络协议栈处理处罚数据包的核心数据结构,贯穿数据包的整个生命周期(吸收、处理处罚、发送)。

  • 预分配数据缓冲区   

    • 为数据包分配一块内存(称为head或data区域),用于存储实际网络数据(如以太网帧、IP头、TCP载荷等)。
    • 支持灵活扩展:预留头部和尾部,便于协议栈添加或删除协议头

  二、函数原型

  1. #include <linux/skbuff.h>
  2. struct sk_buff *alloc_skb(unsigned int size, gfp_t priority);
复制代码
   

  • 参数     

    • size :数据缓冲区(data区域)的总巨细(单位:字节)
    • priority:内存分配标记(GFP_ATOMIC、GFP_KERNEL),决定内存分配的活动(是否允许睡眠)

  • 返回值     

    • 成功:指向新分配的sk_buff的指针
    • 失败:NULL(内存不敷时)

   三、内存布局

   分配后的sk_buff和缓冲区布局如下
  
  1. +-----------------+       +-----------------+
  2. |  sk_buff 结构体  |------>|  数据缓冲区       |
  3. +-----------------+       +-----------------+
  4.                             ^           ^
  5.                             |           |
  6.                           headroom    data
复制代码
      

  • head:缓冲区的起始地址
  • data:实际数据起始地址(通常位于head + headroom处)
  • end:缓冲区结束地址(head + size)
  • tail : 当前数据结束位置,初始时等于data,随数据追加后移
    四、使用场景

         
1. 网络驱动吸收数据包

                     网卡驱动从硬件吸收数据时,调用alloc_skb分配缓冲区,将数据拷贝到sk_buff后提交给协议栈。            
2. 协议栈构造数据包

                     如TCP/IP协议构造SYN、ACK等控制报文,或应用层通过socket发送数据时,需分配sk_buff存放数据            
3. 网络装备传输数据包

                     驱动在发送数据前,大概必要克隆或扩展sk_buff,此时会调用alloc_skb分配新缓冲区。                 五、关键参数详解

           
1. size参数

               

  • 必要数据载荷 + 协议头预留空间分配足够的内存。
  • 示例:构造一个TCP数据包时,需考虑:
     
  1. size = ETH_HLEN + IP_HLEN + TCP_HLEN + payload_size;
复制代码
     
2.  priority参数

            

  • GFP_ATOMIC
                           在原子上下文(如中断处理处罚、软中断)中必须使用此标记,分配不会触发睡眠,但大概因内存不敷失败                  

  • GFP_KERNEL
                           在进程上下文(如体系调用)中使用,允许内存接纳和睡眠,分配成功率更高。                         六、与dev_alloc_skb的区别

               

  • dev_alloc_skb
                              专为网络驱动设计,是alloc_skb的封装,主动添加了NET_SKB_PAD 头部预留(用于对齐优化),并默认使用GFP_ATOMIC标记                             原型:                     
  1. struct sk_buff *dev_alloc_skb(unsigned int length);
复制代码
       等效于:
      
  1. alloc_skb(length + NET_SKB_PAD, GFP_ATOMIC);
复制代码
       七、使用示例

                 
1. 驱动吸收数据包

        
  1. // 在网卡中断处理函数中分配 sk_buff
  2. struct sk_buff *skb = alloc_skb(len + NET_IP_ALIGN, GFP_ATOMIC);
  3. if (!skb) {
  4.     // 处理内存不足
  5.     return -ENOMEM;
  6. }
  7. // 对齐调整
  8. skb_reserve(skb, NET_IP_ALIGN);
  9. // 从网卡 DMA 区域拷贝数据到 sk_buff
  10. memcpy(skb_put(skb, len), hw_buf, len);
  11. // 提交给协议栈
  12. netif_rx(skb);
复制代码
        2. 构造TCP SYN数据包
        
  1. // 在进程上下文中构造 SYN 包
  2. struct sk_buff *skb = alloc_skb(MAX_TCP_HEADER, GFP_KERNEL);
  3. if (!skb) {
  4.     return -ENOMEM;
  5. }
  6. // 预留以太网、IP、TCP 头部空间
  7. skb_reserve(skb, ETH_HLEN + IP_HLEN + TCP_HLEN);
  8. // 填充 TCP 载荷
  9. unsigned char *data = skb_put(skb, payload_len);
  10. memcpy(data, payload, payload_len);
  11. // 构建协议头(此处省略具体协议栈操作)
  12. // ...
  13. // 发送数据包
  14. dev_queue_xmit(skb);
复制代码
        八、内存管理注意事项

         1. 释放sk_buff
                 使用kfree_skb或dev_kfree_skb释放sk_buff,这些函数会处理处罚引用计数和缓冲区接纳
        
  1. kfree_skb(skb); // 通用释放
  2. dev_kfree_skb(skb); // 专用于网络驱动
复制代码
        2. 制止内存泄漏
                 确保每个alloc_skb都有对应的释放操作,尤其在错误处理处罚路径中。
         3. 缓冲区共享
                 使用skb_clone或skb_copy时,需注意引用计数管理,制止重复释放
         九、性能优化

                  
1. 预分配内存池

                            高频网络场景(如高速网卡驱动)可预分配sk_buff池,淘汰动态分配开销                           
2. 零拷贝吸收

                            支持DMA的网卡可将数据直接写入sk_buff的缓冲区,制止内存拷贝。                           
3. 非线形数据

                            使用skb_add_rx_flag支持分散-聚集 I/O,淘汰大块内存分配                                     十、总结

          alloc_skb时Linux内核网络子体系中最底子的内存分配接口,用于创建和管理网络数据包的缓冲区。合理使用GFP_ATOMIC和GFP_KERNEL、精确处理处罚缓冲区生命周期,可制止内核崩溃或性能瓶颈
                        
        

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

东湖之滨

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表