承接上一篇:sk_buff整理笔记(一、数据结构)这一篇要讲的是内核为sk_buff结构提供的一些操作函数。
第一、首先要讲的是sk_buff中的四大指针:
四大指针分别是:head、data、tail、end;这四个指针都是指向了数据区的,数据区中存放的是协议头和数据。head和end指针是每个数据包一样的,也是有这两个指针来确定数据区的大小的。最开始的时候head、data、tail三个指针都是指向一起的,当有协议数据加进来时才更改。
再来说下包的形成,首先是应用层的数据,然后到四层加上四层的TCP协议头(假设为TCP包),然后发往三层;在三层时把四层发来的数据都当作是负载,然后再往负载前加上一个三层IP协议头,发往二层;最后二层加上个帧头就可以发送了。所以在包形成时,这几个指针起到了非常关键的作用。下面来看下四个指针的指向地址大小,这也有利于对下面要讲到一些操作函数的理解。
最后一句的意思是:当数据包在二层(即data指针指向二层协议头)时,获取到三层协议头指针的一种方法。当然也可以直接用自带的获取三层协议头指针的函数(其实函数里面也是用上面这句代码实现的),这里只是为了显示data增加时,是往下移动的。方便后面的几个函数理解。
第二、几个操作sk_buff指针的函数:
首先来说下三个空间,方便下面介绍函数时理解。第一个是:headroom,就是skb->head和skb->data之间的空间;第二个是:data,就是skb->data和skb->tail之间的空间;第三个是:tailroom,就是skb->tail和skb->end之间的空间。如下图:
接下来说下四个操作sk_buff结构中指针的函数:(a)skb_put(), (b)skb_push(), (c)skb_pull(), and (d)skb_reserve();这四个函数在数据包在各层之间传输时,起到了至关
重要。
(a)skb_put():向后扩大数据区空间,headroom空间不变,tailroom空间减少,skb->data指针不变,skb->tail指针下移;
(b)skb_push():向前扩大数据区空间,headroom空间减少,tailroom空间不变,skb->tail指针不变,skb->data指针上移;
(c)skb_pull():缩小数据区空间,headroom空间增大,tailroom空间不变,skb->data指针下移,skb->tail指针不变;
(d)skb_reserve():数据区不变,headroom空间增大,tailroom空间减少,skb->data和skb->tail同时下移;
大家也可以照着源码来分析,还有个当大家看源码时,会发现好多函数都有个同名的,比如:skb_push()函数,就有两个:static inline unsigned char *__skb_push(struct sk_buff *skb, unsigned int len);和unsigned char *skb_push(struct
sk_buff *skb, unsigned int len);第一个函数是具体内容的实现(关键函数),第二个函数只是在第一个函数的基础上进行一些合法性检查。
第三、其他简单的操作函数:
获取/设置协议头指针等一系列函数,如:获取IP头指针,unsigned char *skb_network_header(const struct sk_buff *skb);还有其他些函数(skb内存申请、skb克隆和复制、skb队列操作)将到后面做详细分析。
sk_buff整理笔记(二、操作函数),布布扣,bubuko.com