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函数可用于更新套接字队列中所持有的内存。

相关推荐
涛ing1 小时前
32. C 语言 安全函数( _s 尾缀)
linux·c语言·c++·vscode·算法·安全·vim
__雨夜星辰__1 小时前
Linux 学习笔记__Day2
linux·服务器·笔记·学习·centos 7
大耳朵土土垚1 小时前
【Linux】日志设计模式与实现
linux·运维·设计模式
学问小小谢1 小时前
第26节课:内容安全策略(CSP)—构建安全网页的防御盾
运维·服务器·前端·网络·学习·安全
一ge科研小菜鸡2 小时前
网络安全实战指南:攻防技术与防御策略
网络
马立杰5 小时前
H3CNE-33-BGP
运维·网络·h3cne
Mason Lin6 小时前
2025年1月22日(网络编程 udp)
网络·python·udp
字节全栈_rJF6 小时前
概述、 BGP AS 、BGP 邻居、 BGP 更新源 、BGP TTL 、BGP路由表、 BGP 同步
网络·智能路由器·php
EchoToMe6 小时前
电信传输基本理论/5G网络层次架构——超三万字详解:适用期末考试/考研/工作
网络·5g·架构
深度Linux6 小时前
Linux网络编程中的零拷贝:提升性能的秘密武器
linux·linux内核·零拷贝技术