/home/green/src/list.c
alloc_skb
kfree_skb
skb_put
skb_trim
#############
/home/green/src/list.c
#############
alloc_skb
kfree_skb
skb_put // used data后部扩展
skb_push // used data前部扩展
skb_pull // used data前部截断
skb_trim // used data后部截断
skb_reserve // data+分片后移,只允许对空缓存使用
skb_queue_head_init // 初始化struct sk_buff_head
skb_queue_head // list头部添加一个packet
skb_queue_tail // list尾部添加一个packet
skb_dequeue // 移去list头部第一个packet(返回移除的packet指针,内存没有收回?)
skb_dequeue_tail // 移去list尾部第一个packet
skb_queue_purge // 清空list中的节点
skb_append // 在list的给定packet后append一个packet
skb_insert // 在list的给定packet前insert一个packet
#############
alloc_skb
#############
<linux-2.6.36/net/core/skbuff.c>
__alloc_skb()分析:
申请struct skb_buff skb空间, 必须从CACHE中申请(skbuff_fclone_cache或skbuff_head_cache).
申请数据区内存, 使用kmalloc. 数据区包括字节对齐后的size和struct skb_shared_info.
填充skb结构.
填充分片信息struct skb_shared_info shinfo.
如果头部skb_buff是从skbuff_fclone_cache中申请的,do something... //TODO
********
__alloc_skb()完成时,内存状态:
skb struct sk_buff <-| skb->truesize
-------------- |
data size |
skb->data |
skb->head |
------------- <-|
struct skb_shared_info
tail 和 end是偏移量
skb->tail = skb->data - skb->head = 0
skb->end = skb->tail + skb->size
********
head,data是指针,tail,end是偏移量。
<linux-2.6.36/include/linux/skbuff.h>
#ifdef NET_SKBUFF_DATA_USES_OFFSET
typedef unsigned int sk_buff_data_t;
#else
typedef unsigned char *sk_buff_data_t;
#endif
struct sk_buff {
/* These elements must be at the end, see alloc_skb() for details. */
sk_buff_data_t tail;
sk_buff_data_t end;
unsigned char *head,
*data;
unsigned int truesize;
atomic_t users;
};
*********
skb,shinfo的引用计数都是原子类型atomic_t.
volatile只读内存,不读寄存器.
#############
kfree_skb
#############
内存屏障
软件可通过读写屏障强制内存访问次序.所有在设置读写屏障之前发起的内存访问,必须先于在设置屏障之后发起的内存访问之前完成,确保内存访问按程序的顺序完成.
smp_mb() 适用于多处理器的内存屏障。
smp_rmb() 适用于多处理器的读内存屏障。
http://blogold.chinaunix.net/u3/93713/showart_2061476.html
#############
skb_put
#############
BUG() BUGON()
BUG()和BUG_ON()被用来提供断言,当被调用时会引发oops,导致栈的回溯和错误信息的打印.
大部分体系结构把BUG()定义成某种非法操作.
断言某种情况不该发生:
if(bad_thing):
BUG();
或者更好的形式:
BUG_ON(bad_thing);
******
frag_list
如果传输层将数据包分片了,就会把这些数据包放到skb的frag_list链表中.
******
skb_put 在尾部扩展used data area.常被用于给数据块添加协议尾部.
其实就修改了tail偏移量和len值,别的什么都没做.
设了俩断言:
数据包不能有分片;
扩展数据区不能超出skb->end.
#############
skb_trim
#############
struct sk_buff
truesize = skb + data
len = data + 分片
data+len = 分片