首先看下mnt_init方法:
// fs/namespace.c
void __init mnt_init(void)
看下其init_rootfs方法:
// init/do_mounts.c
static struct file_system_type rootfs_fs_type = ;
int __init init_rootfs(void)
該方法主要是用來註冊rootfs檔案系統。
再看下init_mount_tree方法:
// fs/namespace.c
static void __init init_mount_tree(void)
該方法首先拿到上面註冊的rootfs檔案系統,再呼叫vfs_kern_mount方法掛載該系統,然後將掛載結果mnt賦值給型別為struct path的變數root,同時將root.dentry賦值為mnt->mnt_root,即掛載的rootfs檔案系統的根目錄。
最後,設定當前程序的當前目錄和根目錄都為root。
看下vfs_kern_mount方法:
// fs/namespace.c
struct vfsmount *vfs_kern_mount(struct file_system_type *type,
int flags, const char *name,
void *data)
export_symbol_gpl(vfs_kern_mount);
先看下其fs_context_for_mount方法:
// fs/fs_context.c
struct fs_context *fs_context_for_mount(struct file_system_type *fs_type,
unsigned int sb_flags)
export_symbol(fs_context_for_mount);
繼續看alloc_fs_context方法:
// fs/fs_context.c
static struct fs_context *alloc_fs_context(struct file_system_type *fs_type,
struct dentry *reference,
unsigned int sb_flags,
unsigned int sb_flags_mask,
enum fs_context_purpose purpose)
由上可知,fc->fs_type指向的rootfs檔案系統型別裡並沒有init_fs_context方法,所以該方法就被賦值為legacy_init_fs_context,之後又呼叫了該方法。
// fs/fs_context.c
const struct fs_context_operations legacy_fs_context_ops = ;
/* * initialise a legacy context for a filesystem that doesn't support
* fs_context.
*/static int legacy_init_fs_context(struct fs_context *fc)
該方法的主要作用就是將fc->ops欄位設定為legacy_fs_context_ops。
繼續看下vfs_kern_mount的fc_mount方法:
// fs/namespace.c
struct vfsmount *fc_mount(struct fs_context *fc)
...}export_symbol(fc_mount);
該方法先呼叫了vfs_get_tree方法,看下:
// fs/super.c
int vfs_get_tree(struct fs_context *fc)
export_symbol(vfs_get_tree);
由上可知,fc->ops指向的值為legacy_fs_context_ops,所以,fc->ops->get_tree對應的方法為legacy_get_tree。
// fs/fs_context.c
static int legacy_get_tree(struct fs_context *fc)
該方法又呼叫了fc->fs_type->mount指向的方法,並將返回值賦值給fc->root,這樣,fc->root就指向了該檔案系統的跟目錄。
由上可知,fc->fs_type->mount指向的方法為rootfs_mount。
// init/do_mounts.c
static struct dentry *rootfs_mount(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data)
該方法中,fill變數被設定為ramfs_fill_super方法,然後該方法又呼叫了mount_nodev方法。
// fs/super.c
struct dentry *mount_nodev(struct file_system_type *fs_type,
int flags, void *data,
int (*fill_super)(struct super_block *, void *, int))
export_symbol(mount_nodev);
該方法先建立乙個struct super_block例項,再呼叫fill_super指向的方法為該例項賦值,最後返回s->s_root指向的值,即:該檔案系統的根目錄。
由上可知,fill_super指向的方法為ramfs_fill_super。
// fs/ramfs/inode.c
int ramfs_fill_super(struct super_block *sb, void *data, int silent)
該方法先呼叫ramfs_get_inode方法建立並初始化乙個inode,再呼叫d_make_root方法生成乙個dentry,並將inode的值賦值給dentry的d_inode欄位。
生成的dentry例項最後被賦值給了sb->s_root,這樣sb->s_root就指向了該檔案系統的根目錄。
返回上面的fc_mount方法,通過呼叫vfs_get_tree方法,fc->root的值就指向了rootfs檔案系統的根目錄。
再看下fc_mount中的的vfs_create_mount方法:
// fs/namespace.c
struct vfsmount *vfs_create_mount(struct fs_context *fc)
export_symbol(vfs_create_mount);
由該方法可以看到,mnt->mnt.mnt_root被設定為fc->root,即rootfs檔案系統的根目錄。
fc_mount方法呼叫完畢之後退回到vfs_kern_mount方法,vfs_kern_mount方法呼叫完畢之後退回到init_mount_tree,而在上文也講到了,init_mount_tree方法裡會把root.dentry的值設定為mnt->mnt_root,即rootfs檔案系統的根目錄,再之後將root的值賦值給當前程序的當前目錄和根目錄字段。
這樣,rootfs檔案系統的整個掛載過程就結束了,最終的結果就是,當前程序的根目錄就是rootfs檔案系統的根目錄。
那rootfs檔案系統的根目錄就是我們想要找的根目錄嗎?
當然不是,我們要找的根目錄應該在硬碟上啊。
那硬碟上的檔案系統的根目錄是在**掛載的呢?硬碟上的檔案系統和rootfs檔案系統又是什麼關係呢?
限於篇幅原因,我們下篇文章再講
Linux的檔案系統,根目錄rootfs結構
檔案系統時作業系統用來管理檔案的。fs filesystem。在linux中,一切皆為檔案,這句話夠經典了吧。linux中每個分割槽都是乙個fs。linux下的filesystem hierarchy standard 檔案系統層次化標準 樹形結構。標準來說,都是基於fhs3.0,裡面詳細解釋了每個...
Linux 檔案系統目錄
檔案系統時作業系統的重要組成部分,主要負責管理磁碟檔案的輸入輸出。檔案通過目錄方式進行組織,目錄結構是檔案存放在磁碟等儲存裝置上的組織方式,目錄提供了乙個管理檔案的乙個方便而有效的途徑。linux目錄採用多級樹形結構。目錄存放的檔案 bin 放置的是在單使用者模式下也能夠被操作的指令 boot 主要...
linux檔案系統目錄
bin 存放著一百多個linux下常用的命令 工具 dev 存放著linux下所有的裝置檔案 home 使用者主目錄,每建乙個使用者,就會在這裡新建乙個與使用者同名的目錄,給該使用者乙個自己的空間 lost found 顧名思義,一些丟失的檔案可能可以在這裡找到 mnt 外部裝置的掛接點,通常用cd...