1. 程式人生 > >TCP/IP協議棧初始化(十一)完結篇-完成IP層與網絡卡的連線

TCP/IP協議棧初始化(十一)完結篇-完成IP層與網絡卡的連線

上回ICMP的插曲說完了,把一個ICMP socket的建立流程說完了。對於資料結構關係圖沒有加入什麼新元素。執行的流程是從inet_family_ops到inet_create,raw_prot,這樣的執行順序。此時完成的只是ICMP協議的處理socket。繼續看原始碼,icmp_init函式返回後,後面還有內容。當然要有,IP層和裝置還沒有關聯呢。走繼續看。
其實仔細一看,我們的協議棧的初始化也基本上接近尾聲了。下面是來到1434行的一個函式呼叫。一般預編譯裡的內容,我會選擇跳過,但這次要破例下。是的,你總想在自己的人生中堅持自己的原則,但總會有些人會讓你破壞自己的原則。沒有錯,這個函式正是這樣的。因為,它太有誘惑力了。關乎IP協議中的多播實現,忍不了了。
1434 ip_mr_init()


函式定義在net/ipv4/ipmr.c中。

1886 void __init ip_mr_init(void)
1887 {
1888 mrt_cachep = kmem_cache_create("ip_mrt_cache",
1889 sizeof(struct mfc_cache),
1890 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC,
1891 NULL);
1892 init_timer(&ipmr_expire_timer);
1893 ipmr_expire_timer.function=ipmr_expire_process;
1894 register_netdevice_notifier(&ip_mr_notifier);
1895 #ifdef CONFIG_PROC_FS
1896 proc_net_fops_create(&init_net, "ip_mr_vif", 0, &ipmr_vif_fops);
1897 proc_net_fops_create(&init_net, "ip_mr_cache", 0, &ipmr_mfc_fops);
1898 #endif
1899 }


1888 申請了一個快取物件,物件單元是struct mfc_cache。一般協議棧裡的快取都會記錄在協議的資料結構裡,作為成員存在。這裡沒有采用這樣的方式。暫不明白。
1892 初始化了一個定時器。同之前說過的路由表一樣,多播路由表也有超時的時間。看expire就是超期的意思。看原始碼的同時還學習了英文,多好。一箭雙鵰。
1893 超時定時器的事件處理函式。暫時記下就行,等超時了再去看,它幹了什麼。
1894 同路由表一樣,多播路由表也要接受特定的訊息來自我更新。註冊一個通知訊息的處理例項吧。同樣暫且不表。
後面兩個可以跳過。不能每次都破例。總結來說,這個函式,為多播建立了條件,可以存貯、更新多播路由表。
回到inet_init。來了一個函式。mibs是什麼東西?s是表示複數,mib 什麼?這個光猜是猜不出來的。我負責地去原始碼裡找了一圈,沒有找到。最後去bing的詞典裡查了下,是Management Information Base,可以翻譯為管理資訊庫。
1440 if (init_ipv4_mibs())
1441 printk(KERN_CRIT "inet_init: Cannot init ipv4 mibs\n");

然而這個函式我沒有打算把原始碼列出來,分析一下。沒有什麼新鮮的東西,全是協議棧的資料統計結構例項,形如xxx_statistics的名稱。然而,這是一個吉兆,如周易裡的“見龍在田,利見大人”一樣。這預示著,我們的協議棧初始化基本上完成了,快可以工作了。
1443 這個我打算跳過。還是去/proc目錄下建立一些目錄和檔案,提供訪問協議棧的介面。
1445 ipfrag_init();
這個是關於IP分片的初始化。當從上層協議中得到的資料分組,比當前鏈路層中的MTU還大時,IP就要開始分片了。本以為它會很複雜,進去一看,一堆初始化賦值,外加一個函式呼叫。函式來自net/ipv4/ip_fragment.c中。

610 void __init ipfrag_init(void)
611 {
612 ip4_frags.ctl = &ip4_frags_ctl;
613 ip4_frags.hashfn = ip4_hashfn;
614 ip4_frags.constructor = ip4_frag_init;
615 ip4_frags.destructor = ip4_frag_free;
616 ip4_frags.skb_free = NULL;
617 ip4_frags.qsize = sizeof(struct ipq);
618 ip4_frags.match = ip4_frag_match;
619 ip4_frags.frag_expire = ip_expire;
620 inet_frags_init(&ip4_frags);
621 }

