Linux内核深度解析
上QQ阅读APP看书,第一时间看更新

1.3.2 C语言部分

内核初始化的C语言部分入口是函数start_kernel,函数start_kernel首先初始化基础设施,即初始化内核的各个子系统,然后调用函数rest_init。函数rest_init的执行流程如下。

(1)创建1号线程,即init线程,线程函数是kernel_init。

(2)创建2号线程,即kthreadd线程,负责创建内核线程。

(3)0号线程最终变成空闲线程。


init线程继续初始化,执行的主要操作如下。

(1)smp_prepare_cpus():在启动从处理器以前执行准备工作。

(2)do_pre_smp_initcalls():执行必须在初始化SMP系统以前执行的早期初始化,即使用宏early_initcall注册的初始化函数。

(3)smp_init():初始化SMP系统,启动所有从处理器。

(4)do_initcalls():执行级别0~7的初始化。

(5)打开控制台的字符设备文件“/dev/console”,文件描述符0、1和2分别是标准输入、标准输出和标准错误,都是控制台的字符设备文件。

(6)prepare_namespace():挂载根文件系统,后面装载init程序时需要从存储设备上的文件系统中读文件。

(7)free_initmem():释放初始化代码和数据占用的内存。

(8)装载init程序(U-Boot程序可以传递内核参数“init=”以指定init程序),从内核线程转换成用户空间的init进程。

级别0~7的初始化,是指使用以下宏注册的初始化函数:

    include/linux/init.h
    #define pure_initcall(fn)            __define_initcall(fn, 0)
    #define core_initcall(fn)            __define_initcall(fn, 1)
    #define core_initcall_sync(fn)      __define_initcall(fn, 1s)
    #define postcore_initcall(fn)       __define_initcall(fn, 2)
    #define postcore_initcall_sync(fn)  __define_initcall(fn, 2s)
    #define arch_initcall(fn)            __define_initcall(fn, 3)
    #define arch_initcall_sync(fn)      __define_initcall(fn, 3s)
    #define subsys_initcall(fn)         __define_initcall(fn, 4)
    #define subsys_initcall_sync(fn)    __define_initcall(fn, 4s)
    #define fs_initcall(fn)              __define_initcall(fn, 5)
    #define fs_initcall_sync(fn)        __define_initcall(fn, 5s)
    #define rootfs_initcall(fn)         __define_initcall(fn, rootfs)
    #define device_initcall(fn)         __define_initcall(fn, 6)
    #define device_initcall_sync(fn)    __define_initcall(fn, 6s)
    #define late_initcall(fn)            __define_initcall(fn, 7)
    #define late_initcall_sync(fn)      __define_initcall(fn, 7s)