skb_buff 详解(二)

来源:互联网 发布:网络实践教程全部答案 编辑:程序博客网 时间:2024/06/08 03:27


skbuffs是那些linux内核处理网络分组的缓存。网卡收到分组后,将它们放进skbuff,然后再传送给网络堆栈。网络堆栈一直

要用到skbuff。

1. 一个完整的skb buff组成(1) struct sk_buff--用于维护socket buffer状态和描述信息
(2) header data--独立于sk_buff结构体的数据缓冲区,用来存放报文分组,使各层协议的header存储在连续的空间中,以方便协议栈对其操作

(3) struct skb_shared_info --作为header data的补充,用于存储ip分片,其中sk_buff *frag_list是一系列子skbuff链表,而frag[]是由一组单独的page组成的数据缓冲区

这两个函数的定义位于net/core/skbuff.c文件内。通过这alloc_skb()申请的内存空间有两个,一个是存放实际报文数据的内存空间,通过kmalloc()函数申请;一个是sk_buff数据结构的内存空间,通过 kmem_cache_alloc()函数申请



len和data_len

之前说过len代表的是整个数据的长度,data_len代表的是非线性数据长度。

现在从分配内存开始解释这个图的由来:

我们使用skb_alloc给skb分配空间,那么刚刚分配结束返回时候,是什么样的情况呢?看下图(图二):

刚刚开始初始化的时候,预分配一个一块线性数据区域,这个区域一般放入的是各个协议层次的不同的头,还有一些实际数据,下面的非线性区域是为了弥补当数据真的很多的时候,作为数据区域的扩展!关于skb_shared_info具体意思下面会继续说!注意在初始化的时候,head,data和tail都指向内存的开始位置,head在这个位置始终不变,它表示的是分配的内存的开始位置。end的位置也是不变的,表示的是分配的内存的结束位置。data和tail会随着数据的加入和减少变化,总之表示的是放入数据的内存区域(由图一)可知。

现在需要解释一下skb_shared_info这个结构体,这个结构体真的是很很有特色!主要是其中的两个字段frags和frag_list,下面继续解释:

struct skb_shared_info {         atomic_t        dataref;        // 对象被引用次数         unsigned short  nr_frags;       // 分页段数目,即frags数组元素个数         unsigned short  tso_size;                unsigned short  tso_segs;         unsigned short  ufo_size;         unsigned int    ip6_frag_id;         struct sk_buff  *frag_list;    // 一般用于分段(还没有非常清楚的理解)         skb_frag_t      frags[MAX_SKB_FRAGS]; // 保存分页数据(skb->data_len=所有的数组数据长度之和)};

关于frags和frag_list没有必然的联系!

> : 对于frags[]一般用在,当数据真的很多,而且在线性数据区域装不下的时候,需要使用这个,skb_frag_t中是一页一页的数据,先看看结构体:

struct skb_frag_struct {         struct page *page;    // 代表一页数据         __u16 page_offset;    // 代表相对开始位置的页偏移量         __u16 size;           // page中数据长度};
需要注意的是:只有在DMA支持物理分散页的Scatter/Gather(SG,分散/聚集)操作时候才可以使用frags[]来保存剩下的数据,否则,只能扩展线性数据区域进行保存!!!

这些页其实是其实就是虚拟页映射到物理页的结构,看下图(图三):



对于frag_list来说,一般我们在分片的时候里面装入每个片的信息,注意,每个片最终也都是被封装成一个小的skb,



0 0
原创粉丝点击