Socker Buffer的克隆

1 skb克隆

在什么时候需要对Socket Buffer进行克隆,某些时候,同一个Socket Buffer会由不同的进程进行独立处理,但这些进程所需要操作的只是sk_buff数据结构描述符,不需要对数据包本身做改动。这是为了提高处理性能,内核不需要对整个Socket Buffer(sk_buff数据结构和数据包缓冲区)做完全的复制,只对sk_buff数据结构做完全的复制,并对数据包的引用计数(dataref)加1,以此防止在还有进程使用该Socket Buffer的数据包情况下,缓冲区被释放。这就是sk_buff克隆函数的功能。这时原sk_buff和克隆的ks_buff共享同一个数据包。实现克隆操作的函数为:struct sk_buff *sk_clone(struct sk_buff *skb, gfp_t gtp_mask)。skb_clone产生一个队skb的克隆数据结构,返回指向克隆出来的sk_buff数据结构的指针。

克隆的sk_buff都具有以下特点:

  • 不放任何sk_buff的管理队列
  • 不属于任何套接字,即没有任何套接字拥有克隆的sk_buff.
  • 两个sk_buff的结构的skb->cloned域都需要设置为1,克隆出来的sk_buff的sk->users域应设置为1,这样当要释放克隆出来的sk_buff数据结构时,第一次对他的释放就能成功了。
  • 当一个sk_buff被克隆后,他的数据包中的值就不能再修改,这时我们访问数据包是可以不加锁,因为只能对数据包作读操作,也就不存在并发访问的问题

2 skb_clone函数

struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
{
	struct sk_buff_fclones *fclones = container_of(skb,
						       struct sk_buff_fclones,
						       skb1);
	struct sk_buff *n = &fclones->skb2;

	if (skb_orphan_frags(skb, gfp_mask))
		return NULL;

	if (skb->fclone == SKB_FCLONE_ORIG &&
	    n->fclone == SKB_FCLONE_FREE) {
		n->fclone = SKB_FCLONE_CLONE;
		atomic_inc(&fclones->fclone_ref);
	} else {
		if (skb_pfmemalloc(skb))
			gfp_mask |= __GFP_MEMALLOC;

		n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
		if (!n)
			return NULL;

		kmemcheck_annotate_bitfield(n, flags1);
		n->fclone = SKB_FCLONE_UNAVAILABLE;
	}

	return __skb_clone(n, skb);
}

实际调用的时__skb_clone

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_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(head_frag);
	C(data);
	C(truesize);
	atomic_set(&n->users, 1);  //设置标识位 

	atomic_inc(&(skb_shinfo(skb)->dataref)); //引用计数加1
	skb->cloned = 1;  //克隆标识

	return n;
#undef C
}

__skb_clone主要做了4件事

  • 对Socket Buffer数据结构各元素做复制
  • skb->cloned设置为1
  • 克隆的数据包skb->users设置为1
  • skb->dataref引用计数加1

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值