Simple function call relationships for mounting and initializing the root file system rootfs are as follows:
Init/main. c
Start_kernel --> vfs_cache_init --> mnt_init --> init_rootfs
Init_mount_tree --> vfs_kern_mount
Mount and initialize the root file system rootfs,
1. Start the kernel and call the start_kernel function for initialization.
Asmlinkage void _ init start_kernel (void) // init \ Main. c: 528
{
Buffer_init ();
Key_init ();
Security_init ();
Vfs_caches_init (totalram_pages); // row 678, vfs Initialization
Signals_init ();
}
2. start_kernel calls vfs_caches_init to initialize vfs.
// Fs \ Dcach. c: Row 2354
Void _ init vfs_caches_init (unsigned long mempages)
{
.......
Dcache_init ();
Inode_init ();
Files_init (mempages );
Mnt_init (); // mnt Initialization
Bdev_cache_init ();
Chrdev_init ();
}
3. Call the mnt_init function of row 2321 of fs \ namespace. c In vfs_caches_init.
Void _ init mnt_init (void)
{
Init_rootfs (); // initialize the rootfs File System
Init_mount_tree (); // initialize the loading tree
}
4. The init_rootfs function of row 308th of fs \ ramfs initializes the rootfs file system.
Int _ init init_rootfs (void)
{
Int err;
Err = bdi_init (& ramfs_backing_dev_info );
If (err)
Return err;
Err = register_filesystem (& rootfs_fs_type); // register the rootfs File System
If (err)
Bdi_destroy (& ramfs_backing_dev_info );
Return err;
}
Rootfs File System Information fs/ramfs/inode. c
Static struct file_system_type rootfs_fs_type = {
. Name = "rootfs ",
. Get_sb = rootfs_get_sb, (init_mount_tree will initialize rootfs by calling this function)
. 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-& gt; mnt_ns = ns;
2299 maid (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}
1058 struct 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}
879 struct 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); (call the get_sb of rootfs, that is, rootfs_get_sb)
*********
}
263 static 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 () Here we finally see the familiar "/" root directory;
Return to the start_kernel function and call rest_init in the last line.
Rest_init creates the kernel thread kernel_init and calls do_basic_setup to decompress the initrd content to the rootfs file system.
Call init_post to execute the init script under initrd (note that it is indeed a script. For details, refer to initrd decompression)
Rest_init --> kernel_init --> do_basic_setup --> do_init_cils
--> Init_post
Static void _ initDo_initcils(Void)
{
Initcall_t * call;
Int count = preempt_count ();
For (call = _ initcall_start; call <_ initcall_end; call ++ ){
··················
(* Call) (); // call a series of initialization functions
···················
}
---------------------------
_ Initcall_start and _ initcall_end define the starting address for storing the initialization function pointer area, that is, from _ initcall_start to _ initcall_end, function pointers pointing to various initialization functions are stored. The initialization of each part is completed by (* call) (), which facilitates expansion.
Among them, init/initramfs. c rootfs_initcall (populate_rootfs );
# Define rootfs_initcall (fn) _ define_initcall ("rootfs", fn, rootfs)
Populate_rootfs decompress the initrd content to the rootfs file system;
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 is initially called/init in the kernel_init function. For details about the init script, see the appendix.
834 if (ramdisk_execute_command ){
835 run_init_process (ramdisk_execute_command );
// The kernel with initrd will not execute the following code; the run_init_process function will not return;
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}
// The kernel with initrd will not execute the following code, and those with no initrd will be executed here;
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}