少于 1 分钟阅读 次阅读

概要:介绍 initcode.S 如何通过汇编压栈参数、设置系统调用号并触发中断来发起 exec 系统调用,以及 exec 成功/失败两个分支和 /init 接管后初始化用户环境的流程。

1. 触发机制与核心功能

initcode.S 的核心任务是触发 exec 系统调用。

  • 功能: exec 用新程序的代码和数据替换当前进程的内存与寄存器。
  • 状态保留: 替换过程中,进程的 文件描述符 (FD)进程 ID (PID) 以及 父进程 保持不变。

2. 汇编层面的调用准备 (initcode.S)

在指令级别,initcode.S 通过以下步骤手动构建系统调用环境:

  • 压栈参数:$argv (参数指针), $init (字符串 “/init”), 以及 $0 (用于对齐/结束) 依次推入栈中。
  • 设置寄存器: 将系统调用号 SYS_exec 存入 %eax 寄存器。
  • 触发中断: 执行 int T_SYSCALL 指令,陷入内核,告知内核运行 exec

参数说明: 系统调用最终指向名为 $init 的程序(即以空字符结尾的字符串 /init)。

3. 执行路径:成功与失败

exec 调用后会产生两个分支:

  • 成功路径: exec 不会返回。它直接跳转并运行 /init 程序的二进制代码,替换掉原有的 initcode
  • 失败路径: 如果 exec 因某种原因失败并返回,initcode 将进入一个无限循环,不断调用 exit 系统调用。

4. /init 进程接管与系统建立

一旦 /init 成功运行,它将负责初始化用户环境:

  1. 创建设备文件: 在需要时创建控制台设备文件(console node)。
  2. 设置标准流: 依次打开该设备,占据文件描述符 0 (stdin)1 (stdout)2 (stderr)
  3. 主循环逻辑:
    • 开启一个控制台 Shell
    • 持续回收(wait)没有父进程的僵尸进程
    • 若 Shell 退出,则重新开启。

留下评论