歡迎您光臨本站 註冊首頁

linux網路整體認識

←手機掃碼閱讀     火星人 @ 2014-03-22 , reply:0

開始看重博客了,總覺得寫的不夠好。但為了有一個開始,先傳上來吧。這篇文章現在只有乾巴巴的文字,有些方面描述的不是很清晰,希望大家看的時候能從中獲取一些新的理解。

一、linux網路分層結構
linux的網路分層如下:
BSD socket(對應數據結構結構為socket->proto_ops,sock_iocb也包含在socket之中, 數據表示用msghdr結構)
Inet Socket 即傳輸層TCP、UDP(對應數據結構為sock數據結構,sock_common包含在其中;inet_sock->proto結構中包含了sock數據結構。數據包採用了sk_buff結構來表示)
IP層()
網卡驅動

二、linux network的全局變數
1. 通知結構全局變數, static struct notifier_block *netdev_chain;
當對某個nic調用ioctl時,應反應到每一個socket
2. 最上層協議全局變數static struct net_proto_family *net_families[NPROTO];
這個裡面放置的都是af_unix, af_inet, af_packet這樣的頂層協議結構
這一部分的內容,相當於BSD中提到的域的概念,用來支持不同的網路體系架構,例如iso和tcpip等等
3. 所有的proto類型的變數都要被鏈接到static LIST_HEAD(proto_list);中,當然這種類型的變數最終還是要被嵌入到sock結構體裡面的。
4. packet_type類型的數據結構
該數據結構是用於在協議棧與網路設備之間構築一個數據傳遞的橋樑。
有兩個全局的變數:
static struct list_head ptype_base[16];
static struct list_head ptype_all;
調用函數dev_add_pack()可把packet_type類型變數添加到hash表中,
在接收數據時netif_receive_skb()函數遍歷ptype_base鏈表,調用其中的每個rcv函數,並傳入skb結構。
在文件net/ipv4/af_inet.c中靜態定義了變數ip_packet_type,用來表示ip包結構
在文件net/ipv4/arp.c中靜態定義了變數arp_packet_type,用來表示arp包結構
5. 網路設備介面常用的全局變數
在Linux內核中,用結構體struct net_device代表一個網路設備介面,內核函數register_netdev用於向內核註冊一個網路設備介面。下面看幾個網路設備註冊相關的數據結構。
dev_base是一個struct net_device的全局指針,它指向的是一個包含當前系統中所有網路設備介面的鏈表,每次調用register_netdev註冊一個新的網路設備介面時,都會在這個鏈表的尾部新添加一項。
dev_name_head是一個list數組,它實際上是一個哈希表,系統中所有的的網路設備都以它們的名字作為哈希鍵值放入這個哈希表,以提供諸如dev_get_by_name這樣的介面,使得可以通過設備名找到設備。
dev_index_head也是一個list數組形式的哈希表,系統中的所有網路設備在註冊時都會被分配給一個索引號,它是按照設備註冊的順序遞增的一個值。所有的網路設備都以它們分配的索引號作為哈希鍵值放入這個哈希表,以提供諸如dev_get_by_index這樣的介面,使得可以通過設備索引號找到設備。
netdev_chain是一個struct notifier_block的全局鏈表,當一個網路設備介面被註冊或狀態發生變化時,需要調用這個鏈表中每一項中的成員函數,以通知相關模塊,設備發生了變化。如果某一模塊需要得到網路設備發生變化的通知,它只需要定義一個struct notifier_block,提供一個通知回調函數即可。所以網路設備註冊接下來要調用notifier_call_chain,通知所有相關的模塊,有一個新的網路設備介面被註冊進來了。
6. softnet_data對應的全局變數
每個CPU對應一個,它是一個結構體struct softnet_data類型,
struct softnet_data
{
struct net_device *output_queue;
struct sk_buff_head input_pkt_queue;
struct list_head poll_list;
struct sk_buff *completion_queue;
struct net_device backlog_dev;
};
成員input_pkt_queue是core層次的接收數據隊列。結構體struct sk_buff_head的成員qlen記錄接收隊列的長度,內核中對接收隊列的長度有一個上限限制mynetdev_max_backlog,其值定義為1000。

三、針對inet協議的數據結構和全局變數
1. 結構proto_ops是BSD Socket層的socket結構中定義的操作函數結構。這個結構的實現函數都工作在INET Socket層,實際指向的都是INET Socket層的具體函數。例如:tcp和udp分別指向inet_stream_ops和inet_dgram_ops。
2. 對應數據結構為sock數據結構,sock_common包含在其中;而inet協議自己做了一個數據結構inet_sock,它把數據結構sock作為自己的一個成員。結構proto是INET Socket層的控制函數,它定義不同的協議族,tcp和udp分別對應tcp_prot和udp_prot。
struct sock數據結構存放在文件include/net/sock.h中。
struct proto在文件include/net/sock.h中。
498 /* Networking protocol blocks we attach to sockets.
499 * socket layer -> transport layer interface
500 * transport -> network interface is defined by struct inet_protosw
501 */
3. 所有的傳輸層協議註冊過程
類型net_protocol的作用是提供一個本協議的接收函數,網路層收到數據報后,根據IP首部中的協議欄位確定是某一個協議的數據報,然後再到全局變數inet_protos中找到這個接收函數。
在文件include/net/protocol.h中定義該結構,在文件net/ipv4/protocol.c定義下面的全局變數,所有的傳輸層的協議TCP, UDP, ICMP, IGMP都要在其中註冊下面的數組中。
struct net_protocol *inet_protos[MAX_INET_PROTOS];
#define MAX_INET_PROTOS 256
使用函數inet_add_protocol把協議protocol的編號加到hash表inet_protos中,
使用inet_del_protocol從hash表inet_protos刪除某個協議。
在文件net/ipv4/af_inet.c中靜態定義了協議變數tcp_protocol, udp_protocol, igmp_protocol, icmp_protocol。
4.數據結構struct inet_protosw 。
所謂結構struct inet_protosw是某些傳輸層協議所提供的服務類型,例如:SOCK_STREAM對應可靠數據流服務,SOCK_DGRAM對應不可靠數據報文服務,SOCK_RAW對應原始IP層服務。
在函數inet_protosw中即有struct proto的指針,也有struct proto_ops的指針。
對應靜態全局變數static struct inet_protosw inetsw_array[] ={}
該靜態全局變數靜態定義了三種socket類型:SOCK_STREAM、SOCK_DGRAM、SOCK_RAW。
針對ipv4的話實際上是一一對應的,SOCK_STREAM對應tcp, SOCK_DGRAM對應udp,SOCK_RAW對應raw ip。
在這種情況下,同一套接字類型在協議棧的數組inetsw_array中僅對應一項。同一套接字的不同協議類型用鏈表連接起來。
5. inet_protosw結構數組inetsw_array和net_protocol結構數組inet_protos的對應關係是: inet_protosw::protocol域是整數,這個數就是net_protocol結構類型的數組inet_protos[]的索引。
使用如下: inet_protos[inet_protosw::protocol]就得到了inet_protosw類型的變數。

[火星人 ] linux網路整體認識已經有347次圍觀

http://coctec.com/docs/linux/show-post-107945.html