linux 2.6.28 kernel之rootfs根文件系统及安装卸载

深渊向深渊呼唤
/////////////////////////////////////////////////////////////////
asmlinkage void __init start_kernel(void) { // 省略很多 vfs_caches_init_early();
        thread_info_cache_init();
//省略        vfs_caches_init(num_physpages);
ftrace_init();
/* Do the rest non-__init'ed, we're now alive */ rest_init(); } ////////////////////////////////////////////////////////////////////
fs/dcache.c

本函数由init/main.c的asmlinkage void __init start_kernel(void)函数调用
void __init vfs_caches_init(unsigned long mempages) { unsigned long reserve;
/* Base hash sizes on available memory, with a reserve equal to            150% of current kernel size */
reserve = min((mempages - nr_free_pages()) * 3/2, mempages - 1); mempages -= reserve;
names_cachep = kmem_cache_create("names_cache", PATH_MAX, 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
dcache_init(); inode_init(); files_init(mempages); mnt_init(); bdev_cache_init(); chrdev_init();
////////////////////////////////////////
fs/namespace.c
void __init mnt_init(void) { unsigned u; int err;
init_rwsem(&namespace_sem);
mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
mount_hashtable = (struct list_head *)__get_free_page(GFP_ATOMIC);
if (!mount_hashtable) panic("Failed to allocate mount hash table\n");
printk("Mount-cache hash table entries: %lu\n", HASH_SIZE);
for (u = 0; u INIT_LIST_HEAD(&mount_hashtable[u]);
err = sysfs_init(); if (err) printk(KERN_WARNING "%s: sysfs_init error: %d\n", __func__, err); fs_kobj = kobject_create_and_add("fs", NULL); if (!fs_kobj) printk(KERN_WARNING "%s: kobj create error\n", __func__); init_rootfs(); init_mount_tree(); }
/////////////////////////////////////////////////////////////////////////////////////////////////
 fs/ramfs/inode.c
module_init(init_ramfs_fs) module_exit(exit_ramfs_fs)
  int __init init_rootfs(void) { int err;
err = bdi_init(&ramfs_backing_dev_info); if (err) return err;
err = register_filesystem(&rootfs_fs_type); if (err) bdi_destroy(&ramfs_backing_dev_info);
return err; }
////////////////////////////////


//////////////////////////////    //////////////////////////////////
fs/namespace.c
//见mount系统调用日志
static void __init init_mount_tree(void) { struct vfsmount *mnt; struct mnt_namespace *ns; struct path root;
mnt = do_kern_mount("rootfs", 0, "rootfs", NULL); if (IS_ERR(mnt)) panic("Can't create rootfs");
                //为进程号0的命名空间分配一个namespace对象  ns = kmalloc(sizeof(*ns), GFP_KERNEL); if (!ns) panic("Can't allocate initial namespace"); atomic_set(&ns->count, 1); INIT_LIST_HEAD(&ns->list); init_waitqueue_head(&ns->poll); ns->event = 0;
            //将分配到的namespace插入到由do_kern_mount()函数返回的已安装文件系统描述符中  list_add(&mnt->mnt_list, &ns->list); ns->root = mnt; mnt->mnt_ns = ns;
init_task.nsproxy->mnt_ns = ns; get_mnt_ns(ns);
root.mnt = ns->root; root.dentry = ns->root->mnt_root; //将进程0的根目录和当前工作目录设置为根文件系统,后面会有安装实际根文件系统 set_fs_pwd(current->fs, &root); set_fs_root(current->fs, &root); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
fs/ramfs/inode.c
static struct    backing_dev_info      ramfs_backing_dev_info = { .ra_pages = 0, /* No readahead */ .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK |  BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |  BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP, }; 
///
static struct file_system_type      ramfs_fs_type = { .name = "ramfs", .get_sb = ramfs_get_sb, .kill_sb = kill_litter_super, };
/// fs/ramfs/inode.c static struct file_system_type     rootfs_fs_type = { .name = "rootfs", .get_sb = rootfs_get_sb, .kill_sb = kill_litter_super, };  ///

///
include/linux/backing-dev.h
struct     backing_dev_info { unsigned long ra_pages; /* max readahead in PAGE_CACHE_SIZE units */ unsigned long state; /* Always use atomic bitops on this */ unsigned int capabilities; /* Device capabilities */ congested_fn *congested_fn; /* Function pointer if device is md/dm */ void *congested_data; /* Pointer to aux data for congested func */ void (*unplug_io_fn)(struct backing_dev_info *, struct page *); void *unplug_io_data;
struct percpu_counter bdi_stat[NR_BDI_STAT_ITEMS];
struct prop_local_percpu completions; int dirty_exceeded;
unsigned int min_ratio; unsigned int max_ratio, max_prop_frac;
struct device *dev;
#ifdef CONFIG_DEBUG_FS struct dentry *debug_dir; struct dentry *debug_stats; #endif };
/// include/linux/fs.h
struct file_system_type { const char *name; int fs_flags; int (*get_sb) (struct file_system_type *, int,       const char *, void *, struct vfsmount *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; struct list_head fs_supers;
struct lock_class_key s_lock_key; struct lock_class_key s_umount_key;
struct lock_class_key i_lock_key; struct lock_class_key i_mutex_key; struct lock_class_key i_mutex_dir_key; struct lock_class_key i_alloc_sem_key; }; 
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


/////////////////////////////
 fs/ramfs/inode.c
 static int rootfs_get_sb(struct file_system_type *fs_type,                          int flags, const char *dev_name, void *data, struct vfsmount *mnt) { return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super,    mnt); }
//////////////////////////////////
fs/super.c
int get_sb_nodev(struct file_system_type *fs_type,                                   int flags, void *data,                                     int (*fill_super)(struct super_block *, void *, int),                                         struct vfsmount *mnt) { int error; struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
if (IS_ERR(s)) return PTR_ERR(s);
s->s_flags = flags;
error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); if (error) { up_write(&s->s_umount); deactivate_super(s); return error; } s->s_flags |= MS_ACTIVE; return simple_set_mnt(mnt, s); }  ////////////////////////////////////

/////////////////////////////////实际安装根文件系统///////////////////////////////////////////////////////////////////////////////

static void noinline __init_refok rest_init(void) __releases(kernel_lock) { int pid;
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); numa_default_policy(); pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns); unlock_kernel();
/* * The boot idle thread must execute schedule() * at least once to get things moving: */ init_idle_bootup_task(current); preempt_enable_no_resched(); schedule(); preempt_disable();
/* Call into cpu_idle with preempt disabled */ cpu_idle(); } ///
init/main.c
static int __init kernel_init(void * unused) { lock_kernel(); /* * init can run on any cpu. */ set_cpus_allowed_ptr(current, CPU_MASK_ALL_PTR); /* * Tell the world that we're going to be the grim * reaper of innocent orphaned children. * * We don't want people to have to make incorrect * assumptions about where in the task array this * can be found. */ init_pid_ns.child_reaper = current;
cad_pid = task_pid(current);
smp_prepare_cpus(setup_max_cpus);
do_pre_smp_initcalls(); start_boot_trace();
smp_init(); sched_init_smp();
cpuset_init_smp();
do_basic_setup();
/* * check if there is an early userspace init.  If yes, let it do all * the work */
if (!ramdisk_execute_command) ramdisk_execute_command = "/init";
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.. */ stop_boot_trace(); init_post(); return 0; } //// /*  * Prepare the namespace - decide what/where to mount, load ramdisks, etc.  */
 init/do_mounts.c 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 */ while (driver_probe_done() != 0) msleep(100);
md_run_setup();
if (saved_root_name[0]) { root_device_name = saved_root_name; if (!strncmp(root_device_name, "mtd", 3) ||    !strncmp(root_device_name, "ubi", 3)) { mount_block_root(root_device_name, root_mountflags); goto out; }
                //把 root_device_name变量置为从启动参数"root"中获取的设备文件名 ROOT_DEV = name_to_dev_t(root_device_name); if (strncmp(root_device_name, "/dev/", 5) == 0) root_device_name += 5; }
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); }
is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
if (is_floppy && rd_doload && rd_load_disk(0)) ROOT_DEV = Root_RAM0;
mount_root(); out:
        //移动rootfs文件系统根目录上的已安装文件系统的安装点    
          //注意rootfs特殊文件系统没有被卸载,他只是隐藏在基于磁盘的根文件系统下了。  sys_mount(".", "/", NULL, MS_MOVE, NULL); sys_chroot("."); }
////////////////////////////////////////////////实际安装根文件系统end///////////////////////////////////////////////////////////////////////////////////////////////////  window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)]; 阅读(242) | 评论(0) | 转发(0) | 0

上一篇:linux 2.6.28 kernel之VFS虚拟文件系统read系统调用详解

下一篇:arm64 device tree加载过程

栏目
文章分类