linux文件系统的系统分析--(三)rootfs的安装
2012-11-29 18:32
405 查看
在《linux文件系统的系统分析--(一)文件系统类型的注册》我们以rootfs为例分析了文件系统是如何注册的,接着我们就分析rootfs的安装。
在mnt_init-->init_mount_tree:
分为3部分来分析这个函数:
1、mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);这个是安装操作的核心;
1.2、mnt = vfs_kern_mount(type, flags, name, data);
1.2.1、mnt = alloc_vfsmnt(name);初始化struct vfsmount *mnt;结构体;
1.2.2、error = type->get_sb(type, flags, name, data, mnt);调用rootfs的get_sb方法rootfs_get_sb来获取超级块:
1.2.2.1、struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
set_anon_super获得一个未使用的次设备号dev,然后用主设备号0和次设备号dev设置s的s_dev字段
调用alloc_super函数来初始化s,然后对s这个super_block超级块的几个关键字段赋值:
s的s_dev字段就是前面提到的设备号,s的s_type就是rootfs_fs_type这个file_system_type结构体类型的指针,
s的s_id字段放置文件系统类型的名称"rootfs",将新建的super_block对象加入以super_blocks为头的双向链表中,链接的字段是struct
list_head s_list;
将s的s_instances字段加入rootfs的的fs_supers双向链表头,这里表明同一种文件系统类型可以有多个super_block,有多个实例,这些斗用fs_supers串起来。
1.2.2.2、调用rootfs的fill_super(ramfs_fill_super)来分配索引节点对象和对应的目录项对象,并填充超级块字段值。这里会建立rootfs的“/”目录项对象和索引节点对象。
sb->s_root = root; 这个root就是“/”目录项对象。
1.2.2.3、将mnt的mnt_sb指向刚建的super_block超级块对象,将mnt的mnt_root指向sb的s_root对象("/"的目录项对象)
1.2.3、
mnt->mnt_mountpoint = mnt->mnt_root; 安装树的根的目录项和安装点的目录项都指向前面的root(rootfs的"/"目录项对象)
mnt->mnt_parent = mnt; 将我们mount的文件系统指向自己。比如在/mnt/a下是mount了一块ext2的磁盘,在/mnt/a/b下又mount omfs文件系统,那么这里的parent就可 以指明这个关系。
2、ns = create_mnt_ns(mnt);
新建一个私有的命名空间(mnt_namespace),并添加root fs:
mnt->mnt_ns = new_ns;
new_ns->root = mnt;
list_add(&new_ns->list, &new_ns->root->mnt_list);
3、
root.mnt = ns->root;
root.dentry = ns->root->mnt_root;
set_fs_pwd(current->fs, &root);
set_fs_root(current->fs, &root);
将进程0的根目录和当前工作目录设备为根文件系统。
到目前我们看得rootfs都是基于内存的数据,要真正安装根文件系统,就要安装实际的文件系统。我们以磁盘的文件系统为例。
在系统初始化的最后部分:
start_kernel-->rest_init-->kernel_init-->prepare_namespace
1、把root_device_name变量设置为从启动参数"root"中获取的设备文件名。同样把ROOT_DEV变量设置为同一设备文件的主设备号和次设备号。
实际上代码中会优先将root_device_name和mtd ubi做对比,如果有这样的flash设备,就从flash上建立文件系统。
2、还是以磁盘说明,调用mount_root函数:
2.1、调用sys_mknod在rootfs初始根文件系统中创建设备文件/dev/root,其主次设备号与ROOT_DEV中的一样。
2.2、分配一个缓冲区并用文件系统类型名链表填充它。该链表通过启动参数"rootfstype"传送给内核,也可以通过file_systems为头的单向链表中获取元素建立。
2.3、扫描上面建立的链表,对每一种文件系统斗调用sys_mount在根目录上安装给定的文件系统类型。但是由于每种文件系统都有自己的magic,在get_sb时候会从
物理设备的特定位置读到magic,这个magic实在mkfs的时候写入物理设备的。因为magic的存在,所以大多数文件系统不可用,只有一个例外,就是用根设备上实际 使用过的文件系统的函数来填充超级块的那个调用,该文件系统安装在rootfs文件系统的/root目录。
3、
sys_mount(".", "/", NULL, MS_MOVE, NULL);
sys_chroot(".");
移动rootfs文件系统目录上的已安装文件系统的安装点。
注意的是:rootfs文件系统没有卸载,只是隐藏在基于磁盘(磁盘或flash这种存储介质)的根文件系统下了。
举个例子说明:
在pc的ubuntu下,
lrwxrwxrwx 1 root root 4 2012-04-03 14:46 /dev/root -> sda7
sda7是安装ubuntu的盘
df -TH结果如下:
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda7 ext4 27G 24G 1011M 97% /
none devtmpfs 494M 716K 493M 1% /dev
none tmpfs 500M 1.3M 499M 1% /dev/shm
none tmpfs 500M 384K 500M 1% /var/run
none tmpfs 500M 0 500M 0% /var/lock
看到的是ext4文件系统是在/dev/sda7这个磁盘上的,但它作为实际的根文件系统,mount在"/"上了。
因为是双系统,还可以看到:
/dev/sda5 fuseblk 156G 141G 15G 91% /media/DATAPART
win下的磁盘都被linux挂在/media目录下了。
到这里,"/"终于出现了!
在mnt_init-->init_mount_tree:
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"); ns = create_mnt_ns(mnt); if (IS_ERR(ns)) panic("Can't allocate initial namespace"); init_task.nsproxy->mnt_ns = ns; get_mnt_ns(ns); root.mnt = ns->root; root.dentry = ns->root->mnt_root; set_fs_pwd(current->fs, &root); set_fs_root(current->fs, &root); }其中vfsmount结构体用来描述安装的文件系统;mnt_namespace描述命名空间;
分为3部分来分析这个函数:
1、mnt = do_kern_mount("rootfs", 0, "rootfs", NULL);这个是安装操作的核心;
struct vfsmount * do_kern_mount(const char *fstype, int flags, const char *name, void *data) { struct file_system_type *type = get_fs_type(fstype); struct vfsmount *mnt; if (!type) return ERR_PTR(-ENODEV); mnt = vfs_kern_mount(type, flags, name, data); if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) && !mnt->mnt_sb->s_subtype) mnt = fs_set_subtype(mnt, fstype); put_filesystem(type); return mnt; }1.1、首先根据“rootfs”这个标识文件系统类型的字符串在file_systems为表头的单向链表中查找文件系统类型,获取rootfs文件系统的类型(rootfs_fs_type);
1.2、mnt = vfs_kern_mount(type, flags, name, data);
struct vfsmount * vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) { struct vfsmount *mnt; char *secdata = NULL; int error; if (!type) return ERR_PTR(-ENODEV); error = -ENOMEM; mnt = alloc_vfsmnt(name); if (!mnt) goto out; if (flags & MS_KERNMOUNT) mnt->mnt_flags = MNT_INTERNAL; if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { secdata = alloc_secdata(); if (!secdata) goto out_mnt; error = security_sb_copy_data(data, secdata); if (error) goto out_free_secdata; } error = type->get_sb(type, flags, name, data, mnt); if (error < 0) goto out_free_secdata; BUG_ON(!mnt->mnt_sb); WARN_ON(!mnt->mnt_sb->s_bdi); error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); if (error) goto out_sb; /* * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE * but s_maxbytes was an unsigned long long for many releases. Throw * this warning for a little while to try and catch filesystems that * violate this rule. This warning should be either removed or * converted to a BUG() in 2.6.34. */ WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " "negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; up_write(&mnt->mnt_sb->s_umount); free_secdata(secdata); return mnt; out_sb: dput(mnt->mnt_root); deactivate_locked_super(mnt->mnt_sb); out_free_secdata: free_secdata(secdata); out_mnt: free_vfsmnt(mnt); out: return ERR_PTR(error); }
1.2.1、mnt = alloc_vfsmnt(name);初始化struct vfsmount *mnt;结构体;
1.2.2、error = type->get_sb(type, flags, name, data, mnt);调用rootfs的get_sb方法rootfs_get_sb来获取超级块:
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); }get_sb_nodev函数主要步骤如下:
1.2.2.1、struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
set_anon_super获得一个未使用的次设备号dev,然后用主设备号0和次设备号dev设置s的s_dev字段
调用alloc_super函数来初始化s,然后对s这个super_block超级块的几个关键字段赋值:
s的s_dev字段就是前面提到的设备号,s的s_type就是rootfs_fs_type这个file_system_type结构体类型的指针,
s的s_id字段放置文件系统类型的名称"rootfs",将新建的super_block对象加入以super_blocks为头的双向链表中,链接的字段是struct
list_head s_list;
将s的s_instances字段加入rootfs的的fs_supers双向链表头,这里表明同一种文件系统类型可以有多个super_block,有多个实例,这些斗用fs_supers串起来。
1.2.2.2、调用rootfs的fill_super(ramfs_fill_super)来分配索引节点对象和对应的目录项对象,并填充超级块字段值。这里会建立rootfs的“/”目录项对象和索引节点对象。
sb->s_root = root; 这个root就是“/”目录项对象。
1.2.2.3、将mnt的mnt_sb指向刚建的super_block超级块对象,将mnt的mnt_root指向sb的s_root对象("/"的目录项对象)
1.2.3、
mnt->mnt_mountpoint = mnt->mnt_root; 安装树的根的目录项和安装点的目录项都指向前面的root(rootfs的"/"目录项对象)
mnt->mnt_parent = mnt; 将我们mount的文件系统指向自己。比如在/mnt/a下是mount了一块ext2的磁盘,在/mnt/a/b下又mount omfs文件系统,那么这里的parent就可 以指明这个关系。
2、ns = create_mnt_ns(mnt);
新建一个私有的命名空间(mnt_namespace),并添加root fs:
mnt->mnt_ns = new_ns;
new_ns->root = mnt;
list_add(&new_ns->list, &new_ns->root->mnt_list);
3、
root.mnt = ns->root;
root.dentry = ns->root->mnt_root;
set_fs_pwd(current->fs, &root);
set_fs_root(current->fs, &root);
将进程0的根目录和当前工作目录设备为根文件系统。
到目前我们看得rootfs都是基于内存的数据,要真正安装根文件系统,就要安装实际的文件系统。我们以磁盘的文件系统为例。
在系统初始化的最后部分:
start_kernel-->rest_init-->kernel_init-->prepare_namespace
1、把root_device_name变量设置为从启动参数"root"中获取的设备文件名。同样把ROOT_DEV变量设置为同一设备文件的主设备号和次设备号。
实际上代码中会优先将root_device_name和mtd ubi做对比,如果有这样的flash设备,就从flash上建立文件系统。
2、还是以磁盘说明,调用mount_root函数:
2.1、调用sys_mknod在rootfs初始根文件系统中创建设备文件/dev/root,其主次设备号与ROOT_DEV中的一样。
2.2、分配一个缓冲区并用文件系统类型名链表填充它。该链表通过启动参数"rootfstype"传送给内核,也可以通过file_systems为头的单向链表中获取元素建立。
2.3、扫描上面建立的链表,对每一种文件系统斗调用sys_mount在根目录上安装给定的文件系统类型。但是由于每种文件系统都有自己的magic,在get_sb时候会从
物理设备的特定位置读到magic,这个magic实在mkfs的时候写入物理设备的。因为magic的存在,所以大多数文件系统不可用,只有一个例外,就是用根设备上实际 使用过的文件系统的函数来填充超级块的那个调用,该文件系统安装在rootfs文件系统的/root目录。
3、
sys_mount(".", "/", NULL, MS_MOVE, NULL);
sys_chroot(".");
移动rootfs文件系统目录上的已安装文件系统的安装点。
注意的是:rootfs文件系统没有卸载,只是隐藏在基于磁盘(磁盘或flash这种存储介质)的根文件系统下了。
举个例子说明:
在pc的ubuntu下,
lrwxrwxrwx 1 root root 4 2012-04-03 14:46 /dev/root -> sda7
sda7是安装ubuntu的盘
df -TH结果如下:
Filesystem Type Size Used Avail Use% Mounted on
/dev/sda7 ext4 27G 24G 1011M 97% /
none devtmpfs 494M 716K 493M 1% /dev
none tmpfs 500M 1.3M 499M 1% /dev/shm
none tmpfs 500M 384K 500M 1% /var/run
none tmpfs 500M 0 500M 0% /var/lock
看到的是ext4文件系统是在/dev/sda7这个磁盘上的,但它作为实际的根文件系统,mount在"/"上了。
因为是双系统,还可以看到:
/dev/sda5 fuseblk 156G 141G 15G 91% /media/DATAPART
win下的磁盘都被linux挂在/media目录下了。
到这里,"/"终于出现了!
相关文章推荐
- linux文件系统的系统分析--(三)rootfs的安装
- linux文件系统的系统分析--(三)rootfs的安装
- Linux--安装过程中的根文件系统的分析
- linux文件系统的系统分析--(四)sysfs的安装和挂载
- Linux下oracle11gR2系统安装到数据库建立配置及最后oracle的dmp文件导入一站式操作记录
- linux系统下怎么安装.deb文件?
- 安装Linux系统及合理划分文件系统
- Linux下NFS(网络文件系统)的安装与配置方法
- linux文件系统的系统分析--(一)vfs和数据结构
- linux文件系统的系统分析--(十三)sysfs和设备模型--Device
- Linux启动过程之内核挂载内存文件系统和真正根文件系统原因及过程分析
- Linux--根文件系统的挂载过程分析
- 全面了解安装使用Linux下的日志文件系统
- linux 2.6.11内核文件IO的系统调用实现分析--再续
- 一个设想:基于colinux,去厚重虚拟化,共盘直接文件系统安装运行的windows,linux
- VMware安装Linux,出现错误-未找到要在其中创建新文件系统
- linux系统下,以.run为后缀的文件的安装与卸载
- Linux 内核文件系统与设备操作流程分析
- linux文件系统启动分析(转载)
- 安装Linux系统及合理划分文件系统