linux下IPROTO_TCP,TCP/IP协议栈在Linux内核中的运行时序分析
可選題目三:TCP/IP協議棧在Linux內核中的運行時序分析
在深入理解Linux內核任務調度(中斷處理、softirg、tasklet、wq、內核線程等)機制的基礎上,分析梳理send和recv過程中TCP/IP協議棧相關的運行任務實體及相互協作的時序分析。
編譯、部署、運行、測評、原理、源代碼分析、跟蹤調試等
應該包括時序
一, 基礎概念簡介
1.什么是TCP/IP?
TCP/IP 也即傳輸控制協議/網際協議(Transmission Control Protocol / Internet Protocol),是一類通信協議,也是因特網種最根本的協議,用于提供已連接因特網的計算機進行通信。TCP/IP 定義了電子設備(比如計算機)如何連入因特網,以及數據如何在它們之間傳輸的標準。當然,TCP/IP協議不僅僅是指TCP和IP兩個協議,而是指一類協議,如下圖所示,對于四層模型,應用層中Telnet、FTP、SMTP等協議及傳輸層TCP/UDP協議也包括其中。以此命名,也只是因為在TCP/IP協議中TCP協議和IP協議最具代表性。
2.osi七層模型
OSI參考模型將網絡結構劃分為七層,即物理層、數據鏈路層、網絡層、傳輸層、會話層、表示層和應用層。每一層均有自己的一套功能集,并與緊鄰的上層和下層交互作用。在頂層,應用層與用戶使用的軟件進行交互,在七層模型中,每個分層都接受由它下一層所提供的特定服務,并且負責為自己的上一層提供特定的服務。需要注意的是OSI為理論參考模型,現在普遍采用的是下面介紹的四層模型。
3. TCP/IP四層模型
基于TCP/IP的參考模型將網絡結構分成四層,分別是網絡訪問層、網際層、傳輸層和應用層。相對于OSI參考模型,去掉了會話層和表示層(這兩層的功能被合并到應用層實現)。同時將OSI參考模型中的數據鏈路層和物理層合并為網絡訪問層。
4.Socket
Socket接口是TCP/IP網絡的API,獨立于具體協議的網絡編程接口,在TCP/IP模型中,socket套接字主要位于傳輸層和應用層之間。Socket接口定義了許多函數或例程,可以用它們來開發TCP/IP網絡上的應用程序,事實上,它是設計模式的一種應用,用于讓編程變的更簡單。
二、套接口層相關結構
1.socket結構
2.proto_ops 結構:套接口系統調用到傳輸層函數的跳轉表,完成從套接口層到傳輸層的映射功能
3.sock結構:公用的網絡描述塊,定義了基本的傳輸控制塊結構。與具體的協議無關。
4.proto結構:在proto_ops 結構的基礎上,進一步將傳輸層和網絡層之間進行映射
5.net_proto_family:每一個協議族都會用net_porto_family結構的一個實例進行表示,在初始化時,會調用sock_register函數進行統一的注冊
三、Socket系統調用
1.sys_socketcall
在Linux系統中,所有的socket系統的調用總入口都為sys_socketcall,其函數原型為:
函數的兩個形參含義如下:
*call:每個數字代表一個操作碼,一共17種,具體操作碼對應情況如下:
對一些常用操作的說明:
SYS_SOCKET: 創建一個套接口,若創建成功,返回一個打開的文件描述符
SYS_BIND:將套接字地址與套接字號相綁定
SYS_CONNECT: 建立連接
SYS_LISTEN: 僅在TCP服務器端調用,將套接字轉換到LISTEN狀態
SYS_ACCEPT: 用于面向對象的連接器,用于接受新的連接
SYS_SEND:見下分析
SYS_RECV:見下分析
*args參數:為一個指針,指向數組,其可以根據不同的操作碼要求,從用戶態復制相應長度的數據,結構如下:
2.SYS_SOCKET()函數分析:
前面有同學對該函數進行了一定的分析,但是仍不夠全面,在此做一定的補充。首先對源碼進行分析:
我們發現在sys_socket函數中,還調用了兩個函數:socket_create()以及socket_mp_fd(),下面我們進一步對這兩個函數進行進一步的解析:
sock_create()
事實上,我們可以看到該函數只是將__socket_create()進行了簡單封裝,并將最后一個參數默認設置為0,所以我們這里將對__socket_create()做解析即可。
__socket_create()函數解析:
2.socket_mp_fd()
socket_map_fd的功能實際上是將socket套接口與文件描述符進行綁定(實際上我們從函數名也可以推測出)。
綜上所述,由此我們可以得到sys_socket的函數調用時序圖大致如下:
跟蹤調試結果:
四、Send系統調用分析:
事實上sys_send只是對sys_sendto函數的簡單封裝:
同時未指定數據輸出的目的地址(參數為NULL),所以采取默認地址,即connect函數連接的那個地址。
所以我們對sys_sendto函數進行分析即可,實際上該函數的作用是將數據報發送至指定的目的地址,下面對源碼進行分析:
我們發現在sys_sendto函數種最終還是通過調用SYS_SENDMSG函數進行發送數據,所以我們接著對SYS_SENDMSG函數做分析。該函數的主要工作是將用戶空間的信息復制到內核空間中,然后再逐級調用發包接口發送數據。具體到源碼的解析如下:
通過上述源碼的分析,我們大致可以畫出sendmsg函數的系統調用過程
調試結果:
五、RECV系統調用分析:
與send過程類似,相當于鏡像操作。這里就沒必要詳細展開了。直接給出調用過程圖如下:
調試結果:
五、傳輸層部分
網際層向傳輸層方向:
各調用函數作用說明:
1.tcp_v4_rcv():充當網絡層與傳輸層的接口,傳輸層報文處理入口函數
2.__inet_lookup_v4_lookup():在ehash或者bhask中查找傳輸控制塊,若無找到則進行退出, 并通過tcp_v4_send_reset(skb)發送RST段給對方,如果報文被損壞則無法發送rst,直接丟包
3.xfrm4_policy_check():進行安全檢查
4.sk_filter():看是否符合過濾器規則
5.tcp_v4_do_rcv():傳輸層處理TCP段的主入口
6.tcp_rcv_established():當連接已經建立時,用快速路徑處理報文
7. tcp_v4_hnd_req():為偵聽套口,處理半連接狀態的ACK消息
8. tcp_child_process():不是偵聽套接字,說明已經建立了半連接。調用此函數初始化子傳輸控制塊,如果失敗則向客戶端發送rst段,即tcp_v4_send_reset()
調試結果:
傳輸層向網際層方向:
大致經歷了以下幾個步驟:
調用Tcp_sendmsg函數檢查鏈接狀態,并同時獲取鏈接的MSS。創建該數據包的 sk_buffer 數據結構實例 skb,從 userspace buffer 中拷貝 packet 的數據到 skb 的 buffer。構造數據包頭部,接而計算 TCP 校驗和(ack)和順序號(seq)。最后調用ip_queue_xmit函數將數據包傳輸到網際層進行處理。
這里主要對Tcp_sendmsg函數的調用邏輯進行補充分析,該函數只要檢查已經建立的 TCP connection 的狀態,然后獲取有效的 MSS,Tcp_sendmsg函數的內部調用順序如下:
各調用函數作用說明:
1.Tcp_sendmsg分析:sendmsg系統調用在TCP層的實現
2.lock_sock():獲取套接口的鎖
3.sock_sndtimeo()根據標志計算阻塞超時時間
4.sk_stream_wait_connect():對于不能發送信息狀態須等待連接正確建立,超時
5.tcp_current_mss():獲得有效的MSS
六、網際層:
網際層到傳輸層方向:
各調用函數作用說明:
1.Ip_rcv函數:對IP頭部合法性進行嚴格檢查,如數據報文長度、首部長度、是否為共享數據包,然后把具體功能交給ip_rcv_finish
2.ip_rcv_finish函數:如果還未為該數據報查找輸入路由緩存,調用ip_route_input為其查找輸入的路由緩存,接著處理IP數據報首部中的選項,最后根據輸入路由緩存輸入到本地或轉發。
3.Ip_forward: 數據報轉發的接口函數。
4.Ip_forward_finish:完成輸入ip數據報的轉發
5.Ip_local_deliver:處理輸入到本地的IP數據報,將分片進行重組,獲得完整數據報,之后調用ip_local_deliver_finish函數進行數據傳輸。
6.ip_local_deliver_finish:將數據報從網絡層傳遞到傳輸層。
調試結果:
同時發現了傳輸層與網絡層接口部分·:
網際層到網絡訪問層方向:
各調用函數作用說明:
Ip_queue_xmit:將TCP端打包成IP數據報
Dst_output:封裝了輸出數據報目的路由緩存項中的輸出端口(分為兩類:單播,組播)
Ip_output: 處理單播數據報,設置數據報的輸出網絡設備以及網絡層協議類型參數。
Ip_finish_output:觀察數據報長度是否大于MTU,若大于,則調用ip_fragment分片,否則調用ip_finish_output2輸出;
Ip_ finish_output2: 對skb的頭部空間進行檢查,看是否能夠容納下二層頭部,若空間不足,則需要重新申請skb;然后,獲取鄰居子系統,并通過鄰居子系統輸出
調試結果:
網絡層與傳輸層的接口部分:
七、網絡訪問層:
從網際層接受數據方向:
數據包傳輸過程:
啟用軟中斷后,調用dev_queue_xmit函數對數據包進行處理,主要處理依據為是否采用了Generic Segmentation Offload技術,是否采用了QoS技術進行處理。對函數dev_queue_xmit的源碼分析如下:
從網絡接口層向網際層方向:
主要實現函數為softnet_data,前面有同學也提到,但未做出詳細分析,所以下面部分就softnet_data結構及其工作原理加以說明補充。該結構實質上描述的是與軟中斷相關的輸入及輸出隊列。該結構的源碼如下:
結構的參數說明:
Throttle:該參數與后面avg_blog、cng_level參數配合使用,實現擁塞管理算法,throttle的值實際為bool值,其含義是,當CPU是超載時,為true,否則為false。
cng_level:用于表示擁塞級別,在處理每一幀時會重新進行計算。
avg_blog:表示的是后面參數input_pkt_queue隊列的平均長度
input_pkt_queue:數據包排列形成的隊列結構
poll_list:等待處理入幀的雙向設備鏈表。
output_queue:記錄了需要發送數據包的設備列表。
completion_queue:記錄了已經成功發送可以釋放的緩沖區。
backlog_dev:表示與CPU相關的的設備
數據包傳輸過程:
若采取非NAPI方式,首先會通過硬中斷讀取數據包。再調用netif_rx函數將收到的數據包添加到input_pkt_queue隊列結構中,最后通過產生一個軟中斷的方式,依次將數據傳輸到網絡層。
若采取NAPI方式,相較于非NAPI方式,可以有效的減少硬中斷的數量。首先會將網絡設備添加到poll_list結構中,再通過軟中斷的方式將網絡設備中的報文傳輸到網絡層中。
標簽:調用,函數,IP,TCP,Linux,傳輸層,socket
來源: https://www.cnblogs.com/PaddyPan/p/14312038.html
總結
以上是生活随笔為你收集整理的linux下IPROTO_TCP,TCP/IP协议栈在Linux内核中的运行时序分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java 故障处理与性能监控工具
- 下一篇: 中南林科大c语言程序设计,2017年中南