Linux内核--网络协议栈深入分析(二)--sk_buff的操作函数2
函数执行完成后,sk_buff的数据指针的形式如下:2、kfree_skb()函数
该函数就是释放不被使用的sk_buff结构
/**
* kfree_skb - free an sk_buff
* @skb: buffer to free
*
* Drop a reference to the buffer and free it if the usage count has
* hit zero.
*/
void kfree_skb(struct sk_buff *skb)
{
if (unlikely(!skb))
return;
if (likely(atomic_read(&skb->users) == 1)) smp_rmb();
else if
(likely(!atomic_dec_and_test(&skb->users))) return;
trace_kfree_skb(skb, __builtin_return_address(0));
__kfree_skb(skb);
} 再调用__kfree_skb函数
void __kfree_skb(struct sk_buff *skb)
{
skb_release_all(skb);//释放除了skb本身占用的内存kfree_skbmem(skb);
} 这里不再向深层函数探究,以后再说。
3、skb_put()函数
该函数是在数据区的末端添加某协议的尾部
/**
* 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);
SKB_LINEAR_ASSERT(skb);
skb->tail += len;//尾部后移len
skb->len += len;//长度增加len
if (unlikely(skb->tail > skb->end))//panic
skb_over_panic(skb, len,
__builtin_return_address(0));
return tmp;
} 执行前后的示意图如下:4、skb_push()函数
该函数的作用是在数据区的前端添加某协议的头部,和
skb_put类似。
只不过这里移动的数据指针的是data前移len个单位。
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;
}
5、skb_pull和skb_trim函数正好和上面两个函数的功能相反,是去掉相应的部分,不再赘述。
6、skb_reverse()函数
该函数的作用是在数据区创建存储协议头部的空间,函数实现很简单。
static inline void skb_reserve(struct sk_buff *skb, int len) {
skb->data += len;
skb->tail += len;