最近在寫網路編程方面的一些東西,然後遇到了關於傳輸上的小問題。由於之前有簡單的看過一些TCP/IP詳解的一些東西,所以索性就找了本《追蹤LinuxTCP/IP代碼運行》的書看了一上午,結果發現初次接觸這些核心方面的東西,收穫甚微。於是又在網上找相關類的大神部落格,拿來拜讀,雖然依然看的不是太明白,吸收的也不夠好,但是我想以部落格的形式把它記錄下來,也希望能為我以後學這些東西開個好頭吧 1.linux的網路通訊協定棧的主要結構 (1)socket層
這層主要處理socket相關的東西,例如其各種結構的初始化等。每個socket在核心中以socket結構體的形式存在,它的結構體定義如下
socket結構體
struct socket{ socket_stat state; //socket的狀態 unsigned long flags; //socket的標誌位 const struct proto_ops *pos //socket的函數動作表 struct fasync_struct *fasync_list //socket的非同步喚醒隊列 struct file *file; //與socket關聯的檔案指標 struct sock *sk; //代表具體協議內容的sock結構指標 wait_queue_head_t wait //用於等待隊列 short type; //socket的類型}
其中sock結構體封裝了與具體協議相關的東西,它的結構體定義稍微有點大,所以這裡我就不一一列出,只是簡單的給大家介紹一下它定義的主要幾個模組
(1)定義了與inet_timewait_sock共用的結構體sock_common,該結構體主要包含了地址族,串連狀態,協議函數表等內容
(2)定義了各種和接收發送隊列相關的資料以及隊列
(3)用於記錄以及提供控制的各種接收發送的資料 (2)INET socket層
該層是個可用於各種網路通訊協定的介面,當用於TCP/IP (3)TCP/UDP層
主要處理傳輸層的操作,傳輸層用struct inet_protocol和struct proto倆個結構表示 (4)IP層
處理網路層的操作,網路層用stuct packet_type結構的表示 (5)資料連結層和驅動程式
每一個網路裝置都以struct net_device結構體表示 2.TCP/IP協議棧的一些代碼的簡單分析 (1)主要資料結構
struct msghdrstruct sk_bufstruct socketstruct sockstruct proto_opsstruct proto
不言而喻通訊端層對應操作的就是socket,那麼我們如何建立一個socket呢。接觸過網路編程的大概都會知道瘡癤一個通訊端只需調用函數socket(),其實這個函數內部實現是非常複雜的,它會根據上述函數的參數建立一個socket執行個體(應該可以理解成對socket結構體的初始化),並建立一個通訊端描述符,然後通過指標讓這二者建立聯絡。其中初始化socket時,會根據不同的協議初始化出不同的函數動作表pos(見上面的結構體資訊)。如果是TCP為inet_stream_ops,是UDP則為inet_dgram_ops,同時socket還通過調用sock中的相關操作完成從socket到sock層的傳遞初始化sock時還會初始化3個隊列。recvive_queue(接收的資料包sk_buf鏈表隊列),send_queue(需要發送資料包sk_buf的鏈表隊列),back_queue(TCP三向交握成功的資料包隊列)。還有將faimly初始化為inet類型,type為stream類型,sock_proto初始化為tcp_prot。
在一端進行write或send過程時,首先會把write緩衝區中的資料打包成msghdr的資料結構形式,然後調用sock_sendmsg把msghdr的資料發送至inet層(應運層與傳輸層的中間,提供各種協議的介面),然後msghdr的結構中的資料又被sk_buf結構所封裝,此時的資料包就是個完全體了,可以掛在發送隊列了 (2)linux的路由系統
主要儲存了三種與路由相關的資料,第一種是在物理上和本機相串連的主機地址資訊表,第二種是儲存了在網路訪問中判斷一個網路地址應該走啥路由的資料表,第三種是最新使用過的查詢路由地址的緩衝地址資料表
FIB結構中儲存了最重要的路由規則,通過其可以找到路由地址方法。系統中路由的手段一般為現在路由緩衝中尋找,如果能找到直接將對應的項作為路由規則,如果找不到,解根據FIB中的規則換算出來
資料連結層
前面提到的net_device硬體表對應於每一個網路介面裝置。這個結構中包含了很多可以直接擷取網卡資訊的函數和變數,以及對網卡操作的函數,此類函數直接指向網路卡驅動程式的入口,包括髮送和接收幀到緩衝區這些工作完成之後,便由netif_rx把緩衝區中的幀組成sk_buf的形式掛到系統的系統的接收隊列 2.啟動過程
初始化進程主要:start—>kernel—>do_basic_setup—>sock_init—->do_initcalls
do_initcalls初始化的基本流程可以概述如下
(1)協議的初始化
(2)路由的初始化
(3)網路介面裝置的初始化 3.網路連接
TCP串連通過如下函數
sockfd = socket(AF_INET,SOCK_STREAM,0);
connect(sockfd,&adress,sizeof(address))
在此函數的調用過程中主要發生了如下事情
(1)sys_socket系統調用,它又調用socket_creat()來建立一個滿足socket函數參數的socket結構,而sock_creat()又會根據協議的不同調用不同的函數,對inet來說,它會調用inet_create函數,然後它還會調用其他的一系列的函數
(2)在系統初始化工作完成之後便會進行connect的工作,connect將一個和sockect關聯的通訊端描述符與一個遠端機器相關聯,並調用各個協議自己對應的connect串連函數。TCP為inet_stream_connect
(3)inet_stream_connect會得到一個sk結構,這個sk結構描述了通訊端的一些屬性以及狀態,對於TCP來說然後調用tcp_v4_connect函數
(4)tcp_v4_connect()又調用其他函數用於尋找合適的路由 4.串連的關閉
(1)關閉串連時由close調用sock_close函數
(2)sock_close()調用sock_release()來釋放一些空間
(3)inet_release調用socket對應的協議的關閉函數,最後釋放sk 5.發送資料的流程圖
接收資料的流程圖
大家如果看完我的學習筆記對哪有疑問的可以戳到人家的原文串連
http://blog.csdn.net/cz_hyf/article/details/602802