Chinaunix首页 | 论坛 | 博客
  • 博客访问: 365705
  • 博文数量: 166
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 10
  • 用 户 组: 普通用户
  • 注册时间: 2013-03-21 17:29
文章分类

全部博文(166)

文章存档

2015年(60)

2014年(99)

2013年(7)

我的朋友

分类: LINUX

2014-03-17 19:17:14

2pskb_copy()

skb_copy()不同,当一个函数不仅需要修改skb描述符,而且需要修改其缓冲区中的数据时,就需要复制缓冲区的数据。如果需要修改的数据在skb->headskb->end之间,即数据是一个线性空间的数据时,便可调用pskb_copy()函数来完成此操作。

  1. /**

  2.  * pskb_copy - create copy of an sk_buff with private head.

  3.  * @skb: buffer to copy

  4.  * @gfp_mask: allocation priority

  5.  *

  6.  * Make a copy of both an &sk_buff and part of its data, located

  7.  * in header. Fragmented data remain shared. This is used when

  8.  * the caller wishes to modify only header of &sk_buff and needs

  9.  * private copy of the header to alter. Returns %NULL on failure

  10.  * or the pointer to the buffer on success.

  11.  * The returned buffer has a reference count of 1.

  12.  */

  13.  

  14. struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)

  15. {

  16.        /*

  17.         * Allocate the copy buffer

  18.         */

  19.        struct sk_buff *n;

  20. /* 先申请skb描述符字段的内存空间,在这种情况下,skb描述符是不能继用预先分配的skb描述符的 */

  21. #ifdef NET_SKBUFF_DATA_USES_OFFSET

  22.        n = alloc_skb(skb->end, gfp_mask);

  23. #else

  24.        n = alloc_skb(skb->end - skb->head, gfp_mask);

  25. #endif

  26.        if (!n)

  27.               goto out;

  28.  

  29.        /* Set the data pointer */

  30.     /* 设置数据指针 */

  31.        skb_reserve(n, skb->data - skb->head);

  32.        /* Set the tail pointer and length */

  33.     /* 设置skb->tail指针和skb->len 长度 */

  34.        skb_put(n, skb_headlen(skb));

  35.        /* Copy the bytes */

  36.     /* 拷贝线性空间的数据 */

  37.        skb_copy_from_linear_data(skb, n->data, n->len);

  38.    

  39.     /* 对share info结构进行拷贝,并设置相关字段的值 */

  40.        n->truesize += skb->data_len;

  41.        n->data_len = skb->data_len;

  42.        n->len = skb->len;

  43.  

  44.        if (skb_shinfo(skb)->nr_frags) {

  45.               int i;

  46.  

  47.         /*在share info中有数据的情况下,拷贝share字段,特别注意:这里并没有拷贝share info中的数据 */

  48.               for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {

  49.                      skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];

  50.                      get_page(skb_shinfo(n)->frags[i].page);

  51.               }

  52.               skb_shinfo(n)->nr_frags = i;

  53.        }

  54.  

  55.        if (skb_has_frags(skb)) {

  56.               skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list;

  57.               skb_clone_fraglist(n);

  58.        }

  59.  

  60.     /* 拷贝skb头部的相关字段 */

  61.        copy_skb_header(n, skb);

  62. out:

  63.        return n;

  64. }

  65.  

  66. /**

  67.  * skb_reserve - adjust headroom

  68.  * @skb: buffer to alter

  69.  * @len: bytes to move

  70.  *

  71.  * Increase the headroom of an empty &sk_buff by reducing the tail

  72.  * room. This is only allowed for an empty buffer.

  73.  */

  74. static inline void skb_reserve(struct sk_buff *skb, int len)

  75. {

  76.        skb->data += len;

  77.        skb->tail += len;

  78. }

特别说明:pskb_copy()skb_copy()更重量级一些,他不仅仅拷贝skb描述符,还需要拷贝skb->data指向的数据,但他并不拷贝share info指向的非线性数据,新skbshare info指向与原始skbshare info相同的数据。

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