只要把數據在協議棧中的流動線路和脈絡弄清楚了,關於協議棧的實現部分,理解起來就輕鬆多了。
在網絡編程章節的數據接收過程當中,咱們主要介紹過read()、recv()、recvfrom()還有一個recvmsg()沒介紹到,今天咱們就來看一下這幾個API函數到底有什麼差異。
數據接收
在接收數據的過程,主要分兩個階段:BOTTOM-HALF和TOP-HALF。
BOTTOM-HALF:
當從網卡驅動收到數據包後即進入BOTTOM-HALF階段,在這裏要根據以太幀頭部中的類型字段來肯定上層承載的具體協議類型,如IP,或ARP、RARP等。IP報文的處理函數一般交付給ip_recv()函數來處理,而後數據進入網絡層,具體流程:
若是該數據包是發給本機的通常調用ip_local_deliver()函數,若是是須要本機轉發給出去的,而且本機也開啓了轉發功能,那麼就會調用ip_forward()函數。
在這裏咱們看到了Netfilter的身影,很久沒看到它了,仍是有些親切。你們能夠結合這幅圖回頭再理解一下Netfilter和協議棧的關係。
BOTTOM-HALF最後將收到的skb填充到socket套接字的接收隊列裏,參見下圖。
TOP-HALF:
緊承BOTTOM-HALF階段,該階段的主要任務就是從接收隊列裏拿出一個skb而後將其傳遞到用戶空間去,以下:
能夠看出,這幾個函數的內部最終都統一到了一塊兒:__sock_recvmsg()。
數據發送
一樣的,數據發送也分兩個階段,對照接收的狀況,發送數據時確定也存在一個發送隊列,這樣想就對了。前面關於發送數據包時咱們介紹過的API有write()、send()、sendto()還有一個sendmsg()沒介紹到。
TOP-HALF以下:
BOTTOM-HALF以下所示:
通過這麼一份探索,咱們對這幾個數據收發的API至少理解的要比別人深入些了吧。至於不一樣函數之間的回調、調用關係是如何搭建的,咱們在協議棧分析章節再作進一步討論。最後來一張全家福:
完。