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 < HASH_SIZE; 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///

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xx-xx-xxx-xxx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值