一、注册时机
1、在内核初始化时完成;2、内核初始化过程(init/main.c): kernel_init()->do_basic_setup()->do_initcalls()->do_one_initcall() ;
3、socket文件系统注册过程(net/socket.c): core_initcall(sock_init) ;
1) core_initcall宏定义如下:
- #define core_initcall(fn) __define_initcall("1",fn,1)
- #define __define_initcall(level,fn,id) \
- static initcall_t __initcall_##fn##id __used \
- __attribute__((__section__(".initcall" level ".init"))) = fn
根据上面的解释,core_initcall(sock_init)的作用就是让编译器在编译时声明函数指针变量__initcallsock_init1,让其指向sock_init,并放到名为".initcall1.init"的section中;
二、socket文件系统注册
1、socket文件系统类型
- static struct file_system_type sock_fs_type = {
- .name = "sockfs",
- .get_sb = sockfs_get_sb,
- .kill_sb = kill_anon_super,
- };
2、sock_init主要逻辑
函数的主要代码如下:
- static int __init sock_init(void){
- init_inodecache();
- register_filesystem(&sock_fs_type);
- sock_mnt = kern_mount(&sock_fs_type);
- return 0;
- }
2) register_filesystem() :将socket文件系统注册到内核中;
在内核中,所有的文件系统保存在全局变量file_systems中,如下:
static struct file_system_type *file_systems;
不同的文件系统类型通过结构体的next字段形成一个单向链表;
这样,注册文件系统实质是将新的结构体插入到单向链表中的过程;
3) kern_mount() :在内核中安装文件系统,并建立安装点;
在安装的过程中,会初始化该安装点的超级块,此时会将该超级块的操作函数指针记录下来;如:
- static int sockfs_get_sb(struct file_system_type *fs_type,
- int flags, const char *dev_name, void *data,
- struct vfsmount *mnt)
- {
- return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC,
- mnt);
- }
- static struct super_operations sockfs_ops = {
- .alloc_inode = sock_alloc_inode,
- .destroy_inode =sock_destroy_inode,
- .statfs = simple_statfs,
- };