在使用socket函數建立通訊端時,系統建立socket/sock兩個結構體,用於本機資料的管理,組織,而這兩個資料結構是不會被傳送到網路上的,而真正被用來攜帶資料的結構體是skb_buff,系統在開闢skb_buff結構體空間時,同時把使用者資料所需要的空間一起開闢了,也就是一次malloc(sizeof(struct skb_buff)+size)這麼多空間,即skb_buff本身的大小,加上使用者空間所需要的size大小的空間,由於malloc分配,所以這些空間時連續的一片空間的,也就是說skb_buff結構體資料結束後,接著就是使用者的資料,因此,skb_buff結構體的最後成員unsigned char data[0],定義了一個數組,卻沒有成員,就是只有數組名,這個數組名所指向的空間恰恰是skb_buff結構體的尾部,也正是使用者資料的首部。
struct sk_buff {
struct sk_buff * volatile next;
struct sk_buff * volatile prev;/*這兩個欄位用於構成 sk_buff結構的隊列*/
#if CONFIG_SKB_CHECK
int magic_debug_cookie;/*調試之目的*/
#endif
/*這個指標也是用於構成 sk_buff結構的隊列。這個隊列就是資料包重發隊列,用於 TCP協議中。重發隊列是由 sock 結構的 send_head, send_tail 欄位指向的隊列。send_head 指向這個隊列的首部,send_tail 指向這個隊列的尾部。而隊列的串連是使用 sk_buff結構的 link3 欄位完成的。send_head, send_tail是指向 sk_buff 結構的指標,而非 sk_buff_head 結構*/
struct sk_buff * volatile link3;/*該資料包所屬的通訊端*/
struct sock *sk;/*該資料包的發送時間。該欄位用於計算往返時間 RTT*/
volatile unsigned long when; /* used to compute rtt's */
/*該欄位也是記錄時間,但目前暫未使用該欄位用於任何目的*/
struct timeval stamp;
/*對於一個接收的資料包而言,該欄位表示接收該資料包的介面裝置。對於一個待發送的資料
包而言,該欄位如果不為 NULL,則表示將要發送該資料包的介面裝置*/
struct device *dev;
/*該 sk_buff結構在記憶體中的基地址,該欄位用於釋放該 sk_buff 結構*/
struct sk_buff *mem_addr;
/*該欄位一個等位型別,表示了資料包在不同處理層次上所到達的處理位置。如在鏈路層上,
eth 指標有效,指向乙太網路首部第一個位元組位置,在網路層上,iph 指標有效指向 IP 首部第
一個位元組位置。raw 指標隨層次變化而變化,在鏈路層上時,其等於 eth,在網路層上時,
其等於 iph。seq 是針對使用 TCP 協議的待發送資料包而言,此時該欄位值表示該資料包的
ACK值。ACK值等於資料包中第一個資料的序號加上資料的長度值。*/
union {
struct tcphdr *th;
struct ethhdr *eth;
struct iphdr *iph;
struct udphdr *uh;
unsigned char *raw;
unsigned long seq;
} h;
/*指向 IP首部的指標,此處特別的分出一個欄位用於指向 IP首部主要用於 RAW 通訊端*/
struct iphdr *ip_hdr; /* For IPPROTO_RAW */
/*該欄位表示 sk_buff結構大小加上資料幀的總長度*/
unsigned long mem_len;
/*該欄位只表示資料幀長度。即 len=mem_len – sizeof(sk_buff).*/
unsigned long len;
/*這兩個欄位用於分區資料包。fraglen 表示分區資料包個數,而 fraglist 指向分區資料包隊列*/
unsigned long fraglen;
struct sk_buff *fraglist; /* Fragment list */
unsigned long truesize;/*同 mem_len*/
unsigned long saddr;/*資料包發送的源端 IP地址*/
unsigned long daddr;/*資料包最終目的端 IP地址*/
unsigned long raddr; /* next hop addr 資料包下一站 IP地址*/
/*
acked=1 表示該資料包已得到確認,可以從重發隊列中刪除。
used=1 表示該資料包的資料已被應用程式讀完,可以進行釋放。
free=1 用於資料包發送,當某個待發送資料包 free 標誌位等於 1,則表示無論該資料包是否
發送成功,在進行發送操作後立即釋放,無需緩衝。
arp 用於待發送資料包,該欄位等於 1 表示此待發送資料包已完成 MAC 首部的建立。arp=0
表示 MAC 首部中目的端硬體地址尚不知曉,故需使用 ARP協議詢問對方,在 MAC 首部尚
未完全建立之前,該資料包一直處於發送緩衝隊列中(device 結構中 buffs 數組元素指向的
某個隊列以及 ARP協議的某個隊列中) 。
*/
volatile char acked,
used,
free,
arp;
/*
tries 欄位表示該資料包已進行 tries 試發送,如果試發送超出域值,則會放棄該資料包的發
送。如對於 TCP建立串連之 SYN 資料包,發送次數超過 3次即放棄發送。
lock 表示該資料包是否正在被系統其它部分使用。
localroute 表示進行路由時是使用區域網路路由(localroute=1)還是廣域網路路由
pkt_type
該資料包的類型,可取如下值:
PACKET_HOST
這是一個發往原生資料包。
PACKET_BROADCAST
廣播資料包。
PACKET_MULTICAST
多播資料包。
PACKET_OTHERHOST
該資料包是發往其它機器的,如果本機沒有被配置為轉寄功能,該資料包即被丟棄
*/
unsigned char tries,lock,localroute,pkt_type;
#define PACKET_HOST 0 /* To us */
#define PACKET_BROADCAST 1
#define PACKET_MULTICAST 2
#define PACKET_OTHERHOST 3 /* Unmatched promiscuous */
/*users 使用該資料包的模組數*/
unsigned short users; /* User count - see datagram.c (and soon seqpacket.c/stream.c) */
/*同 pkt_type*/
unsigned short pkt_class; /* For drivers that need to cache the packet type with the skbuff (new PPP) */
#ifdef CONFIG_SLAVE_BALANCING
unsigned short in_dev_queue;/*該欄位表示該資料包是否正在緩衝於裝置緩衝隊列中*/
#endif
unsigned long padding[0];/*填充位元組。目前定義為 0 位元組,即無填充*/
unsigned char data[0];/*指向資料部分。資料一般緊接著該 sk_buff結構,也有可能在任何地址處*/
};
同時還有一個結構體
struct sk_buff_head {
struct sk_buff * volatile next;
struct sk_buff * volatile prev;
#if CONFIG_SKB_CHECK
int magic_debug_cookie;
#endif
};
它的成員與 sk_buff 結構的開始幾個欄位時一樣的,如此處理可以利用指標轉化將 sk_buff_head 當作 sk_buff 結構使用,反過來也如此。
系統就是通過上述兩個結構體來組織資料,並形成隊列,最終在網路上傳輸