initrd掛載根檔案系統

來源:互聯網
上載者:User

掛載並初始化根檔案系統rootfs的簡單函數調用關係如下:

init/main.c

start_kernel --> vfs_cache_init-->mnt_init-->init_rootfs

init_mount_tree-->vfs_kern_mount

掛載並初始化根檔案系統rootfs,

1.核心啟動調用start_kernel函數進行初始化。

asmlinkage void __init start_kernel(void) //init\Main.c:528
{
buffer_init();
key_init();
security_init();
vfs_caches_init(totalram_pages);//678行,vfs初始化
signals_init();
}

2.start_kernel調用vfs_caches_init對vfs進行初始化。

//fs\Dcach.c:2354行
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函數

void __init mnt_init(void)
{

init_rootfs(); //初始化rootfs檔案系統
init_mount_tree(); //初始化載入樹
}

4. fs\ramfs第308行的init_rootfs函數初始化rootfs檔案系統

int __init init_rootfs(void)
{
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

static struct file_system_type rootfs_fs_type = {
.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 }

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.