作者: zjujoe 转载请注明出处
Email:[email protected]
BLOG:http://blog.csdn.net/zjujoe
Linux 启动时, 我们通过 root 参数提供根设备的名字。可以是符号名,比如
/dev/tbml3, 也可以是主设备号,比如139:3。 那么,内核是如何根据这些信息
去安装根设备的呢? 让我们简单研究一下。
内核启动过程中会调用 Init() 函数, Init() 函数 会调用
prepare_namespace(), 其会调用name_to_dev_t()得到主次设备号。 如果
root 参数是数字,则直接解析。 如果是/dev/*, 则会调用 try_name 使用
sysfs来解析!当然, name_to_dev_t() 首先会调用:
145 int mkdir_err = sys_mkdir("/sys", 0700);
146 if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0)
147 goto out;
来安装 sysfs 文件系统。
try_name首先判断是不是存在/sys/block/*/dev(比如/sys/block/tbml3/dev),
如果存在, 则直接打开这个设备文件取得主次设备号。
有些设备名比较复杂,比如, /dev/hda/3 则会读取 /sys/block/*/range 文件,
然后根据父设备的设备号及分区号,组合出主次设备号。
TIP: 嵌入式Linux可以把mount sysfs以及从符号名到数字名的过程优化掉,
直接使用数字名作为root参数, 比如 root=139:3
得到主次设备号后会调用 mount_root, 该函数会调用
mount_block_root("/dev/root", root_mountflags);
安装根分区。
mount_block_root 首先调用 get_fs_names 得到根文件系统的类型(通常由
rootfstype=来指定), 然后调用 do_mount_root, 该函数会调用 sys_mount 完
成任务:
int err = sys_mount(name, "/root", fs, flags, data);
这个函数大家都很熟悉了。这里 name 为 /dev/root。
回到函数 prepare_namespace, 将根文件系统 mount 到 /root 后以后,会调
用 chroot 将根目录切换到 /root 目录, 使其根文件系统变成真正的根。而原
来的根只是一个虚拟的内存根。内核在这个根下手工创建了 /dev /sysfs /root
等目录用于安装真正的根。