How does the linux kernel finally mount the root file system
1, Past life and present life
In kernel_ Kernel will be called in init thread function_ init_ Freeable() function, in the kernel_init_ Prepare will be called in the freeable function_ The namespace () function mounts the root file system.
[it's a long way to go, mounting begins!!!]
2, kernel_init thread entry
kernel_ The init() function is as follows (/ init/main.c):
static int __ref kernel_init(void *unused) { int ret; kernel_init_freeable(); async_synchronize_full(); free_initmem(); mark_rodata_ro(); system_state = SYSTEM_RUNNING; numa_default_policy(); flush_delayed_fput(); if (ramdisk_execute_command) { ret = run_init_process(ramdisk_execute_command); if (!ret) return 0; pr_err("Failed to execute %s (error %d)\n", ramdisk_execute_command, ret); } if (execute_command) { ret = run_init_process(execute_command); if (!ret) return 0; panic("Requested init %s failed (error %d).", execute_command, ret); } if (!try_to_run_init_process("/sbin/init") || !try_to_run_init_process("/etc/init") || !try_to_run_init_process("/bin/init") || !try_to_run_init_process("/bin/sh")) return 0; panic("No working init found. Try passing init= option to kernel. " "See Linux Documentation/init.txt for guidance."); }
When the execution of line 5 of the above code is completed, the root file system is mounted successfully. The specific execution function is prepared_ The namespace () function is implemented. This function is analyzed below.
Lines 7-8 are used to release the memory allocated during the initialization function call, async_ synchronize_ The full() function is used to synchronize all asynchronous function calls. free_ The initmem() function is used to free the initialized memory space.
3, Heavy character - prepare_namespace
prepare_ The namespace function is defined in the (/ init/do_mounts.c) file as follows:
void __init prepare_namespace(void) { int is_floppy; if (root_delay) { printk(KERN_INFO "Waiting %d sec before mounting root device...\n", root_delay); ssleep(root_delay); } //Wait for the detection of known devices to complete wait_for_device_probe(); md_run_setup(); 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); if (strncmp(root_device_name, "/dev/", 5) == 0) root_device_name += 5; } if (initrd_load()) { goto out; } /* Wait for all asynchronous scan operations to complete */ if ((ROOT_DEV == 0) && root_wait) { printk(KERN_INFO "Waiting for root device %s...\n", saved_root_name); while (driver_probe_done() != 0 || (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0) msleep(100); async_synchronize_full(); } is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0; mount_root(); out: devtmpfs_mount("dev"); sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); }
The above code is essentially three program operation modes:
(1) [method 1]: if root_ device_ If name is the root device of mtd or ubi type, run mount_block_root() mounts the file system.
(2) [method 2]: call initrd_load() mounts the early root file system. If it is mount_ When initrd is true, the root file system mount operation will be performed. The linux kernel contains two mechanisms for mounting the early root file system. Initializing RAM disk (initrd) is an old-fashioned mechanism. Initramfs is a new mechanism for mounting early root file systems. The purpose of initrd and initramfs mechanisms: to execute early user space programs; Load some necessary device drivers before mounting the true (last) root file system.
(3) [method 3]: call mount_ The root () function mounts the file system. This mode is commonly used in the linux kernel. There are three file system mounting modes under this mode: 1. nfs. 2. Floppy mode. 3. block mode. In normal development, nfs is often used to mount the file system on the network for development and debugging.
In the above three ways, in the actual linux startup process, the linux kernel automatically selects one way to mount the root file system.
These three approaches are analyzed below:
[method 1] mount_ block_ The root () function will call do_mount_root() mounts the file system. As shown in the figure below:
[mode 2] file system mount in initrd mode.
[method 3]
For mode 3, mount is called_ The root() function mounts the root file system. The function is defined as follows (/ init/do_mounts.c):
void __init mount_root(void) { #ifdef CONFIG_ROOT_NFS if (ROOT_DEV == Root_NFS) { if (mount_nfs_root()) return; printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); ROOT_DEV = Root_FD0; } #endif #ifdef CONFIG_BLK_DEV_FD if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { /* rd_doload is 2 for a dual initrd/ramload setup */ if (rd_doload==2) { if (rd_load_disk(1)) { ROOT_DEV = Root_RAM1; root_device_name = NULL; } } else change_floppy("root floppy"); } #endif #ifdef CONFIG_BLOCK create_dev("/dev/root", ROOT_DEV); mount_block_root("/dev/root", root_mountflags); #endif }
As can be seen from the above code snippet: mount is in progress_ There are also three methods for root () operation:
(1) NFS mode
adopt mount_nfs_root()Function complete.
(2) ramload mode
adopt rd_load_disk()Function complete.
(3) BLOCK mode
adopt create_dev()and mount_block_root()Two functions complete.
mount_nfs_root () and mount_ block_ Both root () functions call a core function: do_mount_root(),
The function is defined as follows:
static int __init do_mount_root(char *name, char *fs, int flags, void *data) { struct super_block *s; int err = sys_mount(name, "/root", fs, flags, data); if (err) return err; sys_chdir("/root"); s = current->fs->pwd.dentry->d_sb; ROOT_DEV = s->s_dev; printk(KERN_INFO "VFS: Mounted root (%s filesystem)%s on device %u:%u.\n", s->s_type->name, s->s_flags & MS_RDONLY ? " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV)); return 0; }
In the above code, Sys is called_ Mount() and sys_chdir() system call function.
System call to linux again, Sys_ For mount system call, please refer to this article:
https://blog.csdn.net/kai_ding/article/details/9050429
Xiaosheng has limited knowledge and energy. If there is anything wrong with the article, you are welcome to criticize it or discuss it with Xiaosheng( iriczhao@163.com ). ha-ha!