switch_root 命令¶
在之前讨论过的,当内核初始化完成后会在 initramfs 根目录下查找 init 脚本,这个脚本将会依次执行initramfs根目录下的 hook 中脚本对应函数,这块详细流程已经在 [init脚本] 中说明,这里做一下过程小结(从Linux内核被引导完成开始说起):
当内核引导完成,此时内核解压缩initramfs,并在其根文件系统中找到
init脚本,并运行它。init脚本首先在initramfs文件系统中挂载内核虚拟文件系统
proc、sys、dev,并设置 dev/ 下软连接init脚本接下来会解析命令行参数,这个命令行参数是由引导器从linux内核传入的,根据参数设置指定参数
init脚本根据内核参数禁用一些Hook脚本
init脚本执行initramfs根目录hook文件夹中脚本的
run_earlyhook函数init脚本根据配置加载指定模块
init脚本执行initramfs根目录hook文件夹中脚本的
run_hook函数init脚本开始获取实际文件系统所在的设备UUID
init脚本调用 fsck 检查实际根文件系统是否有损坏,有则修复(这个过程不是必须的,如果内核传入参数希望快速启动则忽略此过程)
init脚本挂载实际根文件系统到 initramfs 中的
/new_rootinit脚本执行initramfs根目录hook文件夹中脚本的
run_latehook函数init脚本执行initramfs根目录hook文件夹中脚本的
run_cleanuphook函数init脚本检测实际根文件系统是否正常挂载到
/new_root下init脚本开始执行
switch_root命令,将根文件系统切换到实际根文件系统,并删除initramfs中的根文件系统。
switch_root 程序¶
switch_root 是一个二进制文件,其接收三个命令行参数,分别是:
根文件系统路径
init程序
命令行其它参数
switch_root 命令来自于 util-linux 软件包,具体功能如下:
从initramfs中卸载内核虚拟文件系统
proc、dev、sys在新的根目录中挂载内核虚拟文件系统
proc、dev、sys运行
chdir(newroot)将运行时路径切换到新的根文件系统中调用
mount(newroot, "/", NULL, MS_MOVE, NULL)将旧的根切到新的根中执行
chroot (".")和chdir("/")完成根目录切换调用
fork(),在子程序中判断以前旧的根目录是否是initramfs,如果使得话就删除掉就的文件系统,执行完后子进程退出。检查传入
switch_root中的 init 程序是否存在且可执行(现代系统中这个命令是指向systemd的软连接),可以执行则调用execv执行它,并把传入的命令行参数传入到 init 程序中。
至此,整个系统控制权完全交到了 init 进程中。