释放控制结构skb和它所指的存储空间。由于一个存储空间可以有多个控制结构,所以只有在存储空间的引用计数为1的情况下才释放存储空间,一般情况下,只释放控制结构skb。unsigned char *skb_put(struct sk_buff *skb, unsigned int len)将tail指针下移,并增加skb的 len值。data和 tail之间的空间就是可以存放网络报文的...
size = SKB_DATA_ALIGN(size); /*分配数据缓冲区,其长度为size大小加上skb_shared_info结构大小*/ data = kmalloc_node_track_caller(size + sizeof(struct skb_shared_info), gfp_mask, node); if (!data) goto nodata; memset(skb, 0, offsetof(struct sk_buff, truesize)); /*设置truesize大小为...
unsigned char *skb_put(struct sk_buff *skb, unsigned int len) 将tail指针下移,并增加skb的 len值。data和 tail之间的空间就是可以存放网络报文的空间。这个操作增加了可以存储网络报文的空间,但是增加不能使tail的值大于end的值,skb的 len值大于truesize的值。 unsigned char *skb_push(struct sk_buff *s...
if ( unlikely(skb->data < skb->head ) ) skb_under_panic(skb , len , __builtin_return_address(0)) ; return skb->data ; } /** * skb_pull - remove data from the start of a buffer * @skb : buffer to use * @len : amount of data to remove * * This function removes data ...
skb->len //大哥、小弟和兄弟的总和,即data的总长度,线性和非线性的总和。 skb->data_len //小弟和兄弟的总和,即大哥缺少的份额,非线性数据长度。 skb_headlen() //即大哥长度,线性长度。和skb_headroom()不一样,这个是只头部空间剩余长度。 skb_pagelen() //大哥和小弟的总和,即线性数据长度和页面碎片的...
skb->len =2有效负载 (线性区域 + 非线性区域(datalen),这里暂时不考虑协议头部) Case2:如果缓冲区积压(存在未被ACK的已经发送的网络包-即SEND-Q中存在sk_buff结构),Linux会尝试将当前包合并到SEND-Q的最后一个sk_buff结构中(粘包);考虑我们上述的768bytes的结构体为SEND-Q的最后一个sk_buff,当用户进程继...
size = SKB_DATA_ALIGN(size);//调整skb大小 size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); data = kmalloc_node_track_caller(size, gfp_mask, node);//分配数据区 if (!data) goto nodata; /* kmalloc(size) might give us more room than requested. ...
Linux内核的网络操作是基于分层设计的,可以形象地比喻为一个数据包的“栈”操作。数据包的形成是通过逐层封装,即所谓的push操作,而解封装则是逐层弹出,即pop操作。核心数据结构sk_buff在这一过程中起到了关键作用。sk_buff操作涉及的步骤包括:首先,通过alloc_skb分配sk_buff结构和数据包缓冲区,...
staticinlinevoidskb_reset_tail_pointer(struct sk_buff *skb) { skb->tail = skb->data; } 最终四大指针初始化为以下图所示: 此时head、data、tail三个指针指向一起,end指向数据缓冲区的尾部。 预留协议头空间:在sk_stream_alloc_skb调用__alloc_skb函数进行内存分配后,下一步就会预留协议头空间,使得head、...
skb_add_data_nocache(sk, skb, from, copy); } ... 这个函数比较长,不过其实逻辑并不复杂。其中 msg->msg_iov 存储的是用户态内存的要发送的数据的 buffer。接下来在内核态申请内核内存,比如 skb,并把用户内存里的数据拷贝到内核态内存中。这就会涉及到一次或者几次内存拷贝的开销。 至于内核...