Chinaunix首页 | 论坛 | 博客
  • 博客访问: 324829
  • 博文数量: 34
  • 博客积分: 860
  • 博客等级: 准尉
  • 技术积分: 524
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-23 12:04
文章存档

2011年(16)

2010年(7)

2009年(4)

2008年(7)

分类: LINUX

2011-03-01 21:00:45

SKB几个复制函数的区别

2011-3-1

1skb_clone()

Skb_clone()函数只是复制sk_buff结构,并不复制skb的数据缓冲区。Clone后的sk_buff结构与原始的sk_buff指向同一数据缓冲区。原始的和clone后的skb描述符的cloned值都会被置1cloneskb描述符的users值置1,同时数据缓冲区的引用计数dataref增加1

  1. /**
  2.  *    skb_clone    -    duplicate an sk_buff
  3.  *    @skb: buffer to clone
  4.  *    @gfp_mask: allocation priority
  5.  *
  6.  *    Duplicate an &sk_buff. The new one is not owned by a socket. Both
  7.  *    copies share the same packet data but not structure. The new
  8.  *    buffer has a reference count of 1. If the allocation fails the
  9.  *    function returns %NULL otherwise the new buffer is returned.
  10.  *
  11.  *    If this function is called from an interrupt gfp_mask() must be
  12.  *    %GFP_ATOMIC.
  13.  */

  14. struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
  15. {
  16.     struct sk_buff *n;

  17.     /* n指向被clone的skb */
  18.     n = skb + 1;
  19.     /* 判断原始skb是否是从skbuff_fclone_cache 缓冲区中分配的,从skbuff_fclone_cache 分配将预先为clone的skb分配好内存,同时判定该预先分配的clone skb是否被使用 */
  20.     if (skb->fclone == SKB_FCLONE_ORIG &&
  21.      n->fclone == SKB_FCLONE_UNAVAILABLE) {
  22.         /* 预先从skbuff_fclone_cache 中分配的skb结构,且未使用,则增加dataref计数*/
  23.         atomic_t *fclone_ref = (atomic_t *) (n + 1);
  24.         n->fclone = SKB_FCLONE_CLONE; /* 置clone的skb中fclone值为SKB_FCLONE_CLONE ,标明其数据区指向原始skb同一数据区 */
  25.         atomic_inc(fclone_ref);
  26.     } else {
  27.         /* 主skb并未同时分配clone skb的情况,将重新独立分配skb结构作为clone的skb */
  28.         n = kmem_cache_alloc(skbuff_head_cache, gfp_mask);
  29.         if (!n)
  30.             return NULL;

  31.         kmemcheck_annotate_bitfield(n, flags1);
  32.         kmemcheck_annotate_bitfield(n, flags2);
  33.         /* 指明该clone的skb并未分配独立的数据缓冲区 */
  34.         n->fclone = SKB_FCLONE_UNAVAILABLE;
  35.     }
  36.     /* 完成后续的skb结构体的复制工作 */
  37.     return __skb_clone(n, skb);
  38. }


  39. /*
  40.  * You should not add any new code to this function. Add it to
  41.  * __copy_skb_header above instead.
  42.  */
  43. static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
  44. {
  45. #define C(x) n->x = skb->x

  46.     n->next = n->prev = NULL;
  47.     n->sk = NULL;
  48.     /* copy 头部字段,详细请参考源代码,很简单 */
  49.     __copy_skb_header(n, skb);

  50.     C(len);
  51.     C(data_len);
  52.     C(mac_len);
  53.     n->hdr_len = skb->nohdr ? skb_headroom(skb) : skb->hdr_len;
  54.     n->cloned = 1;
  55.     n->nohdr = 0;
  56.     n->destructor = NULL;
  57.     C(tail);
  58.     C(end);
  59.     C(head);
  60.     C(data);
  61.     C(truesize);
  62.     /* 设置skb描述符的users为1 */
  63.     atomic_set(&n->users, 1);

  64.     /* 增加shinfo中dataref的引用计数,因为clone的skb与原始skb指向同一数据缓冲区*/
  65.     atomic_inc(&(skb_shinfo(skb)->dataref));
  66.     skb->cloned = 1; /* 指明原始skb是被clone过的 */

  67.     return n;
  68. #undef C
  69. }
  70. 特别说明,skb_clone()函数复制的只是skb描述符,而复制后的skb与原始skb指向的是同一数据缓冲区,由于数据缓冲区并未加什么同步锁机制,因此skb_clone()操作的skb结构的数据缓冲区是不能被修改的

阅读(2931) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~