linux內核中網絡文件系統的註冊初始化

針對內核3.9node

系統開啓時,會使用init/main.c,而後再裏面調用kernel_init(),在裏面會再調用do_basic_setup(),調用do_initcalls(),調用do_one_initcall(),這個函數會去把註冊了全部須要初始化的系統調用一一初始化。而網絡模塊因爲所有都是基於socket在進行,因此,相關網絡模塊,在do_one_initcall()中會經過core_init()調用sock_init()來把網絡文件系統登記在整個linux的文件系統中。其中core_init()很是重要,負責在內核初始化階段把這些須要初始化的函數集中放在一個section裏而後以後一個一個的進行處理。代碼爲:linux

286 #define core_initcall(fn)               module_init(fn)緩存

297 #define module_init(initfn)                                     網絡

298         static inline initcall_t __inittest(void)               數據結構

299         { return initfn; }                                      electron

300         int init_module(void) __attribute__((alias(#initfn)));socket

Sock_init的過程在2.63.9的內核中變化較大,代碼以下:ide

 static int __init sock_init(void)函數

2602 {學習

2603         int err;

2604         /*

2605          *      Initialize the network sysctl infrastructure.

2606          */

2607         err = net_sysctl_init();

2608         if (err)

2609                 goto out;

2610 

2611         /*

2612          *      Initialize skbuff SLAB cache

2613          */

2614         skb_init();

2615 

2616         /*

2617          *      Initialize the protocols module.

2618          */

2619 

2620         init_inodecache();

2621 

2622         err = register_filesystem(&sock_fs_type);

2623         if (err)

2624                 goto out_fs;

2625         sock_mnt = kern_mount(&sock_fs_type);

2626         if (IS_ERR(sock_mnt)) {

2627                 err = PTR_ERR(sock_mnt);

2628                 goto out_mount;

2629         }

而後一句一句地進行分析,咱們知道sysctl設置和顯示在/proc/sys目錄中的內核參數.能用sysctl來設置或從新設置連網功能,如IP轉發、IP碎片去除及源路由檢查等。2607行調用net_sysctl_init()來對其進行初始化,咱們來看怎麼初始化的。

 83 static struct ctl_table_header *net_header;

 84 __init int net_sysctl_init(void)

 85 {

 86         static struct ctl_table empty[1];

 87         int ret = -ENOMEM;

 92         net_header = register_sysctl("net", empty);

 93         if (!net_header)

 94                 goto out;

 95         ret = register_pernet_subsys(&sysctl_pernet_ops);

 96         if (ret)

 97                 goto out;

 98         register_sysctl_root(&net_sysctl_root);

 99 out:

100         return ret;

101 }

首先調用register_sysctl()進行把新的sysctl註冊到ctl表中去,而後調用register_pernet_subsys()利用超級塊操做表註冊塊設備表(此處因爲我尚未學習過文件系統因此沒懂),最後調用register_sysctl_root(),這個函數實際上什麼都沒有,官方給的註釋是爲了不侷限性把這個系統所在位置註冊爲空,說實話,沒怎麼懂,還望指教。

回到sock_init(void)中,skb_init()是爲了初始化slab,不關心。而後是init_inodecache(),這個函數負責對inode進行處理,大概是要建立一塊用於socket相關的inode的調整緩存,以方便以後對inode進行建立和釋放。

而後是 register_filesystem(struct file_system_type * fs),負責socket文件系統註冊到內核中。代碼以下:

 69 int register_filesystem(struct file_system_type * fs)

 70 {

 71         int res = 0;

 72         struct file_system_type ** p;

 73 

 74         BUG_ON(strchr(fs->name, '.'));

 75         if (fs->next)

 76                 return -EBUSY;

 77         write_lock(&file_systems_lock);

 78         p = find_filesystem(fs->name, strlen(fs->name));

 79         if (*p)

 80                 res = -EBUSY;

 81         else

 82                 *p = fs;

 83         write_unlock(&file_systems_lock);

 84         return res;

 85 }

能夠看到這裏其實是把一個新的文件系統註冊到file_system_type這個全局變量的鏈表裏,這裏涉及到file_system_type這個數據結構,其中核心部分以下:

1802 struct file_system_type {

1803         const char *name;

1804         int fs_flags;

1811         struct dentry *(*mount) (struct file_system_type *, int,

1812                        const char *, void *);

1813         void (*kill_sb) (struct super_block *);

1814         struct module *owner;

1815         struct file_system_type * next;

1826 };

其中struct dentry *(*mount) (struct file_system_type *, int,const char *, void *);是一個函數指針(也能夠理解成鉤子函數),負責指明哪一個函數來處理,好比此處須要用到的sock_fs_type,就經過mount來規定使用sockfs_mount來進行註冊。

326 static struct file_system_type sock_fs_type = {

327         .name =         "sockfs",

328         .mount =        sockfs_mount,

329         .kill_sb =      kill_anon_super,

330 };

再回到sock_init(void)最後使用sock_mnt = kern_mount(&sock_fs_type);來把網絡文件系統安裝上。其實是調用vfs_kern_mount(),大概是在虛擬文件系統下進行內存分配之類的工做,沒看懂。

這裏有一個很是優美的地方,在最後調用kern_mount(&sock_fs_type)時,會利用到sock_fs_type數據結構裏的鉤子函數sockfs_mount,而後繼續調用mount_pseudo()執行實際上的安裝,該函數是與文件系統相關的,是後面能執行socket等函數的先決條件。其中涉及文件系統,暫不討論。

相關文章
相關標籤/搜索