Linux根目錄的檔案系統是如何被掛載的

2021-10-03 12:43:41 字數 4090 閱讀 8173

首先看下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...