socket相关的开机初始化分析
针对内核3.9
系统开启时,会使用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里然后之后一个一个的进行处理。代码为:
286 #define core_initcall(fn) module_init(fn)
297 #define module_init(initfn)
298 static inline initcall_t __inittest(void)
299 { return initfn; }
300 int init_module(void) __attribute__((alias(#initfn)));
Sock_init的过程在2.6和3.9的内核中变化较大,代码如下:
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等函数的先决条件。其中涉及文件系统,暂不讨论。
以上便是socket的初始化过程
socket相关的开机初始化分析的更多相关文章
- Linux学习-Linux 的开机流程分析
开机流程一览 系统开机的经过可以汇整成底下的流程的: 加载 BIOS 的硬件信息与进行自我测试,并依据设定取得第一个可开机的装置; 读取并执行第一个开机装置内 MBR 的 boot Loader (亦 ...
- Linux内核启动代码分析二之开发板相关驱动程序加载分析
Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c start_ke ...
- TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现
题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术 轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.com linu ...
- socket相关系统调用的调用流程
最近一直在读内核网络协议栈源码,这里以ipv4/tcp为例对socket相关系统调用的流程做一个简要整理,这些相关系统调用的内部细节虽然各有不同,但其调用流程则基本一致: 调用流程: (1)系统调用 ...
- sparkContext之一:sparkContext的初始化分析
Spark源码学习:sparkContext的初始化分析 spark可以运行在本地模式local下,可以运行在yarn和standalone模式下,但是本地程序是通过什么渠道和这些集群交互的呢?那就是 ...
- 一只简单的网络爬虫(基于linux C/C++)————socket相关及HTTP
socket相关 建立连接 网络通信中少不了socket,该爬虫没有使用现成的一些库,而是自己封装了socket的相关操作,因为爬虫属于客户端,建立套接字和发起连接都封装在build_connect中 ...
- libevent (一) socket属性设置与初始化操作
socket属性设置与初始化操作 libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,内部使用select.epoll.kqueue等系统调用管理事件机制.著名 ...
- List 接口以及实现类和相关类源码分析
List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...
- JobTracker等相关功能模块初始化
[Hadoop代码笔记]Hadoop作业提交之JobTracker等相关功能模块初始化 一.概要描述 本文重点描述在JobTracker一端接收作业.调度作业等几个模块的初始化工作.想过模块的介绍会在 ...
随机推荐
- MongoDB 学习(三)MongoDB 和 Spring 整合(Maven)
一.MongoDB 和 Spring 整合(Maven) 1.相关 jar 包准备 2.用 Maven 创建项目,pom.xml 文件 <project xmlns="http://m ...
- enter键触发事件
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- DB DBS 和DBMS区别
DB:是指datebase(数据库) DBS:是指datebase systerm (数据库系统) DBMS:是指datebase mangement systerm(数据库管理系统)区别:数据库 ...
- 孙鑫VC++视频教程(1-20课全)
孙鑫VC++视频教程(1-20课全)PPT讲义和源代码 http://down.51cto.com/data/467760 孙鑫VC++从入门到精通开发详解视频教程[20讲] http://down. ...
- Android热修复 Dex注入实现静默消灭bug
当app上线后发现紧急bug,如果重新发布版本周期比较长,并且对用户体验不好,此时热修复就派上用场了.热修复就是为紧急bug而生,能够快速修复bug,并且用户无感知.针对热修复,阿里系先后推出AndF ...
- 如何优雅地使用Markdown (Sublime 3 + MarkdownEditing+OmniMarkupPreviewer)
最近开始上手Sublime 3 作为Markdown 的重度使用者自然关于Markdown的插件是必不可少的 . 在这里记录分享一下我常用的两款Markdown插件. MarkdownEditing ...
- CSS居中问题:块级元素和行级元素在水平方向以及垂直方向的居中问题
元素的居中问题是每个初学者碰到的第一个大问题,在此我总结了下各种块级 行级 水平 垂直 的居中方法,并尽量给出代码实例. 首先请先明白块级元素和行级元素的区别 块级元素 块级元素水平居中 1:marg ...
- flask框架下的jinja2模板引擎(1)(模板渲染)
#转载请留言联系 模板是什么? 在 flask 框架中,视图函数有两个作用:处理业务逻辑和返回响应内容.在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本.模板作用即是承担视图函 ...
- swoole 创建UDP服务器
udp_server.php <?php // 创建Server对象,监听 127.0.0.1:9502端口,类型为SWOOLE_SOCK_UDP $serv = new swoole_serv ...
- [转] RISC-V架构介绍
1. RISC-V和其他开放架构有何不同 如果仅从"免费"或"开放"这两点来评判,RISC-V架构并不是第一个做到免费或开放的处理器架构. 在开始之前,我们先通 ...