linux文件系统init源代码,《Linux启动过程分析》init进程挂载其他重要文件系统

说明:本分析基于Linux2.6内核和Android2.3版本,其他版本仅供参考。

一、前言

从前边Linux内核启动之根文件系统挂载分析一文我们分析到Linux内核启动之后的根文件系统要么是rootfs(ramdisk释放到rootfs后,其根目录存在init的情况下),要么是磁盘等文件系统;系统根目录要么是rootfs的根目录,要么是磁盘的根目录。

但我们一直特别关心的设备文件系统、proc文件系统,还有就是Linux2.6内核引入的与设备驱动息息相关的sysfs文件系统都是怎样挂载到系统的根目录的?

下边我们就通过sysfs文件系统的创建、挂载到自己根目录,以及最后又如何挂载到系统/sys目录的过程做简单分析;其他文件系统的挂载类似,就不再做分析。

二、sysfs文件系统创建和挂载到自己的根目录

跟Linux内核启动之根文件系统挂载分析中一样,我们先从Linux内核启动代码看起:

kernel/init/main.c

asmlinkage void __init start_kernel(void)

{

setup_arch(&command_line);//解析uboot命令行,实际文件系统挂载需要

parse_args("Booting kernel", static_command_line, __start___param,

__stop___param - __start___param,

&unknown_bootoption);

vfs_caches_init(num_physpages);

#ifdef CONFIG_PROC_FS

//proc文件系统的创建

proc_root_init();

#endif

rest_init();

/*

static int __init kernel_init(void * unused);

do_basic_setup();

//加载内核静态模块

do_initcalls();

mm/shmem.c

module_init(init_tmpfs);

//dev设备文件系统的创建

register_filesystem(&tmpfs_fs_type);

static struct file_system_type tmpfs_fs_type = {

.owner= THIS_MODULE,

.name= "tmpfs",

.get_sb= shmem_get_sb,

.kill_sb= kill_litter_super,

};

*/

}kernel/fs/dcache.c

void __init vfs_caches_init(unsigned long mempages)

{

mnt_init();

bdev_cache_init(); //块设备文件创建

chrdev_init();//字符设备文件创建

}kernel/fs/namespace.c

void __init mnt_init(void)

{

err = sysfs_init(); //本节主要分析这一步

init_rootfs(); //向内核注册rootfs

init_mount_tree();//重要!!!rootfs根目录的建立以及rootfs文件系统的挂载;设置系统current根目录和根文件系统为rootfs

}kernel/fs/sysfs/mount.c

int __init sysfs_init(void)

{

err = register_filesystem(&sysfs_fs_type);//向内核注册sysfs文件系统

sysfs_mount = kern_mount(&sysfs_fs_type);//将sysfs文件系统挂载到自己的根目录

}

static struct file_system_type sysfs_fs_type = {

.name= "sysfs",

.get_sb= sysfs_get_sb,

.kill_sb= kill_anon_super,

};

1.sysfs文件系统如何将自己挂载到自己的根目录?

这部分内容其实和Linux内核启动之根文件系统挂载分析中rootfs挂载自己到自己的根目录很类似;过程如下:

kernel/include/linux/fs.h

#define kern_mount(type) kern_mount_data(type, NULL)

kernel/fs/super.c

struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)

{

return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);

}

struct vfsmount *

vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data)

{

struct vfsmount *mnt;

mnt = alloc_vfsmnt(name); //建立并填充vfsmount

error = type->get_sb(type, flags, name, data, mnt);//为文件系统建立并填充超级块(主要是其dentry和inode),建立sysfs根目录

mnt->mnt_mountpoint = mnt->mnt_root;//文件系统挂载点目录,其实就是刚才建立的”/”目录。挂载点就是自己!!!!

mnt->mnt_parent = mnt;父对象是自己!!!!

}

我们还是主要分析下超级块及根目录的建立过程:

kernel/fs/sysfs/mount.c

static int sysfs_get_sb(struct file_system_type *fs_type,

int flags, const char *dev_name, void *data, struct vfsmount *mnt)

{

return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt);

}kernel/fs/super.c

int get_sb_single(struct file_system_type *fs_type,

int flags, void *data,

int (*fill_super)(struct super_block *, void *, int),

struct vfsmount *mnt)

{

//在内存中分配一个超级块

s = sget(fs_type, compare_single, set_anon_super, NULL);

//执行回调函数,填充该超级块,并建立根目录项及对应i节点

error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);

//关联超级块(包含目录项dentry和i节点inode)和vfsmount

return simple_set_mnt(mnt, s);

}kernel/fs/sysfs/mount.c

static int sysfs_fill_super(struct super_block *sb, void *data, int silent)

{

//i节点

struct inode *inode;

//根目录项

struct dentry *root;

//超级块

sb->s_blocksize = PAGE_CACHE_SIZE;

sb->s_blocksize_bits = PAGE_CACHE_SHIFT;

sb->s_magic = SYSFS_MAGIC;

sb->s_op = &sysfs_ops;

sb->s_time_gran = 1;

sysfs_sb = sb;

//创建i节点,这里边就是具体ops的操作;有兴趣可以细看下,在此不再分析

inode = sysfs_get_inode(&sysfs_root);

//建立上处i节点的目录项

root = d_alloc_root(inode);

//关联超级块和目录项

sb->s_root = root;

return 0;

}kernel/fs/namespace.c

