在虛擬文件系統的支持下,Linux可以支持迄今爲止的大多數文件系統。但是,Linux並不是在初始化時就把所有文件系統全部都裝入,而只是安裝一個文件系統(通常是Ext2)作爲根文件系統。根文件系統在整個系統運行過程中是不能被拆卸的,是系統的基本組成部分。通常,根文件系統上主要安裝了保證系統正常工作運行的操作系統代碼文件以及若干語言編譯程序、命令解釋程序和相應的命令處理程序等文件。其他文件系統則都定義成可安裝模塊,以便用戶需要時動態地進行安裝。
所謂安裝,就是在虛擬文件系統中建立一個超級塊super_block,並用被安裝文件系統超級塊中的相關信息填寫super_block,然後用被安裝文件系統的根目錄代替系統現有目錄結構的一個空目錄,從而把子系統與原文件系統連接起來。
爲使系統在安裝之前瞭解待安裝文件子系統的基本信息(例如超級塊的位置),必須向系統文件註冊表提交一個數據結構進行註冊。
把一個文件系統安裝到根文件系統的一個節點上的示意圖如下所示:
文件系統的註冊
由於不同的文件系統具有不同的特點,因此其安裝過程也不盡相同。爲了正確地安裝一個文件系統,被安裝的文件系統在安裝之前必須向系統進行註冊,以便使系統感知和了解待安裝文件系統的類型及安裝相關的信息。
系統通過調用文件的初始化例程來填寫一個叫做file_system_type的數據結構,並調用函數register_filesystem()把該數據結構加入到由系統維護的已註冊文件系統的鏈表中。如下圖所示:
數據結構file_system_type的定義如下:
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;
};
文件系統的安裝與卸載
當系統試圖安裝一個子文件系統時,系統會調用函數mount()首先在文件系統註冊鏈表中查找與用戶提供名稱相匹配的註冊文件系統,如果找到,則在該文件系統的file_system_type中獲得與文件系統對應的超級塊的指針,並用超級塊中的相關信息填寫系統分配給該系統的VFS超級塊,並把這個超級塊加入到VFS超級塊鏈表中。
接下來就要填寫一個系統分配給該文件系統的vfsmount數據結構,以保存已被安裝的文件系統的基本安裝信息,從而把該文件系統的根節點安裝到選定的VFS索引節點上。vfsmount結構的定義如下:
struct vfsmount {
struct list_head mnt_hash;
struct vfsmount *mnt_parent; /* 本系統所掛接的父文件系統 */
struct dentry *mnt_mountpoint; /* 掛接點的dentry結構 */
struct dentry *mnt_root; /* 本系統的根目錄 */
struct super_block *mnt_sb; /* pointer to superblock */
struct list_head mnt_mounts; /* list of children, anchored here */
struct list_head mnt_child; /* and going through their mnt_child */
int mnt_flags;
/* 4 bytes hole on 64bits arches */
const char *mnt_devname; /* 設備名稱 e.g. /dev/dsk/hda1 */
struct list_head mnt_list;
struct list_head mnt_expire; /* link in fs-specific expiry list */
struct list_head mnt_share; /* circular list of shared mounts */
struct list_head mnt_slave_list;/* list of slave mounts */
struct list_head mnt_slave; /* slave list entry */
struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */
struct mnt_namespace *mnt_ns; /* containing namespace */
int mnt_id; /* mount identifier */
int mnt_group_id; /* peer group identifier */
/*
* We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
* to let these frequently modified fields in a separate cache line
* (so that reads of mnt_flags wont ping-pong on SMP machines)
*/
atomic_t mnt_count;
int mnt_expiry_mark; /* true if marked for expiry */
int mnt_pinned;
int mnt_ghosts;
/*
* This value is not stable unless all of the mnt_writers[] spinlocks
* are held, and all mnt_writer[]s on this mount have 0 as their ->count
*/
atomic_t __mnt_writers;
};
所有已經被安裝的系統都有一個對應的vfsmount數據結構,結構中的指針mnt_mountpoint指向掛接點的目錄,而指針mut_root指向被安裝系統的根目錄,所以結構vfsmount是子系統與父系統之間的橋樑。該數據結構一旦被填寫,系統便認爲該結構所對應的文件系統已經被安裝。
所以,已經被安裝的系統的vfsmount數據結構,在系統中也是用一個鏈表來管理的。
拆卸一個文件子系統的過程基本與安裝的過程相反。系統首先驗證文件子系統是否爲可拆卸的:如果該文件子系統的文件正在被使用,則該系統時不可拆卸的;否則,釋放該文件子系統所佔用的VFS超級塊和安裝點,從而卸下該文件子系統。