至此需要引入一個管理資料結構例項。ip4_frags,型別為struct inet_frags。這個型別的具體成員,暫不去管。先記著,看我們會遇到哪些內容。
612 初始化了一個控制成員變數。
613-615 初始化雜湊函式,初始化函式,釋放函式(C++中的解構函式)。
616 把skb_free給置空。為什麼?或許ip4_frags永遠都不是真正擁有sk_buff,所以就不可去釋放它。
617 ip4_frags維護了一個佇列,這個佇列的單元長度被賦心struct ipq的位元組長度。一個典型的生產者消費者模式。我理解的這裡的佇列,既可能是接收的佇列,也可能是傳送的佇列。
618 一個匹配函式。什麼時候會執行呢?暫時我也不知道。
619 設定一個超時處理函式。函式頭部的註釋中寫著,如果超時了要清空整個隊列了。這個會在什麼情況下發生呢?IP協議告訴我們,IP分片發生在傳送端,也可能是中間的路由器上。但分片重灌只會發生在目的主機上。當目的主機上的IP分片接收佇列中,有一個分片丟失了,這個時候,由於IP協議本身沒有重傳機制,只能通過額外的機制,來觸發清空整個分片接收佇列,來進行重新接收。
620 針對inet層對ip4_frags進一步的初始化。這個函式只說明下它的功能,不再列原始碼。初始化ip4_frags的散列表,雜湊隨機數,快取計數,初始化重建定時器。
從ipgfrag_init中返回。看到了最後一個函式
1447 dev_add_pack(&ip_packet_type);
至此我們的IP層和裝置關聯起來了,以後網絡卡接到的IP分組的資料就會發給IP協議了。先看下傳入的引數ip_packet_type,定義在af_net.c中。
1348 static struct packet_type ip_packet_type = {
1349 .type = __constant_htons(ETH_P_IP),
1350 .func = ip_rcv,
1351 .gso_send_check = inet_gso_send_check,
1352 .gso_segment = inet_gso_segment,
1353 };

這裡重點關注ip_rcv的成員函式。對,它就是IP分組資料進入IP層的入口函式。其他成員先不看,ip_rcv的光環太耀眼了。而dev_add_pack,之前有遇到過,只是把ip_packet_type掛在了ptype_base的全域性列表裡。
至此協議棧的初始化完成了,可以工作了,剛好11篇,真是個好數字。隨後的一篇中,我會把整個流程再梳理一下,把關係圖完善下。之後,開始協議棧工作之旅了:)

相關推薦

TCP/IP協議初始完結-完成IP連線

上回ICMP的插曲說完了,把一個ICMP socket的建立流程說完了。對於資料結構關係圖沒有加入什麼新元素。執行的流程是從inet_family_ops到inet_create,raw_prot,這樣的執行順序。此時完成的只是ICMP協議的處理socket。繼

SQL Server 2017 AlwaysOn AG 自動初始

自動 進行 備份 情況下 耗時 server serve 使用 日誌 何時不使用自動種子設定在某些情況下,自動種子設定可能不是初始化次要副本的最優選擇。 自動種子設定過程中,SQL Server 通過網絡執行備份以進行初始化。 如果數據庫非常大或者次要副本是遠程副本,此過程

TCP/IP協議初始流程

let's start from bottom up :)有的時候用英語說話比漢語要簡潔和有意思一點:)     一個lance得到資料以後總會這樣處理: skb = dev_alloc_skb (....); skb->protocol = eth_type_trans(skb, dev); ....

SQL Server 2017 AlwaysOn AG 自動初始

class 無法 增加 tle 完整 之前 join 截斷 51cto 何時不使用自動種子設定在某些情況下,自動種子設定可能不是初始化次要副本的最優選擇。 自動種子設定過程中,SQL Server 通過網絡執行備份以進行初始化。 如果數據庫非常大或者次要副本是遠程副本,此過

SQL Server 2017 AlwaysOn AG 自動初始

strong 恢復 種子設定 子網 通過 width SQ 對比 備份 性能測試對比分析拿xx庫來做測試,數據文件8G,備份後為600M:測試場景使用時間1通過備份恢復來創建,開啟備份壓縮1分29秒2通過自動種子設定,開啟備份壓縮1分22秒3通過自動種子設定,開啟備份壓縮,

節課: 第九章,繫結sshd服務

8.4、服務的訪問控制列表         TCPwrappers是RHEL7中預設啟用的流量監控程式,能夠對服務做出允許或拒絕。         TCPwrappers服務由兩個檔案控制:     &n

TCP/IP實現 UDP使用者資料報協議

