SKB几个复制函数的区别
2011-3-1
1、skb_clone()
Skb_clone()函数只是复制sk_buff结构,并不复制skb的数据缓冲区。Clone后的sk_buff结构与原始的sk_buff指向同一数据缓冲区。原始的和clone后的skb描述符的cloned值都会被置1,clone的skb描述符的users值置1,同时数据缓冲区的引用计数dataref增加1。
- /**
-
* skb_clone - duplicate an sk_buff
-
* @skb: buffer to clone
-
* @gfp_mask: allocation priority
-
*
-
* Duplicate an &sk_buff. The new one is not owned by a socket. Both
-
* copies share the same packet data but not structure. The new
-
* buffer has a reference count of 1. If the allocation fails the
-
* function returns %NULL otherwise the new buffer is returned.
-
*
-
* If this function is called from an interrupt gfp_mask() must be
-
* %GFP_ATOMIC.
-
*/
-
-
struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
-
{
-
struct sk_buff *n;
-
-
/* n指向被clone的skb */
-
n = skb + 1;
-
/* 判断原始skb是否是从skbuff_fclone_cache 缓冲区中分配的,从skbuff_fclone_cache 分配将预先为clone的skb分配好内存,同时判定该预先分配的clone skb是否被使用 */
-
if (skb->fclone == SKB_FCLONE_ORIG &&
-
n->fclone == SKB_FCLONE_UNAVAILABLE) {
-
/* 预先从skbuff_fclone_cache 中分配的skb结构,且未使用,则增加dataref计数*/
-
atomic_t *fclone_ref = (atomic_t *) (n + 1);
-
n->fclone = SKB_FCLONE_CLONE; /* 置clone的skb中fclone值为SKB_FCLONE_CLONE ,标明其数据区指向原始skb同一数据区 */
-
atomic_inc(fclone_ref);
-
} else {
-
/* 主skb并未同时分配clone skb的情况,将重新独立分配skb结构作为clone的skb */
-
n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
-
if (!n)
-
return NULL;
-
-
kmemcheck_annotate_bitfield(n, flags1);
-
kmemcheck_annotate_bitfield(n, flags2);
-
/* 指明该clone的skb并未分配独立的数据缓冲区 */
-
n->fclone = SKB_FCLONE_UNAVAILABLE;
-
}
-
/* 完成后续的skb结构体的复制工作 */
-
return __skb_clone(n, skb);
-
}
-
-
-
/*
-
* You should not add any new code to this function. Add it to
-
* __copy_skb_header above instead.
-
*/
-
static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
-
{
-
#define C(x) n->x = skb->x
-
-
n->next = n->prev = NULL;
-
n->sk = NULL;
-
/* copy 头部字段,详细请参考源代码,很简单 */
-
__copy_skb_header(n, skb);
-
-
C(len);
-
C(data_len);
-
C(mac_len);
-
n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
-
n->cloned = 1;
-
n->nohdr = 0;
-
n->destructor = NULL;
-
C(tail);
-
C(end);
-
C(head);
-
C(data);
-
C(truesize);
-
/* 设置skb描述符的users为1 */
-
atomic_set(&n->users, 1);
-
-
/* 增加shinfo中dataref的引用计数,因为clone的skb与原始skb指向同一数据缓冲区*/
-
atomic_inc(&(skb_shinfo(skb)->dataref));
-
skb->cloned = 1; /* 指明原始skb是被clone过的 */
-
-
return n;
-
#undef C
-
}
特别说明,skb_clone()函数复制的只是skb描述符,而复制后的skb与原始skb指向的是同一数据缓冲区,由于数据缓冲区并未加什么同步锁机制,因此skb_clone()操作的skb结构的数据缓冲区是不能被修改的。
阅读(2980) | 评论(0) | 转发(0) |