- 论坛徽章:
- 3
|
本帖最后由 dreamice 于 2011-03-02 21:04 编辑
2、pskb_copy()
与skb_copy()不同,当一个函数不仅需要修改skb描述符,而且需要修改其缓冲区中的数据时,就需要复制缓冲区的数据。如果需要修改的数据在skb->head到skb->end之间,即数据是一个线性空间的数据时,便可调用pskb_copy()函数来完成此操作。
- /**
- * pskb_copy - create copy of an sk_buff with private head.
- * @skb: buffer to copy
- * @gfp_mask: allocation priority
- *
- * Make a copy of both an &sk_buff and part of its data, located
- * in header. Fragmented data remain shared. This is used when
- * the caller wishes to modify only header of &sk_buff and needs
- * private copy of the header to alter. Returns %NULL on failure
- * or the pointer to the buffer on success.
- * The returned buffer has a reference count of 1.
- */
-
- struct sk_buff *pskb_copy(struct sk_buff *skb, gfp_t gfp_mask)
- {
- /*
- * Allocate the copy buffer
- */
- struct sk_buff *n;
- /* 先申请skb描述符字段的内存空间,在这种情况下,skb描述符是不能继用预先分配的skb描述符的 */
- #ifdef NET_SKBUFF_DATA_USES_OFFSET
- n = alloc_skb(skb->end, gfp_mask);
- #else
- n = alloc_skb(skb->end - skb->head, gfp_mask);
- #endif
- if (!n)
- goto out;
-
- /* Set the data pointer */
- /* 设置数据指针 */
- skb_reserve(n, skb->data - skb->head);
- /* Set the tail pointer and length */
- /* 设置skb->tail指针和skb->len 长度 */
- skb_put(n, skb_headlen(skb));
- /* Copy the bytes */
- /* 拷贝线性空间的数据 */
- skb_copy_from_linear_data(skb, n->data, n->len);
-
- /* 对share info结构进行拷贝,并设置相关字段的值 */
- n->truesize += skb->data_len;
- n->data_len = skb->data_len;
- n->len = skb->len;
-
- if (skb_shinfo(skb)->nr_frags) {
- int i;
-
- /*在share info中有数据的情况下,拷贝share字段,特别注意:这里并没有拷贝share info中的数据 */
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- skb_shinfo(n)->frags[i] = skb_shinfo(skb)->frags[i];
- get_page(skb_shinfo(n)->frags[i].page);
- }
- skb_shinfo(n)->nr_frags = i;
- }
-
- if (skb_has_frags(skb)) {
- skb_shinfo(n)->frag_list = skb_shinfo(skb)->frag_list;
- skb_clone_fraglist(n);
- }
-
- /* 拷贝skb头部的相关字段 */
- copy_skb_header(n, skb);
- out:
- return n;
- }
-
- /**
- * skb_reserve - adjust headroom
- * @skb: buffer to alter
- * @len: bytes to move
- *
- * Increase the headroom of an empty &sk_buff by reducing the tail
- * room. This is only allowed for an empty buffer.
- */
- static inline void skb_reserve(struct sk_buff *skb, int len)
- {
- skb->data += len;
- skb->tail += len;
- }
复制代码 特别说明:pskb_copy()与skb_copy()更重量级一些,他不仅仅拷贝skb描述符,还需要拷贝skb->data指向的数据,但他并不拷贝share info指向的非线性数据,新skb的share info指向与原始skb的share info相同的数据。 |
|