linux 内核网络sk_buff布局字段 “每日读书”

sk_buff 有些字段只是为了方便搜寻以及组织数据结构本身,内核在一个双向链表中维护所有的sk_buff结构,但是该表的组织比传统的双向链表更为复杂。

像任何双向链表一样,通过每个sk_buff 结构中的next和prev字段实现联系,next字段只想前,prev指向后,但是,这个表还有另一项必要需求,每个sk_buff 结构必须能够快速找到整个表的头,为了实现这个,在表的开端额外增加一个sk_buff_head 结构作为一种哑元元素,sk_buff_head结构是,

struct sk_buff_head {

struct sk_buff *next;

struct sk_buff *prev;

__u32 qlen;

spinlock_t lock;

}

qlen 代表表中的元素的数目,lock是用于防止对表的并发访问,在本章稍后的表管理函数,一节中会予以描述。

sk_buff和sk_buff_head 的前两个元素是相同的,next和prev指针,尽管sk_buff_head与sk_buff 相比实在太小,但是还是允许两个结构共同存在一个表中。

另外,同样的函数也可以用于操作sk_buff和sk_buff_head二者。

每个sk_buff 结构都包涵一个指针,指向单一的sk_buff_head 结构,增加了其复杂性,这个指针的字段名称为list, 图2-1 有助于你了解这些数据结构的关系。

sk_buff其他感兴趣的字段如下:

struct sock *sk

这是一个指针,指向拥有此缓冲区的套接字的sock数据结构,当数据在本地产生或者正由本地的进程接收时,就需要这个指针。因为该数据以及套接字相关的信息会由L4(TCP或者UDP)以及用户应用程序使用,当缓冲区只是被转发时,该指针就是NULL。

unsigned int len

这是指缓冲区中数据区块的大小。这个长度包括主要缓冲区的数据以及一些片段的数据,当缓冲区从一个网络分层移往下一个网络分层的时候,值就会变化,因为在协议栈重往上移动时报头就会被丢弃,但是往下移动的时候,就会添加进来,len也会吧协议报头算在内,如数据预留和对齐,skb_reserve,skb_put, skb_push 以及skb_pull 一节中国呢的图2-8所示。

unsigned int data_len

与len不同的是,data_len 只计算片段中的数据大小。

unsigned int mac_len

MAC报头的大小。

atomic_t user

这是引用计数,或者使用这个sk_buff缓冲区的实例的树木,这个参数的主要用途是避免在某人依然使用sk_buff结构时,把这个结构给释放,因此,此缓冲区的每个用户在必要时,都要递增和递减此字段,此计数器只计算sk_buff数据结构的用户,此缓冲区所包含的实际数据由一个相似的字段dataref 所包含,本章稍后的skb_shared_info 结构和skb_shinfo 函数,一节将予以介绍。

users 有时会直接用atomic_inc和atomic_dec函数递增和递减,但是大多数情况下,采用skb_get和kfree_skb 进行处理。

unsigned int truesize

此字段代表此缓冲区总的大小,包括sk_buff结构本身,当此缓冲区得到所分配的len个字符的数据请求空间时,此字段的初始化由alloc_skb函数设置成len + sizeof(sk_buff)

struct sk_buff *alloc_skb(unsigned int size, int gfp_mask)

{

skb->truesize = size + sizeof(struct sk_buff);

}

每当skb->len的值增加时,此字段就会得到更新。

unsigned char *head;

unsigned char *end;

unsigned char *data;

unsigned char *tail

这些字段代表缓冲区边界一起其中的数据,每当一个分层为其工作而准备缓冲区时,可能会为一个报头或者更多的数据分配更多的空间。head和end指向已经分配缓冲区空间的开端和尾端,而data和tail则指向实际数据的开端和尾端,参见图2-2所示,然后,该分层可以吧head和data之间的空隙填上一个协议报头,或者以新数据填入tail和head之间的空隙。在稍后的分配内存,alloc_skb 和dev_alloc_skb 一节中就会知道,图2-2右边的缓冲区在底端包含一个附加报头。

void (*destructor)(...)

此函数可以被初始化为一个函数,当此缓冲区被删除时,可完成某些工作,当此缓冲区不属于一个套接字时,destructor 通常不湖北初始化,此缓冲区属于一个套接字时,通常吧诶设置成sock_kfree或者sock_wfree ,这两个sock_xxx函数可用于更新套接字队列中所持有的内存。

相关推荐
gywl41 分钟前
openEuler VM虚拟机操作(期末考试)
linux·服务器·网络·windows·http·centos
WTT00111 小时前
2024楚慧杯WP
大数据·运维·网络·安全·web安全·ctf
杨德杰2 小时前
QT网络(一):主机信息查询
网络·qt
日记跟新中2 小时前
Ubuntu20.04 修改root密码
linux·运维·服务器
码农君莫笑2 小时前
信管通低代码信息管理系统应用平台
linux·数据库·windows·低代码·c#·.net·visual studio
BUG 4042 小时前
Linux——Shell
linux·运维·服务器
007php0072 小时前
Go语言zero项目部署后启动失败问题分析与解决
java·服务器·网络·python·golang·php·ai编程
yang_shengy2 小时前
【JavaEE】网络(6)
服务器·网络·http·https
大霞上仙3 小时前
Linux 多命令执行
linux·运维·服务器
晨欣3 小时前
Kibana:LINUX_X86_64 和 DEB_X86_64两种可选下载方式的区别
linux·运维·服务器