01void __init vfs_caches_init(unsigned long mempages)
02{
03 unsigned long reserve;
04
05 /* Base hash sizes on available memory, with a reserve equal to
06 150% of current kernel size */
07
08 reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1);
09 mempages -= reserve;
10
11 names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0,
12 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
13
14 dcache_init(); //页目录缓存的初始化
15 inode_init(); //索引结点缓存的初始化
16 files_init(mempages);
17 mnt_init(); // 虚拟文件系统挂载的初始化, 主要是挂载节点的初始化化和把目录设置为当前挂载点目录
18 bdev_cache_init();
19 chrdev_init();
20}
static int __init populate_rootfs(void)
02{
03 char *err = unpack_to_rootfs(__initramfs_start,
04 __initramfs_end - __initramfs_start);
05 if (err)
06 panic(err); /* Failed to decompress INTERNAL initramfs */
07 if (initrd_start) {
08#ifdef CONFIG_BLK_DEV_RAM
09 int fd;
10 printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
11 err = unpack_to_rootfs((char *)initrd_start,
12 initrd_end - initrd_start);
13 if (!err) {
14 free_initrd();
15 return 0;
16 } else {
17 clean_rootfs();
18 unpack_to_rootfs(__initramfs_start,
19 __initramfs_end - __initramfs_start);
20 }
21 printk(KERN_INFO "rootfs image is not initramfs (%s)"
22 "; looks like an initrd\n", err);
23 fd = sys_open("/initrd.image", O_WRONLY|O_CREAT, 0700);
24 if (fd >= 0) {
25 sys_write(fd, (char *)initrd_start,
26 initrd_end - initrd_start);
27 sys_close(fd);
28 free_initrd();
29 }
30#else
31 err = unpack_to_rootfs((char *)initrd_start,
32 initrd_end - initrd_start);
33 if (err)
34 printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
35 free_initrd();
36#endif
37 }
38 return 0;
39}
01void __init prepare_namespace(void)
02{
03 int is_floppy;
04 if (root_delay) {
05 printk(KERN_INFO "Waiting %dsec before mounting root device...\n",
06 root_delay);
07 ssleep(root_delay);
08 }
09
10 /*
11 * wait for the known devices to complete their probing
12 *
13 * Note: this is a potential source of long boot delays.
14 * For example, it is not atypical to wait 5 seconds here
15 * for the touchpad of a laptop to initialize.
16 */
17 wait_for_device_probe();
18
19 md_run_setup();
20
21 if (saved_root_name[0]) {
22 root_device_name = saved_root_name;
23 if (!strncmp(root_device_name, "mtd", 3) ||
24 !strncmp(root_device_name, "ubi", 3)) {
25 mount_block_root(root_device_name, root_mountflags);
26 goto out;
27 }
28 ROOT_DEV = name_to_dev_t(root_device_name);
29 if (strncmp(root_device_name, "/dev/", 5) == 0)
30 root_device_name += 5;
31}
32
33 if (initrd_load())
34 goto out;
35
36 /* wait for any asynchronous scanning to complete */
37 if ((ROOT_DEV == 0) && root_wait) {
38 printk(KERN_INFO "Waiting for root device %s...\n",
39 saved_root_name);
40 while (driver_probe_done() != 0 ||
41 (ROOT_DEV = name_to_dev_t(saved_root_name)) == 0)
42 msleep(100);
43 async_synchronize_full();
44 }
45
46 is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
47
48 if (is_floppy && rd_doload && rd_load_disk(0))
49 ROOT_DEV = Root_RAM0;
50
51 mount_root();
52out:
53 sys_mount(".", "/", NULL, MS_MOVE, NULL);
54 sys_chroot(".");
55}
第21行检查saved_root_name是否为真,这里是有值的。
第22行把它赋给root_device_name,此时为/dev/mtdblock3
第23-27行不执行
第25行挂载根文件系统
第28行名字到设备号的转变,这个设备号是设备的设备号,下面会用到的。我这里是flash的第三个分区
第29行/dev/mtdblock3的前5个字符与/dev/比较,这里是相等的。
第30行root_device_name加5,所以此时root_device_name为mtdblock3.
第37-44行由于设备号不为0,所以这里面没有执行。
第53行移动根文件系统的根目录为/
01void __init mount_block_root(char *name, int flags)
02{
03 char *fs_names = __getname();
04 char *p;
05#ifdef CONFIG_BLOCK
06 char b[BDEVNAME_SIZE];
07#else
08 const char *b = name;
09#endif
10
11 get_fs_names(fs_names);
12retry:
13 for (p = fs_names; *p; p += strlen(p)+1) {
14 int err = do_mount_root(name, p, flags, root_mount_data);
15 switch (err) {
16 case 0:
17 goto out;
18 case -EACCES:
19 flags |= MS_RDONLY;
20 goto retry;
21 case -EINVAL:
22 continue;
23 }
24 /*
25 * Allow the user to distinguish between failed sys_open
26 * and bad superblock on root device.
27 * and give them a list of the available devices
28 */
29#ifdef CONFIG_BLOCK
30 __bdevname(ROOT_DEV, b);
31#endif
32 printk("VFS: Cannot open root device \"%s\" or %s\n",
33 root_device_name, b);
34 printk("Please append a correct \"root=\" boot option; here are the available partitions:\n");
35
36 printk_all_partitions();
37#ifdef CONFIG_DEBUG_BLOCK_EXT_DEVT
38 printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify "
39 "explicit textual name for \"root=\" boot option.\n");
40#endif
41 panic("VFS: Unable to mount root fs on %s", b);
42 }
43
44 printk("List of all partitions:\n");
45 printk_all_partitions();
46 printk("No filesystem could mount root, tried: ");
47 for (p = fs_names; *p; p += strlen(p)+1)
48 printk(" %s", p);
49 printk("\n");
50#ifdef CONFIG_BLOCK
51 __bdevname(ROOT_DEV, b);
52#endif
53 panic("VFS: Unable to mount root fs on %s", b);
54out:
55 putname(fs_names);
56}
第3行申请空间
第11行fs_name指向内核里面编译文件系统的第一个
第13行循环把这些文件系统挂到根目录下,我的内核里面分别有,ext3,ext3,vfat等,这里用到的是yaffs文件系统
第14行调用do_mount_root函数进行挂载
第15行返回的结果0
第17行增加对文件系统的引用
01static int __init do_mount_root(char *name, char *fs, int flags, void *data)
02{
03 int err = sys_mount(name, "/root", fs, flags, data);
04 if (err)
05 return err;
06
07 sys_chdir("/root");
08 ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev;
09 printk("VFS: Mounted root (%s filesystem)%s on device %u:%u.\n",
10 current->fs->pwd.mnt->mnt_sb->s_type->name,
11 current->fs->pwd.mnt->mnt_sb->s_flags & MS_RDONLY ?
12 " readonly" : "", MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
13 return 0;
14}
第3行挂载文件系统,这里的name为/dev/root,fs为文件的类型,这里是yaffs2,文件类型当然还是ext3,ext2等。
第7行改变到/root目录下
第9行分别显示出挂载出根文件系统和主次设备号,这里是yaffs文件系统,主:次31:3
01void __init mount_root(void)
02{
03#ifdef CONFIG_ROOT_NFS
04 if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) {
05 if (mount_nfs_root())
06 return;
07
08 printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n");
09 ROOT_DEV = Root_FD0;
10 }
11#endif
12#ifdef CONFIG_BLK_DEV_FD
13 if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
14 /* rd_doload is 2 for a dual initrd/ramload setup */
15 if (rd_doload==2) {
16 if (rd_load_disk(1)) {
17 ROOT_DEV = Root_RAM1;
18 root_device_name = NULL;
19 }
20 } else
21 change_floppy("root floppy");
22 }
23#endif
24#ifdef CONFIG_BLOCK
25 create_dev("/dev/root", ROOT_DEV);
26 mount_block_root("/dev/root", root_mountflags);
27#endif
28}
这里只执行了CONFI_BLOCK宏开关
第25行创建设备结点,这里我在ubutu上测试了一下,/dev/root是的连接是hda1
第26行挂载根文件系统
第五部分运行真正根目录中的init程序
01static noinline int init_post(void)
02 __releases(kernel_lock)
03{
04 /* need to finish all async __init code before freeing the memory */
05 async_synchronize_full();
06 free_initmem();
07 unlock_kernel();
08 mark_rodata_ro();
09 system_state = SYSTEM_RUNNING;
10 numa_default_policy();
11
12 if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
13 printk(KERN_WARNING "Warning: unable to open an initial console.\n");
14
15 (void) sys_dup(0);
16 (void) sys_dup(0);
17
18 current->signal->flags |= SIGNAL_UNKILLABLE;
19
20 if (ramdisk_execute_command) {
21 run_init_process(ramdisk_execute_command);
22 printk(KERN_WARNING "Failed to execute %s\n",
23 ramdisk_execute_command);
24 }
25
26 /*
27 * We try each of these until one succeeds.
28 *
29 * The Bourne shell can be used instead of init if we are
30 * trying to recover a really broken machine.
31 */
32 if (execute_command) {
33 run_init_process(execute_command);
34 printk(KERN_WARNING "Failed to execute %s. Attempting "
35 "defaults...\n", execute_command);
36 }
37 run_init_process("/sbin/init");
38 run_init_process("/etc/init");
39 run_init_process("/bin/init");
40 run_init_process("/bin/sh");
41
42 panic("No init found. Try passing init= option to kernel.");
43}
第12行打开/dev/console设备文件
第15-16行将文件描述符0复制给文件描述符1和2。
第20-24行ramdisk_execute_command变量中如果指定了要运行的程序,就开始运行这个程序,在u-boot的命令行参数中会指定rdinit=…,这个时候ramdisk_execute_command等于这个参数指定的程序。也可能/init程序存在,哪么ramdisk_execute_command就等于/init,或者为空。本程序没有指定,所以这里为空。
第37行执行/sbin/init程序,这个程序存在于根文件系统,如果存在,执行它,系统的控制权交给/sbin/init,不再返回init_post函数