root=/dev/mmcblk0p2根文件系統掛載

linux掛載跟文件系統,一般通過ramdisk方式。如果沒有使用ramdisk方式,而是使用磁盤上分區文件系統,那麼在prepare_namespace中進行。

static noinline void __init kernel_init_freeable(void)
{
	/*
	 * Wait until kthreadd is all set-up.
	 */
	wait_for_completion(&kthreadd_done);

	/* Now the scheduler is fully set up and can do blocking allocations */
	gfp_allowed_mask = __GFP_BITS_MASK;

	/*
	 * init can allocate pages on any node
	 */
	set_mems_allowed(node_states[N_MEMORY]);
	/*
	 * init can run on any cpu.
	 */
	set_cpus_allowed_ptr(current, cpu_all_mask);

	cad_pid = task_pid(current);

	smp_prepare_cpus(setup_max_cpus);

	do_pre_smp_initcalls();
	lockup_detector_init();

	smp_init();
	sched_init_smp();

	do_basic_setup();

	/* Open the /dev/console on the rootfs, this should never fail */
	if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
		pr_err("Warning: unable to open an initial console.\n");

	(void) sys_dup(0);
	(void) sys_dup(0);
	/*
	 * check if there is an early userspace init.  If yes, let it do all
	 * the work
	 */

	if (!ramdisk_execute_command)   //啓動參數bootargs中沒有指定init進程,那麼採用默認的/init
		ramdisk_execute_command = "/init";

	//搜索當前系統中是否有/init,如果前面已經掛載了ramdisk,就會存在/init
	//ramdisk由uboot搬移到內存中,並傳遞給kernel,所以ramdisk可以很早就進行加載
	//當實際物理設備上的根分區需要 驅動都初始化好後才能加載,所以這裏是等待驅動加載完成後,才prepare_namespace掛載文件系統
	if (sys_access((const char __user *) ramdisk_execute_command, 0) != 0) {
		ramdisk_execute_command = NULL;
		prepare_namespace();
	}

	/*
	 * Ok, we have completed the initial bootup, and
	 * we're essentially up and running. Get rid of the
	 * initmem segments and start the user-mode stuff..
	 */

	/* rootfs is available now, try loading default modules */
	load_default_modules();
}

比如bootargs中 參數: root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait
表示跟分區在mmcblk0p2 ,文件系統類型爲ext4,掛載點爲/dev/root(默認)
由於前面設備驅動已經加載好,所以能夠找到mmcblk0p2

static int __init root_dev_setup(char *line)
{
	strlcpy(saved_root_name, line, sizeof(saved_root_name));
	return 1;
}

__setup("root=", root_dev_setup);
/*
 * Prepare the namespace - decide what/where to mount, load ramdisks, etc.
 */
void __init prepare_namespace(void)
{
	int is_floppy;

	if (root_delay) {
		printk(KERN_INFO "Waiting %dsec before mounting root device...\n",
		       root_delay);
		ssleep(root_delay);
	}

	/*
	 * wait for the known devices to complete their probing
	 *
	 * Note: this is a potential source of long boot delays.
	 * For example, it is not atypical to wait 5 seconds here
	 * for the touchpad of a laptop to initialize.
	 */
	wait_for_device_probe();

	md_run_setup();

	if (saved_root_name[0]) {
		root_device_name = saved_root_name;  //saved_root_name中保存了/dev/mmcblk0p2
		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); //根據設備名mmcblk0p2 生成設備號 dev_t,主設備號和次設備號
		if (strncmp(root_device_name, "/dev/", 5) == 0)
			root_device_name += 5;  //root_device_name 前移5,由/dev/mmcblk0p2 變爲mmcblk0p2
	}

	if (initrd_load())
		goto out;

	/* wait for any asynchronous scanning 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(".");
}
void __init mount_root(void)
{

#ifdef CONFIG_BLOCK
	create_dev("/dev/root", ROOT_DEV); //這裏利用mksnod創建設備文件/dev/root,對應設備號和mmcblk0p2相同
	mount_block_root("/dev/root", root_mountflags);//開始掛載根文件分區,後續會根據/dev/root找到分區mmcblk0p2
#endif
}

後續再講其它。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章