1,struct sk_buff数据结构

struct sk_buff{
//这两个结构必须放在最前面
struct sk_buff *next;
struct sk_buff *prev;
struct sk_buff_head *list; struct sock *sk; //指向所属的sock结构
ktime_t tstamp; //表示包接收的时间 /*
这个变量的类型是net_device,net_device它代表一个网络设备。dev的作用与这
个包是准备发出的包还是刚接收的包有关。当收到一个包时,设备驱动会把sk_buff
的dev指针指向收到这个包的网络设备;当一个包被发送时,这个变量代表将要发
送这个包的设备。在发送网络包时设置这个值的代码要比接收网络包时设置这个值
的代码复杂。有些网络功能可以把多个网 络设备组成一个虚拟的网络设备(也就是
说,这些设备没有和物理设备直接关联),并由一个虚拟网络设备驱动管理。当虚拟
设备被使用时,dev指针指向虚拟设 备的net_device结构。而虚拟设备驱动会在一
组设备中选择一个设备并把dev指针修改为这个设备的net_device结构。因此,在某
些情况 下,指向传输设备的指针会在包处理过程中被改变。
*/
struct net_device *dev;
struct dst_entry *dst;
struct sec_path *sp; union{//运输层的的头信息
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
.......
unsigned char *raw;
}h; union{//网络层头信息
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
unsigned char *raw;
}nh; union{//链路层头信息
struct ethhdr *ethernet;
unsigned char *raw
} unsigned char cloned;//是否是克隆的 char cb[48]; .......
//这几个变量相当重要
unsigned char *head;
unsigned char *data;
unsigned char *tail;
unsigned char *end; ....... }

2,内核是如何维护sk_buff结构的,我们以一图明了:

由上图我们可以清晰的看到内核为何sk_buff结构

head:指针指向内存中已分配的用于存储网路数据的缓冲区起始地址,sk_buff和相关数据块在分配后,该指针的值就固定了。
data:指针指向对应当前协议层有效数据的起始地址。每个协议的有效数据含义不同。
tail:指向对应当前协议层有效数据负载的结尾地址,与data对应。
end:指向内存分配的数据缓冲区的结尾地址,与head指针对应。和head一样,sk_buff和相关数据块被分配后,end指针也就固定了

3,skb_buff的操作

Skb操作
1, skb_queue_empty检查队列是否为空
原型:int skb_queue_empty(struct sk_buff_head *list)
参数:list为队列的头
描述:如果队列为空返回真,否则返回假

2, skb_get引用缓冲区
原型:struct skb_buff* skb_get(struct sk_buff *skb)
参数:skb为要引用的缓冲区;
描述:对套接字缓冲区引用一次,返回指向缓冲区的指针

3, skb_free释放一个缓冲区
原型:void kree_skb(struct sk_buff *skb)
参数:skb为要释放的缓冲区
描述:删除一个缓冲区的引用,如果其引用计数变为0,则释放它

4, skb_cloned判断缓冲区是否是克隆的
原型:int skb_cloned(struct sk_buff *skb)
参数:skb为要检查的缓冲区
描述:如果以skb_clone标志来产生缓冲区,则返回真,否则返回假

5, skb_shared缓冲区是否是共享的
原型:int skb_shared(struct sk_buff *skb)
参数:skb为要检查的缓冲区
描述:如果有多于一个人引用这个缓冲区就返回真

6, skb_share_check检查缓冲区是否是共享的,如果是就克隆它
原型:struct sk_buff *skb_share_check(struct *skb,int pri)
参数:skb为要检查的缓冲区,pri为内存分配的优先级
描述:如果缓冲区的共享的,就克隆这个缓冲区,并把原来缓冲区的引用计数减一,返回新克隆的缓冲区,如果不是共享的,则返回原来的缓冲区,当从中断或者全局锁调用该函数时pri必须为GFP_ATOMIC,内存分配失败返回NULL