一.已連線UDP       我們可以對UDP套接字呼叫connect進行連線,但與TCP連線的差別很大。UDP進行連線並不進行三次握手,核心只是核心只是檢查一些立即可知的錯誤(如一個顯然不可達的目的地),並將對端的IP地址和埠號記錄在PCB協議控制塊中,之後立即返

學習Linux-4.12核心網路協議1.7——網路裝置的初始struct net_device

在linux的網路裝置裡,其中一個最關鍵的結構體應該要算net_device了,它由對應的網路裝置驅動進行建立和初始化,服務於核心網路子系統。 1. struct net_device 註釋分析 struct net_device這個結構體比較大,在瞭解它之前,我們先看一下

linux tcp ip協議學習路線圖1

即將開啟tcp/ip協議棧的學習,本篇部落格主要是提供接下來即將分析的協議棧相應的文章目錄。1. tcp/ip協議棧的資料結構,詳見:點選開啟連結2. inet_init()初始化,詳見:點選開啟連結3. socket()通訊流程基於TCP(面向連線)的socket程式設計,

Linux TCP/IP 協議原始碼分析

---------------------------------------------------------------------------------------------------------------------         這篇文章寫於三年前,當時

linux初始文件

fun ps1 史記 intern header 例如 internet $path 名稱 前面寫了很多linux的知識,其實很多都是命令的,所以要去多多的練習才能學的更好,加油為了好工作。 要麽現在懶惰,未來討飯。要麽現在努力,未來愜意。 一、初始化文件概述   1

linux初始檔案

前面寫了很多linux的知識,其實很多都是命令的,所以要去多多的練習才能學的更好,加油為了好工作。 要麼現在懶惰,未來討飯。要麼現在努力,未來愜意。 一、初始化檔案概述   1.1、概述   系統初始化檔案是給系統做配置資訊的,最重要的系統資訊是環境變數的配置。   初始化

趣談網路協議基於XML的SOAP協議

傳輸協議 (1)基於XML的最著名的通訊協議就是SOAP協議,全稱簡單物件訪問協議。它使用XML編寫簡單的請求和回覆訊息,並用HTTP協議進行傳輸 (2)SOAP將請求和回覆放在一個信封裡,就像傳遞一個郵件一樣。信封裡面的信分擡頭和正文 協議約定 Web服務描述語言

C++11 帶來的新特性 2—— 統一初始Uniform Initialization

1 統一初始化(Uniform Initialization) 在C++ 11之前,所有物件的初始化方式是不同的,經常讓寫程式碼的我們感到困惑。C++ 11努力創造一個統一的初始化方式。 其語法是使用{}和std::initializer_list ,先看示例。 int values[

神經網路之權重初始附程式碼

摘要 神經網路/深度學習模型訓練的過程本質是對權重進行更新,在對一個新的模型進行訓練之前,需要每個引數有相應的初始值。對於多層神經網路/深度學習而言,如何選擇引數初始值便成為一個值得探討的問題。本文從實現啟用值的穩定分佈角度來探討神經網路的效率優化問題 權重在

IOC容器初始原始碼解讀

一、過程(資源定位,Bean的載入,解析,以及註冊) 第一個過程是Resource資源定位。這個Resouce指的是BeanDefinition的資源定位。這個過程就是容器找資料的過程,就像水桶裝水需要先找到水一樣 第二個過程是BeanDefinition的

http協議基礎httphttps

一、http的缺點 之前有介紹過http協議相關的一些知識,http是相當優秀和方便的,但它也有缺點,主要不足表現在如下幾個方面: △ 通訊使用明文(不加密),內容可能會被竊聽 △ 不驗證通訊方的身份,因此可能遭遇偽裝 △ 無法證明報文的完整性,所以有可能已被篡改 其他未加密的協議也存在這類問題

C++類的靜態成員變數一定要初始分配記憶體

文章轉載自https://my.oschina.net/u/1537391/blog/219432 我們知道C++類的靜態成員變數是需要初始化的,但為什麼要初始化呢。其實這句話“靜態成員變數是需要初始化的”是有一定問題的,應該說“靜態成員變數需要定義”才是準確的,而不是初始化

cocos creatorhttp協議

1、http協議簡單使用 1、http協議的簡單使用 var express=require('express'); var app=express(); app.get('/index',function(req,res){      var arg=req.query;

Spring Security技術開發企業級認證授權開發簡訊驗證碼登入

簡訊登入也是一種常見的登入方式,但是簡訊登入的方式並沒有整合到Spring Security中,所以往往還需要我們自己開發簡訊登入邏輯,將其整合到Spring Security中,使用Spring Security來進行校驗。本文將介紹開發簡訊登入的方法,