说一下Linux操作系统的启动过程
BIOS 时期(Basic Input and Output System,基本输入输出系统)
- 插电, 重置 CS 为 0xFFFF , IP 为 0x0000, 对应 BIOS 程序
- 0xF0000-0xFFFFF 映射到 BIOS 程序(存储在ROM中), BIOS 做以下三件事:
- 检查硬件
- 提供基本输入(中断向量表和中断服务程序)输出(显存映射)服务
bootloader 时期
- BIOS界面点启动盘选项
- 加载 MBR(Master Boot Record,主引导记录 / 扇区)到内存(0x7c00)
- MRB: 启动盘第一个扇区(512B, 由 Grub2 写入 boot.img 镜像)
- boot.img (引导)加载 Grub2 的 core.img 镜像
- core.img (内存)包括 diskroot.img, lzma_decompress.img, kernel.img 以及其他模块
- boot.img 先加载运行 diskroot.img, 再由 diskroot.img 加载 core.img 的其他内容
- diskroot.img 解压运行 lzma_compress.img, 由lzma_compress.img 切换到保护模式
从实模式切换到保护模式
- 切换到保护模式需要做以下三件事:
- 启用分段, 辅助进程管理
(注:就是在内存里面建立段描述符表,将寄存器里面的段寄存器变成段选择子,指向某个段描述符,这样就能实现不同进程的切换了。) - 启动分页, 辅助内存管理
(注:将内存分成相等大小的块) - 打开其他地址线
- lzma_compress.img 解压运行 grub 内核 kernel.img, kernel.img 做以下四件事:
- 解析 grub.conf 文件
- 选择操作系统
- 例如选择 linux16, 会先读取内核头部数据进行检查, 检查通过后加载完整系统内核
- 启动系统内核。
内核启动流程图
内核初始化
- 创建样板进程,及各个模块初始化
- 创建第一个进程, 0号进程.
set_task_stack_end_magic(&init_task) and struct task_struct init_task = INIT_TASK(init_task) - 初始化中断,
trap_init() 设置很多中断门. 系统调用是通过发送中断进行 - 初始化内存管理模块,
mm_init() - 初始化进程调度模块,
sched_init() - 初始化基于内存的文件系统 rootfs,在VFS 虚拟文件系统里注册一种类型
(注:VFS(虚拟文件系统)将各种文件系统抽象成统一接口) - 调用
rest_init() 完成其他初始化工作
rest_init()做的其他工作如下
-
创建管理/创建用户态进程的进程, 1号进程
rest_init() 创建 1号进程(工作在用户态).- 权限管理
- x86 提供 4个 Ring 分层权限
- 操作系统利用: Ring0-内核态(访问核心资源); Ring3-用户态(普通程序)
- 用户态调用系统调用: 用户态-系统调用-保存寄存器-内核态执行系统调用-恢复寄存器-返回用户态
- 新进程执行 kernel_init 函数, 先运行 ramdisk 的 /init 程序(位于内存中)
- 首先加载 ELF(可执行与可链接格式) 文件
- 设置用于保存用户态寄存器的结构体
- 返回进入用户态
- 根文件系统的/init 加载存储设备的驱动
(注:基于内存的文件系统。内存访问是不需要驱动的,省空间,这个就是 ramdisk。) - kernel_init 函数启动存储设备文件系统上的 init,形成了用户态所有进程的祖先。
-
创建管理/创建内核态进程的进程, 2号进程
rest_init() 通过创建 2号进程(工作在内核态)负责所有内核态线程的调度和管理
内核初始化流程图
|