7, skb_unshare产生一个共享缓冲区的拷贝
原型:struct sk_buff *skb_unshare(struct sk_buff *skb,int pri);
参数:skb为要检查的缓冲区,pri为内存非配的优先级
描述:如果套接字缓冲区是克隆的,那么这个函数就创建一个新的数据数据拷贝,并把原来缓冲区的引用计数减一,返回因为计数为一的新拷贝,如果不是克隆的,就返回原来的缓冲区,当从中断或者全局锁调用该函数时,pri必须是GFP_ATOMIC,内存分配错误返回NULL

8, skb_queue_len获得队列的长度
原型:__u32 sk_queue_len(struct sk_buff_head *list)
参数:list为测量的链表

9, skb_queue_head,skb_que_tail将newsk添加到链表的首部/尾部
原型:void skb_queue_head/tail(struct sk_buff_head *list,
struct sk_buff *newsk)
参数:list为要使用的链表,newsk为要添加的缓冲区

下面是几个常用的,在此贴出源代码以便更好的理解


static inline void skb_reserve( struct sk_buff *skb , int len )
{
skb->data += len ;
skb->tail += len ;
} /**
* skb_put - add data to a buffer
* @skb : buffer to use
* @len : amount of data to add
*
* This function extends the used data area of the buffer. If this would
* exceed the total buffer size the kernel will panic. A pointer to the
* first byte of the extra data is returned.
*/ unsigned char *skb_put( struct sk_buff *skb , unsigned int len )
{
unsigned char *tmp = skb_tail_pointer(skb) ;
/* 如果存在非线性区,即data_len > 0 ,则报bug */
SKB_LINEAR_ASSERT(skb) ;
skb->tail += len ;
skb->len += len ;
if (unlikely(skb->tail > skb->end ))
skb_over_panic(skb , len , __builtin_return_address(0)) ;
return tmp ;
} /**
* skb_push - add data to the start of a buffer
* @skb : buffer to use
* @len : amount of data to add
*
* This function extends the used data area of the buffer at the buffer
* start. If this would exceed the total buffer headroom the kernel will
* panic. A pointer to the first byte of the extra data is returned.
*/ unsigned char *skb_push( struct sk_buff *skb , unsigned int len )
{
skb->data -= len ;
skb->len += len ;
if ( unlikely(skb->data < skb->head ) )
skb_under_panic(skb , len , __builtin_return_address(0)) ;
return skb->data ;
} /**
* skb_pull - remove data from the start of a buffer
* @skb : buffer to use
* @len : amount of data to remove
*
* This function removes data from the start of a buffer, returning the memory to
* the headroom. A pointer to the next data in the buffer is returned. Once the
* data has been pulled future pushes will overwrite the old data.
*/ unsigned char *skb_pull( struct sk_buff *skb , unsigned int len )
{
return skb_pull_inline(skb , len ) ;
} static inline unsigned char *skb_pull_inline(struct sk_buff *skb , unsigned int len)
{
return unlikely(len > skb->len ) ? NULL : __skb_pull(skb , len) ;
} static inline unsigned char *__skb_pull(struct sk_buff *skb , unsigned int len)
{
skb->len -= len ;
BUG_ON(skb->len < skb->data_len ) ;
return skb->data += len ;
}

