内核的启动从入口函数 start_kernel() 开始。在 init/main.c 文件中,start_kernel 相当于内核的 main 函数。打开这个函数,你会发现,里面是各种各样初始化函数 XXXX_init。

image.png

初始化公司职能部门

进程管理子系统初始化 - 项目管理部门

  • 创建创始进程 (0号进程). fork.
  • 进程调度

系统调用子系统 - 办事大厅

设置中断门 (中断处理程序).

内存管理子系统 - 会议室管理系统

文件子系统 - 档案管理系统

VFS (Virtual File System)

其他初始化

初始化 1 号进程

大徒弟.

1 号进程对于操作系统来讲,有“划时代”的意义。因为它将运行一个用户进程,这意味着这个公司把一个老板独立完成的制度,变成了可以交付他人完成的制度。

x86 提供了分层的权限机制,把区域分成了四个 Ring,越往里权限越高,越往外权限越低:

image.png

将能够访问关键资源的代码放在 Ring0,我们称为内核态(Kernel Mode);将普通的程序代码放在 Ring3,我们称为用户态(User Mode)。

当一个用户态的程序运行到一半,要访问一个核心资源,例如访问网卡发一个网络包,就需要暂停当前的运行,调用系统调用,接下来就轮到内核中的代码运行了。

  • 首先,内核将从系统调用传过来的包,在网卡上排队,轮到的时候就发送。发送完了,系统调用就结束了,返回用户态,让暂停运行的程序接着运行。
  • 这个暂停怎么实现呢?其实就是把程序运行到一半的情况保存下来。

image.png

这个过程就是这样的:用户态 - 系统调用 - 保存寄存器 - 内核态执行系统调用 - 恢复寄存器 - 返回用户态,然后接着运行。

image.png

从内核态到用户态

ramdisk 的作用

我们开始运行 ramdisk 上的 /init。等它运行完了就已经在用户态了。/init 这个程序会先根据存储系统的类型加载驱动,有了驱动就可以设置真正的根文件系统了。有了真正的根文件系统,ramdisk 上的 /init 会启动文件系统上的 init。

创建 2 号进程

内核线程调度

总结

image.png