1、普通的根文件系统存放在flash中的某个分区
因此需要告知内核根文件系统存放在哪个分区中,同时需要知道根文件系统的rootfstype类型。见
mount挂载分析_sydyh43的博客-CSDN博客
2、设备启动阶段,在内核加载最后阶段,需要挂载根文件系统,然后访问根文件系统中的第一个用户进程init
3、挂载函数流程
//init/main.c
start_kernel
rest_init
kernel_init //kernel_thread(kernel_init, NULL, CLONE_FS);
kernel_init_freeable
prepare_namespace
prepare_namespace函数中实现挂载前的准备,解析第1点介绍的分区和rootfstype内容
void __init prepare_namespace(void)
{
......
if (saved_root_name[0]) {
root_device_name = saved_root_name;
if (!strncmp(root_device_name, "mtd", 3) ||
!strncmp(root_device_name, "ubi", 3)) {
mount_block_root(root_device_name, root_mountflags);
goto out;
}
ROOT_DEV = name_to_dev_t(root_device_name); //这步很关键,解析/dev/mtdblock2的主次设备号,存入ROOT_DEV。可以printk("device %u:%u.\n", MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
if (strncmp(root_device_name, "/dev/", 5) == 0)
root_device_name += 5;
}
......
mount_root();
out:
devtmpfs_mount("dev");
sys_mount(".", "/", NULL, MS_MOVE, NULL);
sys_chroot(".");
}
其中saved_root_name变量从环境变量cmdline中解析获取,cat /proc/cmdline查看
static int __init root_dev_setup(char *line)
{
strlcpy(saved_root_name, line, sizeof(saved_root_name));
return 1;
}
__setup("root=", root_dev_setup);
通过__setup函数解析出cmdline中”root=“后的字符串,即saved_root_name=/dev/mtdblock2。rootfstype获取的值也类似。
void __init mount_root(void)
{
......
#ifdef CONFIG_BLOCK
{
int err = create_dev("/dev/root", ROOT_DEV);
if (err < 0)
pr_emerg("Failed to create /dev/root: %d\n", err);
mount_block_root("/dev/root", root_mountflags);
}
#endif
}
继续流程
prepare_namespace
mount_root
mount_block_root
do_mount_root
sys_mount //sys_mount(name, "/root", fs, flags, data);
//sys_mount入参定义
asmlinkage long sys_mount(char __user *dev_name, char __user *dir_name,
char __user *type, unsigned long flags,
void __user *data);
最终就是把/dev/root设备以squashfs文件系统格式挂载到/root目录下。
从设备中可以看出/dev/root软链接到/dev/mtdblock2,就是flash中的rootfs分区