针对内核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相关的开机初始化分析的更多相关文章

  1. Linux学习-Linux 的开机流程分析

    开机流程一览 系统开机的经过可以汇整成底下的流程的: 加载 BIOS 的硬件信息与进行自我测试,并依据设定取得第一个可开机的装置; 读取并执行第一个开机装置内 MBR 的 boot Loader (亦 ...

  2. Linux内核启动代码分析二之开发板相关驱动程序加载分析

    Linux内核启动代码分析二之开发板相关驱动程序加载分析 1 从linux开始启动的函数start_kernel开始分析,该函数位于linux-2.6.22/init/main.c  start_ke ...

  3. TCP/IP协议栈源码图解分析系列10:linux内核协议栈中对于socket相关API的实现

    题记:本系列文章的目的是抛开书本从Linux内核源代码的角度详细分析TCP/IP协议栈内核相关技术 轻松搞定TCP/IP协议栈,原创文章欢迎交流, byhankswang@gmail.com linu ...

  4. socket相关系统调用的调用流程

    最近一直在读内核网络协议栈源码,这里以ipv4/tcp为例对socket相关系统调用的流程做一个简要整理,这些相关系统调用的内部细节虽然各有不同,但其调用流程则基本一致: 调用流程: (1)系统调用 ...

  5. sparkContext之一:sparkContext的初始化分析

    Spark源码学习:sparkContext的初始化分析 spark可以运行在本地模式local下,可以运行在yarn和standalone模式下,但是本地程序是通过什么渠道和这些集群交互的呢?那就是 ...

  6. 一只简单的网络爬虫(基于linux C/C++)————socket相关及HTTP

    socket相关 建立连接 网络通信中少不了socket,该爬虫没有使用现成的一些库,而是自己封装了socket的相关操作,因为爬虫属于客户端,建立套接字和发起连接都封装在build_connect中 ...

  7. libevent (一) socket属性设置与初始化操作

    socket属性设置与初始化操作 libevent是一个事件触发的网络库,适用于windows.linux.bsd等多种平台,内部使用select.epoll.kqueue等系统调用管理事件机制.著名 ...

  8. List 接口以及实现类和相关类源码分析

    List 接口以及实现类和相关类源码分析 List接口分析 接口描述 用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除( ...

  9. JobTracker等相关功能模块初始化

    [Hadoop代码笔记]Hadoop作业提交之JobTracker等相关功能模块初始化 一.概要描述 本文重点描述在JobTracker一端接收作业.调度作业等几个模块的初始化工作.想过模块的介绍会在 ...

随机推荐

  1. java_对象序列化、反序列化

    1.概念 序列化:将对象转化为字节序列的过程 反序列化:将字节序列转化为对象的过程 用途: A:将对象转化为字节序列保存在硬盘上,如文件中,如文本中的例子就是将person对象序列化成字节序列,存在p ...

  2. JavaWeb之JSP原理

    1.为什么需要JSP? 在很多动态网页中,绝大部分内容都是固定不变的,只有局部内容需要动态产生和改变.如果使用Servlet程序来输出只有局部内容需要改动的网页,其中所有的静态内容也需要程序员用jav ...

  3. SQL常用函数总结

    SQL常用函数总结 这是我在项目开发中使用db2数据库写存储过程的时候经常用到的sql函数.希望对大家有所帮助: sql cast函数 (1).CAST()函数的参数是一个表达式,它包括用AS关键字分 ...

  4. linux 忘记密码

    密码保存在/etc/shadow文件中 1. root 密码忘记了 1.1 重启进入单人维护模式后, 系统会主动给予root权限的bash接口, 此时再以passwd修改密码即可: 1.2 以Live ...

  5. cf449D. Jzzhu and Numbers(容斥原理 高维前缀和)

    题意 题目链接 给出\(n\)个数,问任意选几个数,它们\(\&\)起来等于\(0\)的方案数 Sol 正解居然是容斥原理Orz,然而本蒟蒻完全想不到.. 考虑每一种方案 答案=任意一种方案 ...

  6. 01_微信小程序支付

    [支付流程] 1.小程序内调用登录接口,获取到用户的openid(我们这一步骤让前端去获取) 2.服务端代码这边生成订单 3.服务端调用支付统一下单的api 4.服务端将再次签名,返回5个参数(前端得 ...

  7. Android recyclerview删除item刷新列表

    删除item坑 mModels.remove(i); notifyItemRemoved(i); //必须调用这行代码 notifyItemRangeChanged(i, mModels.size() ...

  8. 【Python】安装配置Anaconda

    优点:解决Python 库依赖问题 清华安装镜像 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/

  9. Ganglia安装

    一.rrdtool安装 1.1 安装依赖包 由于rrdtool依赖的包比较多,而且包之间也存在依赖,故使用yum安装由于服务器无法联网,故使用iso文件创建本地yum源,方法见下: (1)创建iso存 ...

  10. 上传附件(图片base64)封装方法

    上传附件(图片base64)封装方法 php 上传附件,base64 项目中封装的接口: public function error($msg){ header("Content-type: ...