Chinaunix首页 | 论坛 | 博客
  • 博客访问: 631575
  • 博文数量: 51
  • 博客积分: 773
  • 博客等级: 军士长
  • 技术积分: 2392
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-07 21:32
文章分类
文章存档

2018年(1)

2013年(16)

2012年(34)

分类: LINUX

2012-11-06 20:37:22

缓冲区的克隆和拷贝
当一个缓冲区需要被特别处理时,可能需要修改sk_buff描述符的内容,但内核不需要完全拷贝sk_buff结构和相关联的数据缓冲区。为了提高效率,内核可以只克隆原始值,也就是拷贝sk_buff结构,然后增加数据缓冲区的引用计数,防止被释放。
    当一个数据包需要被传输给多个接受者,如协议处理例程或多个网络分流器时,就需要使用数据包克隆技术。
    sk_buff的克隆没有链接到任何表,而且也没有引用套接字的拥有者。skb->cloned字段在克隆的和原来的结构猪都设置为1.克隆的skb->users设置为1,但对数据缓冲区的引用计数会递增,因为又有一个sk_buff结构指向这个数据区。
skb_clone函数可用于检查一个skb缓冲区的克隆状态。
skb_share_check函数检查skb->users引用计数是否为1,当不为1时,则说明这个skb是共享的,克隆一个新的skb返回,同时将原来的skb引用计数减一。否则直接返回原来的skb。

当一个缓冲区被克隆是,数据区块的内容不能修改,因此访问该数据的代码不需要上锁机制。当若函数不仅需要修改sk_buff结构体的字段,还需要修改数据时,就必须连数据缓冲区一起克隆。这种情况有两种选择:若只需要修改skb->head和skb->end区域的数据内容,则可以使用pskb_copy只克隆这个区域。若需要修改分片数据块中的内容,则需要使用skb_copy将分片区域的数据一起克隆。在skb_shared_info结构中也可以包含一个sk_buff结构列表frag_list。
以下分别为pskb_copy和skb_copy函数的操作结果:
常见sk_buff元素队列的管理函数
skb_queue_head_init:对skb_buff_head队列头指针进行初始化
skb_queue_head、skb_queue_tail:把一个sk_buff添加到队列头或尾
skb_dequeue、skb_dequeue_tail:将一个sk_buff从队列头或尾移除
skb_queue_purge:把队列变为空队列
skb_queue_walk:遍历队列中的每个元素

这类函数必须以原子方式执行,所以会获取sk_buff_head队列头结构的自旋锁

  1. void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk)
  2. {
  3.     unsigned long flags;

  4.     spin_lock_irqsave(&list->lock, flags);
  5.     __skb_queue_head(list, newsk);
  6.     spin_unlock_irqrestore(&list->lock, flags);
  7. }

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