挂载并初始化根文件系统rootfs的简单函数调用关系如下:
init/main.c
start_kernel --> vfs_cache_init-->mnt_init-->init_rootfs
init_mount_tree-->vfs_kern_mount
挂载并初始化根文件系统rootfs,
1.内核启动调用start_kernel函数进行初始化。
{
buffer_init();
key_init();
security_init();
vfs_caches_init(totalram_pages); // 678行,vfs初始化
signals_init();
}
2.start_kernel调用vfs_caches_init对vfs进行初始化。
void __init vfs_caches_init(unsigned long mempages)
{
.......
dcache_init();
inode_init();
files_init(mempages);
mnt_init(); // mnt初始化
bdev_cache_init();
chrdev_init();
}
3.在vfs_caches_init调用fs\namespace.c 2321行的mnt_init函数
{
![](https://i-blog.csdnimg.cn/blog_migrate/918e8df969f9f8c8d002f25cda86cade.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/918e8df969f9f8c8d002f25cda86cade.gif)
init_rootfs(); // 初始化rootfs文件系统
init_mount_tree(); // 初始化加载树
}
4. fs\ramfs第308行的init_rootfs函数初始化rootfs文件系统
{
int err;
err = bdi_init(&ramfs_backing_dev_info);
if (err)
return err;
err = register_filesystem( & rootfs_fs_type); // 注册rootfs文件系统
if (err)
bdi_destroy(&ramfs_backing_dev_info);
return err;
}
rootfs文件系统信息fs/ramfs/inode.c
.name = "rootfs",
.get_sb = rootfs_get_sb,(init_mount_tree会通过调用该函数对rootfs进行初始化)
.kill_sb = kill_litter_super,
};
5.
static void __init init_mount_tree(void)
2286{
2287 struct vfsmount *mnt;
2288 struct mnt_namespace *ns;
2289 struct path root;
2290
2291 mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);
2292 if (IS_ERR(mnt))
2293 panic("Can't create rootfs");
2294 ns = create_mnt_ns(mnt);
2295 if (IS_ERR(ns))
2296 panic("Can't allocate initial namespace");
2297
2298 init_task.nsproxy->mnt_ns = ns;
2299 get_mnt_ns(ns);
2300
2301 root.mnt = ns->root;
2302 root.dentry = ns->root->mnt_root;
2303
2304 set_fs_pwd(current->fs, &root);
2305 set_fs_root(current->fs, &root);
2306}
1058struct vfsmount *
1059do_kern_mount(const char *fstype, int flags, const char *name, void *data)
1060{
1061 struct file_system_type *type = get_fs_type(fstype);
1062 struct vfsmount *mnt;
1063 if (!type)
1064 return ERR_PTR(-ENODEV);
1065 mnt = vfs_kern_mount(type, flags, name, data);
1066 if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) &&
1067 !mnt->mnt_sb->s_subtype)
1068 mnt = fs_set_subtype(mnt, fstype);
1069 put_filesystem(type);
1070 return mnt;
1071}
879struct vfsmount *
880vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)
881{
882 struct vfsmount *mnt;
883 char *secdata = NULL;
884 int error;
885
886 if (!type)
887 return ERR_PTR(-ENODEV);
888
889 error = -ENOMEM;
890 mnt = alloc_vfsmnt(name);
891 if (!mnt)
892 goto out;
893
894 if (flags & MS_KERNMOUNT)
895 mnt->mnt_flags = MNT_INTERNAL;
896
897 if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) {
898 secdata = alloc_secdata();
899 if (!secdata)
900 goto out_mnt;
901
902 error = security_sb_copy_data(data, secdata);
903 if (error)
904 goto out_free_secdata;
905 }
906
907 error = type->get_sb(type, flags, name, data, mnt);(调用了rootfs的get_sb即rootfs_get_sb)
*********
}
263static int rootfs_get_sb(struct file_system_type *fs_type,
264 int flags, const char *dev_name, void *data, struct vfsmount *mnt)
265{
266 return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,
267 mnt);
268}
821int get_sb_nodev(struct file_system_type *fs_type,
822 int flags, void *data,
823 int (*fill_super)(struct super_block *, void *, int),
824 struct vfsmount *mnt)
825{
826 int error;
827 struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
828
829 if (IS_ERR(s))
830 return PTR_ERR(s);
831
832 s->s_flags = flags;
833
834 error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
835 if (error) {
836 deactivate_locked_super(s);
837 return error;
838 }
839 s->s_flags |= MS_ACTIVE;
840 simple_set_mnt(mnt, s);
841 return 0;
842}
fill_super-->simple_fill_super-->new_inode()
d_alloc_root()这里终于看到熟悉的“/"根目录;
回到start_kernel函数,最后一行调用rest_init
rest_init创建内核线程kernel_init,调用do_basic_setup将 initrd的内容解压到rootfs文件系统下
接着调用init_post执行initrd下的的init脚本(注意,确实是个脚本,参见initrd解压)
rest_init-->kernel_init-->do_basic_setup-->do_init_calls
-->init_post
static void __init do_initcalls(void)
{
initcall_t *call;
int count = preempt_count();
for (call = __initcall_start; call < __initcall_end; call++) {
··················
(*call)(); //调用一系列初始化函数
···················
}
---------------------------
__initcall_start和__initcall_end界定了存放初始化函数指针区域的起始地址,即从__initcall_start开始到__initcall_end结束的区域中存放了指向各个初始化函数的函数指针。 由 (*call)()完成各个部分的初始化工作,且便于扩充。
其中有init/initramfs.c rootfs_initcall(populate_rootfs);
#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
populate_rootfs 将 initrd的内容解压到rootfs文件系统下;
821 static noinline int init_post(void)
822 __releases(kernel_lock)
823 {
824 /* need to finish all async __init code before freeing the memory */
825 async_synchronize_full();
826 free_initmem();
827 mark_rodata_ro();
828 system_state = SYSTEM_RUNNING;
829 numa_default_policy();
830
831
832 current->signal->flags |= SIGNAL_UNKILLABLE;
833
//ramdisk_execute_command在kernel_init函数中被初始话为/init,init脚本详解见附录
834 if (ramdisk_execute_command) {
835 run_init_process(ramdisk_execute_command);
//带有initrd的内核不会执行以下代码; run_init_process函数不会返回;
836 printk(KERN_WARNING "Failed to execute %s\n",
837 ramdisk_execute_command);
838 }
839
840 /*
841 * We try each of these until one succeeds.
842 *
843 * The Bourne shell can be used instead of init if we are
844 * trying to recover a really broken machine.
845 */
846 if (execute_command) {
847 run_init_process(execute_command);
848 printk(KERN_WARNING "Failed to execute %s. Attempting "
849 "defaults...\n", execute_command);
850 }
//带有initrd的内核不会执行以下代码,不带的应该会执行到这里;
851 run_init_process("/sbin/init");
852 run_init_process("/etc/init");
853 run_init_process("/bin/init");
854 run_init_process("/bin/sh");
855
856 panic("No init found. Try passing init= option to kernel. "
857 "See Linux Documentation/init.txt for guidance.");
858 }
【1】 init脚本详解参考:http://unixboy.iteye.com/blog/157717