skb_trim // used data后部截?cái)?/div>
skb_reserve // data+分片后移,只允許對(duì)空緩存使用
skb_queue_head_init // 初始化struct sk_buff_head
skb_queue_head // list頭部添加一個(gè)packet
skb_queue_tail // list尾部添加一個(gè)packet
skb_dequeue // 移去list頭部第一個(gè)packet(返回移除的packet指針,內(nèi)存沒有收回?)
skb_dequeue_tail // 移去list尾部第一個(gè)packet
skb_queue_purge // 清空list中的節(jié)點(diǎn)
skb_append // 在list的給定packet后append一個(gè)packet
skb_insert // 在list的給定packet前insert一個(gè)packet
#############
alloc_skb
#############
<linux-2.6.36/net/core/skbuff.c>
__alloc_skb()分析:
申請(qǐng)struct skb_buff skb空間, 必須從CACHE中申請(qǐng)(skbuff_fclone_cache或skbuff_head_cache).
申請(qǐng)數(shù)據(jù)區(qū)內(nèi)存, 使用kmalloc. 數(shù)據(jù)區(qū)包括字節(jié)對(duì)齊后的size和struct skb_shared_info.
填充skb結(jié)構(gòu).
填充分片信息struct skb_shared_info shinfo.
如果頭部skb_buff是從skbuff_fclone_cache中申請(qǐng)的,do something... //TODO
********
__alloc_skb()完成時(shí),內(nèi)存狀態(tài):
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的引用計(jì)數(shù)都是原子類型atomic_t.
volatile只讀內(nèi)存,不讀寄存器.
#############
kfree_skb
#############
內(nèi)存屏障
軟件可通過讀寫屏障強(qiáng)制內(nèi)存訪問次序.所有在設(shè)置讀寫屏障之前發(fā)起的內(nèi)存訪問,必須先于在設(shè)置屏障之后發(fā)起的內(nèi)存訪問之前完成,確保內(nèi)存訪問按程序的順序完成.
smp_mb() 適用于多處理器的內(nèi)存屏障。
smp_rmb() 適用于多處理器的讀內(nèi)存屏障。
http://blogold.chinaunix.net/u3/93713/showart_2061476.html
#############
skb_put
#############
BUG() BUGON()
BUG()和BUG_ON()被用來提供斷言,當(dāng)被調(diào)用時(shí)會(huì)引發(fā)oops,導(dǎo)致棧的回溯和錯(cuò)誤信息的打印.
大部分體系結(jié)構(gòu)把BUG()定義成某種非法操作.
斷言某種情況不該發(fā)生:
if(bad_thing):
BUG();
或者更好的形式:
BUG_ON(bad_thing);
******
frag_list
如果傳輸層將數(shù)據(jù)包分片了,就會(huì)把這些數(shù)據(jù)包放到skb的frag_list鏈表中.
******
skb_put 在尾部擴(kuò)展used data area.常被用于給數(shù)據(jù)塊添加協(xié)議尾部.
其實(shí)就修改了tail偏移量和len值,別的什么都沒做.
設(shè)了倆斷言:
數(shù)據(jù)包不能有分片;
擴(kuò)展數(shù)據(jù)區(qū)不能超出skb->end.
#############
skb_trim
#############
struct sk_buff
truesize = skb + data
len = data + 分片
data+len = 分片