文件系统安装预备知识

就像每个传统的Unix系统一样,Linux也使用系统的根文件系统(system's root filesystem):它由内核在引导阶段直接安装,并拥有系统初始化脚本以及最基本的系统程序。

 

其他文件系统要么由初始化脚本安装,要么由用户直接安装在已安装文件系统的目录上。作为一个目录树,每个文件系统都拥有自己的根目录(root directory)。安装文件系统的这个目录称之为安装点(mount point)。已安装文件系统属于安装点目录的一个子文件系统。例如,/proc虚拟文件系统是系统的根文件系统的孩子(且系统的根文件系统是/proc的父亲)。已安装文件系统的根目录隐藏了父文件系统的安装点目录原来的内容,而且父文件系统的整个子树位于安装点之下。

 

文件系统的根目录有可能不同于进程的根目录:进程的根目录是与“/”路径对应的目录。缺省情况下,进程的根目录与系统的根文件系统的根目录一致(更准确地说是与进程的命名空间中的根文件系统的根目录一致,这个是重点,我们下面要讨论),但是可以通过调用chroot()系统调用改变进程的根目录。

 

1 命名空间

 

在传统的Unix系统中,只有一个已安装文件系统树:从系统的根文件系统开始,每个进程通过指定合适的路径名可以访问已安装文件系统中的任何文件。从这个方面考虑,Linux 2.6更加的精确:每个进程可拥有自己的已安装文件系统树——叫做进程的命名空间(namespace)。

 

一般来说,整个系统的命名空间只有一个,被大多数进程共享,即位于系统的根文件系统且被init进程使用的已安装文件系统树。不过,如果clone()系统调用以CLONE_NEWNS标志创建一个新进程,那么进程将获取一个新的命名空间。换句话说,如果父进程没有以CLONE_NEWNS标志创建这些子进程,命名空间将由随后的子进程继承。

 

当进程安装或卸载一个文件系统时,仅修改它的命名空间。因此,所做的修改对共享同一命名空间的所有进程都是可见的,并且也只对它们可见。进程甚至可通过使用Linux特有的pivot_root()系统调用来改变它的命名空间的根文件系统。

 

进程的命名空间由进程描述符的namespace字段指向的namespace结构描述:
struct namespace {
 atomic_t  count;                           /* 引用计数器(共享命名空间的进程数) */
 struct vfsmount * root;                /* 命名空间根目录的已安装文件系统描述符 */
 struct list_head list;                     /* 所有已安装文件系统描述符(vfsmount)链表的头 */
 wait_queue_head_t poll;            /* 命名空间等待队列 */
 int event;                                    /* 事件 */
};

 

list字段是双向循环链表的头,该表聚集了属于命名空间的所有已安装文件系统。root字段表示已安装文件系统,它是这个命名空间的已安装文件系统树的根。接下来我们将看到的,已安装文件系统由vfsmount结构描述。

 

2 文件系统安装数据结构

 

在大多数传统的类Unix内核中,每个文件系统只能安装一次。假定存放在/dev/fd0磁盘上的Ext2文件系统通过如下命令安装在目录/flp下:
      mount -t ext2 /dev/fd0 /flp

 

在用umount命令卸载该文件系统前,所有其他作用于/dev/fd0的安装命令都会失败。然而,Linux有所不同:同一个文件系统被安装多次是可能的。当然,如果一个文件系统安装了n次,那么它的根目录就可通过n个安装点来访问。尽管同一文件系统可以通过不同的安装点来访问,但是文件系统的的确确是唯一的。因此,不管一个文件系统被装了多少次,都仅有一个超级块对象。

 

那么,安装的文件系统形成一个层次:一个文件系统的安装点可能成为第二个文件系统的目录,而第二个文件系统又安装在第三个文件系统之上,等等。

 

把多个安装堆叠在一个单独的安装点上也是可能的。尽管已经使用先前安装下的文件和目录的进程可以继续使用,但在同一安装点上的新安装隐藏前一个安装的文件系统。当最顶层的安装被删除时,下一层的安装再一次变为可见的。

 

你可以想像,跟踪已安装的文件系统很快会变为一场恶梦。对于每个安装操作,内核必须在内存中保存安装点和安装标志,以及要安装文件系统与其他已安装文件系统之间的关系。所以,我们需要一个保留安装信息的数据结构来理清这些关系。这样的信息保存在已安装文件系统描述符中;每个描述符是一个具有vfsmount类型的数据结构:


struct vfsmount {
 struct list_head mnt_hash;         /* 用于散列表链表的指针 */
 struct vfsmount *mnt_parent;    /* 指向父文件系统,这个文件系统安装在其上 */
 struct dentry *mnt_mountpoint; /* 指向这个文件系统安装点目录的dentry */
 struct dentry *mnt_root;            /* 指向这个文件系统根目录的dentry */
 struct super_block *mnt_sb;      /* 指向这个文件系统的超级块对象 */
 struct list_head mnt_mounts;    /* 包含所有文件系统描述符链表的头(相对于这个文件系统) */
 struct list_head mnt_child;        /* 用于已安装文件系统链表mnt_mounts的指针 */
 atomic_t mnt_count;                 /* 引用计数器(增加该值以禁止文件系统被卸载) */
 int mnt_flags;                           /* 标志 */
 int mnt_expiry_mark;               /* 如果文件系统标记为到期,那么就设置该标为true
                                                  *(如果设置了该标志,并且没有任何人

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值