linux内核skb操作的更多相关文章

  1. Linux内核 GPIO操作部分API

    内核中关于GPIO的操作API主要集中在<linux/of_gpio.h>和<linux/gpio.h>中,前者主要是GPIO直接与设备树相关的操作,在Linux 设备树操作A ...

  2. Linux 内核热插拔操作

    热插拔事件的实际控制是通过一套存储于 kset_hotplug_ops 结构的方法完成. struct kset_hotplug_ops { int (*filter)(struct kset *ks ...

  3. linux协议栈skb操作函数

  4. linux内核--中断处理程序

    一个设备的中断处理程序是它设备驱动程序的一部分--设备驱动程序是用于对设备进行管理的内核代码.中断处理程序与其他内核函数的真正区别在于,中断处理程序是被内核调用来响应中断的,而它们运行于我们称之为中断 ...

  5. 芯灵思Sinlinx A64开发板Linux内核定时器编程

    开发平台 芯灵思Sinlinx A64 内存: 1GB 存储: 4GB 开发板详细参数 https://m.tb.cn/h.3wMaSKm 开发板交流群 641395230 Linux 内核定时器是内 ...

  6. 全志A33开发板Linux内核定时器编程

    开发平台 * 芯灵思SinlinxA33开发板 淘宝店铺: https://sinlinx.taobao.com/ 嵌入式linux 开发板交流 QQ:641395230 Linux 内核定时器是内核 ...

  7. 芯灵思SinlinxA33开发板Linux内核定时器编程

    开发平台 * 芯灵思SinlinxA33开发板 淘宝店铺: https://sinlinx.taobao.com/ 嵌入式linux 开发板交流 QQ:641395230 Linux 内核定时器是内核 ...

  8. Linux内核0.11体系结构 ——《Linux内核完全注释》笔记打卡

    0 总体介绍 一个完整的操作系统主要由4部分组成:硬件.操作系统内核.操作系统服务和用户应用程序,如图0.1所示.操作系统内核程序主要用于对硬件资源的抽象和访问调度. 图0.1 操作系统组成部分 内核 ...

  9. Linux内核调试的方式以及工具集锦【转】

    转自:https://blog.csdn.net/gatieme/article/details/68948080 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原 ...

随机推荐

  1. tomcat加载类的顺序

    /bin:存放启动和关闭tomcat的脚本文件: /conf:存放tomcat的各种配置文件,比如:server.xml /server/lib:存放tomcat服务器所需要的各种jar文件(jar文 ...

  2. ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则

    原文:ASP.NET MVC基于标注特性的Model验证:一个Model,多种验证规则 对于Model验证,理想的设计应该是场景驱动的,而不是Model(类型)驱动的,也就是对于同一个Model对象, ...

  3. 2014阿里实习生面试题——mysql如何实现的索引

    这是2014北京站的两副面孔阿里实习生问题扯在一起: 在MySQL中.索引属于存储引擎级别的概念,不同存储引擎对索引的实现方式是不同的,比方MyISAM和InnoDB存储引擎. MyISAM索引实现: ...

  4. 一些javascript常用方法

    1.输入一个正整数n,从1累加到n,返回结果.(如果输入为非正整数,如:小数.0.负数.NaN或其它非数字则返回false) function f(n){ return ~~+n == n & ...

  5. 《C语言及程序设计初步》网络课程主页

    题记 CSDN要开在线教育频道,向我发出邀请,看能否开些课程. 我近日一直在关注着翻转课堂,试图在传统课堂中引入新的元素,这须要资源建设的积累.没有时间表的工作,非常难把握. 为CSDN做在线课程,为 ...

  6. EA强大的绘图工具---设计数据库表格

    关于EA这个优秀的软件是从师哥哪里听来的,自己瞎点了点,感觉也没什么.近期和和智福加上一个师哥合作敲机房收费系统时,想到之前听人说EA非常强大,便随便找了找关于EA使用的帮助手冊.果然惊喜-- 如题, ...

  7. c# 委托详解

    1.委托声明 2.委托入门实例 namespace ConsoleApplication1 { public delegate void methodDelegate(string str); cla ...

  8. Asterisk 未来之路3.0_0007

    原文:Asterisk 未来之路3.0_0007 Modules Asterisk 是基于模块构建的.一个模块提供某个特定的功能,它是动态的被装载.比如:信道驱动(chan_sip.so),或可以连接 ...

  9. 激活windows server 2012 R2的方法

    首先登陆dreamspark 注册一个账号https://www.dreamspark.com/Account/SignIn.aspx, 点击创建账户,信息可以完全瞎编,邮箱不存在也可以.然后使用“我 ...

  10. Mysql基础之字符集与乱码

    原文:Mysql基础之字符集与乱码 Mysql的字符集设置非常灵活 可以设置服务器默认字符集 数据库默认字符集 表默认字符集 列字符集 如果某一个级别没有指定字符集,则继承上一级. 以表声明utf8为 ...