int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb)

{

printk("TK-------_>>>>>>>namespace.c>>>>simple_set_mnt\n");//add by tankai

mnt->mnt_sb = sb; //对 mnt_sb超级块指针附值

mnt->mnt_root = dget(sb->s_root); //对mnt_root指向的根目录赋值

return 0;

}

2.驱动加载过程中就可以在操作如上sysfs,但记住此时sysfs、dev等文件系统并没有和系统current根文件系统和根目录有任何关联、这时用户空间程序是访问不到这些文件系统的。 三、sysfs文件系统挂载到系统current目录树的过程

sysfs文件系统挂载到系统current目录树是在用户空间init进程中完成的;如下代码片段:

Android/system/core/init/init.c

int main(int argc, char **argv)

{

mkdir("/dev", 0755);

mkdir("/proc", 0755);

mkdir("/sys", 0755);

//设备文件系统的挂载

mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");

mkdir("/dev/pts", 0755);

mkdir("/dev/socket", 0755);

mount("devpts", "/dev/pts", "devpts", 0, NULL);

//proc文件系统的挂载

mount("proc", "/proc", "proc", 0, NULL);

//sysfs文件系统的挂载

mount("sysfs", "/sys", "sysfs", 0, NULL);

}在看看init.rc中关于其他文件系统的挂载:

# Backward compatibility

symlink /system/etc /etc

symlink /sys/kernel/debug /d

# Right now vendor lives on the same filesystem as system,

# but someday that may change.

symlink /system/vendor /vendor

# create mountpoints

mkdir /mnt 0775 root system

mkdir /mnt/sdcard 0000 system system

# Create cgroup mount point for cpu accounting

mkdir /acct

mount cgroup none /acct cpuacct

mkdir /acct/uid

# Backwards Compat - XXX: Going away in G*

symlink /mnt/sdcard /sdcard

mkdir /system

mkdir /data 0771 system system

mkdir /cache 0770 system cache

mkdir /config 0500 root root

# Directory for putting things only root should see.

mkdir /mnt/secure 0700 root root

# Directory for staging bindmounts

mkdir /mnt/secure/staging 0700 root root

# Directory-target for where the secure container

# imagefile directory will be bind-mounted

mkdir /mnt/secure/asec 0700 root root

# Secure container public mount points.

mkdir /mnt/asec 0700 root system

mount tmpfs tmpfs /mnt/asec mode=0755,gid=1000

# Filesystem image public mount points.

mkdir /mnt/obb 0700 root system

mount tmpfs tmpfs /mnt/obb mode=0755,gid=1000

write /proc/sys/kernel/panic_on_oops 1

write /proc/sys/kernel/hung_task_timeout_secs 0

write /proc/cpu/alignment 4

write /proc/sys/kernel/sched_latency_ns 10000000

write /proc/sys/kernel/sched_wakeup_granularity_ns 2000000

write /proc/sys/kernel/sched_compat_yield 1

write /proc/sys/kernel/sched_child_runs_first 0

# Create cgroup mount points for process groups

mkdir /dev/cpuctl

mount cgroup none /dev/cpuctl cpu

chown system system /dev/cpuctl

chown system system /dev/cpuctl/tasks

chmod 0777 /dev/cpuctl/tasks

write /dev/cpuctl/cpu.shares 1024

mkdir /dev/cpuctl/fg_boost

chown system system /dev/cpuctl/fg_boost/tasks

chmod 0777 /dev/cpuctl/fg_boost/tasks

write /dev/cpuctl/fg_boost/cpu.shares 1024

mkdir /dev/cpuctl/bg_non_interactive

chown system system /dev/cpuctl/bg_non_interactive/tasks

chmod 0777 /dev/cpuctl/bg_non_interactive/tasks

# 5.0 %

write /dev/cpuctl/bg_non_interactive/cpu.shares 52

on fs

# mount mtd partitions

# Mount /system rw first to give the filesystem a chance to save a checkpoint

mount yaffs2 mtd@system /system

mount yaffs2 mtd@system /system ro remount

mount yaffs2 mtd@userdata /data nosuid nodev

mount yaffs2 mtd@cache /cache nosuid nodev

on post-fs

# once everything is setup, no need to modify /

mount rootfs rootfs / ro remount

四、sysfs、rootfs与系统current根文件系统的问题

通过以上分析,结合Linux内核启动之根文件系统挂载分析;有人可能会问为什么不用sysfs替代rootfs功能(也就是直接设置sysfs为系统current的根文件系统),这样、不就可以不需要rootfs了吗?Linux这方面的设计可能是出于安全和效率方面的考虑;不用sysfs作为系统current的根文件系统,而是增加一个rootfs专门完成初始挂载点的创建工作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值