日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

《Linux内核设计与实现》读书笔记(十三)- 虚拟文件系统

發布時間:2024/10/12 linux 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Linux内核设计与实现》读书笔记(十三)- 虚拟文件系统 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

虛擬文件系統(VFS)是linux內核和具體I/O設備之間的封裝的一層共通訪問接口,通過這層接口,linux內核可以以同一的方式訪問各種I/O設備。

虛擬文件系統本身是linux內核的一部分,是純軟件的東西,并不需要任何硬件的支持。

主要內容:

  • 虛擬文件系統的作用
  • 虛擬文件系統的4個主要對象
  • 文件系統相關的數據結構
  • 進程相關的數據結構
  • 小結

1. 虛擬文件系統的作用

虛擬文件系統(VFS)是linux內核和存儲設備之間的抽象層,主要有以下好處。

- 簡化了應用程序的開發:應用通過統一的系統調用訪問各種存儲介質

- 簡化了新文件系統加入內核的過程:新文件系統只要實現VFS的各個接口即可,不需要修改內核部分

?

2. 虛擬文件系統的4個主要對象

虛擬文件中的4個主要對象,具體每個對象的含義參見如下的詳細介紹。

2.1 超級塊

超級塊(super_block)主要存儲文件系統相關的信息,這是個針對文件系統級別的概念。

它一般存儲在磁盤的特定扇區中,但是對于那些基于內存的文件系統(比如proc,sysfs),超級塊是在使用時創建在內存中的。

?

超級塊的定義在:<linux/fs.h>

/* * 超級塊結構中定義的字段非常多,* 這里只介紹一些重要的屬性*/ struct super_block {struct list_head s_list; /* 指向所有超級塊的鏈表 */const struct super_operations *s_op; /* 超級塊方法 */struct dentry *s_root; /* 目錄掛載點 */struct mutex s_lock; /* 超級塊信號量 */int s_count; /* 超級塊引用計數 */struct list_head s_inodes; /* inode鏈表 */struct mtd_info *s_mtd; /* 存儲磁盤信息 */fmode_t s_mode; /* 安裝權限 */ };/** 其中的 s_op 中定義了超級塊的操作方法* 這里只介紹一些相對重要的函數*/ struct super_operations {struct inode *(*alloc_inode)(struct super_block *sb); /* 創建和初始化一個索引節點對象 */void (*destroy_inode)(struct inode *); /* 釋放給定的索引節點 */void (*dirty_inode) (struct inode *); /* VFS在索引節點被修改時會調用這個函數 */int (*write_inode) (struct inode *, int); /* 將索引節點寫入磁盤,wait表示寫操作是否需要同步 */void (*drop_inode) (struct inode *); /* 最后一個指向索引節點的引用被刪除后,VFS會調用這個函數 */void (*delete_inode) (struct inode *); /* 從磁盤上刪除指定的索引節點 */void (*put_super) (struct super_block *); /* 卸載文件系統時由VFS調用,用來釋放超級塊 */void (*write_super) (struct super_block *); /* 用給定的超級塊更新磁盤上的超級塊 */int (*sync_fs)(struct super_block *sb, int wait); /* 使文件系統中的數據與磁盤上的數據同步 */int (*statfs) (struct dentry *, struct kstatfs *); /* VFS調用該函數獲取文件系統狀態 */int (*remount_fs) (struct super_block *, int *, char *); /* 指定新的安裝選項重新安裝文件系統時,VFS會調用該函數 */void (*clear_inode) (struct inode *); /* VFS調用該函數釋放索引節點,并清空包含相關數據的所有頁面 */void (*umount_begin) (struct super_block *); /* VFS調用該函數中斷安裝操作 */ }; View Code

2.2 索引節點

索引節點是VFS中的核心概念,它包含內核在操作文件或目錄時需要的全部信息。

一個索引節點代表文件系統中的一個文件(這里的文件不僅是指我們平時所認為的普通的文件,還包括目錄,特殊設備文件等等)。

索引節點和超級塊一樣是實際存儲在磁盤上的,當被應用程序訪問到時才會在內存中創建。

?

索引節點定義在:<linux/fs.h>

/* * 索引節點結構中定義的字段非常多,* 這里只介紹一些重要的屬性*/ struct inode {struct hlist_node i_hash; /* 散列表,用于快速查找inode */struct list_head i_list; /* 索引節點鏈表 */struct list_head i_sb_list; /* 超級塊鏈表超級塊 */struct list_head i_dentry; /* 目錄項鏈表 */unsigned long i_ino; /* 節點號 */atomic_t i_count; /* 引用計數 */unsigned int i_nlink; /* 硬鏈接數 */uid_t i_uid; /* 使用者id */gid_t i_gid; /* 使用組id */struct timespec i_atime; /* 最后訪問時間 */struct timespec i_mtime; /* 最后修改時間 */struct timespec i_ctime; /* 最后改變時間 */const struct inode_operations *i_op; /* 索引節點操作函數 */const struct file_operations *i_fop; /* 缺省的索引節點操作 */struct super_block *i_sb; /* 相關的超級塊 */struct address_space *i_mapping; /* 相關的地址映射 */struct address_space i_data; /* 設備地址映射 */unsigned int i_flags; /* 文件系統標志 */void *i_private; /* fs 私有指針 */ };/** 其中的 i_op 中定義了索引節點的操作方法* 這里只介紹一些相對重要的函數*/ struct inode_operations {/* 為dentry對象創造一個新的索引節點 */int (*create) (struct inode *,struct dentry *,int, struct nameidata *);/* 在特定文件夾中尋找索引節點,該索引節點要對應于dentry中給出的文件名 */struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);/* 創建硬鏈接 */int (*link) (struct dentry *,struct inode *,struct dentry *);/* 從一個符號鏈接查找它指向的索引節點 */void * (*follow_link) (struct dentry *, struct nameidata *);/* 在 follow_link調用之后,該函數由VFS調用進行清除工作 */void (*put_link) (struct dentry *, struct nameidata *, void *);/* 該函數由VFS調用,用于修改文件的大小 */void (*truncate) (struct inode *); }; View Code

2.3 目錄項

和超級塊和索引節點不同,目錄項并不是實際存在于磁盤上的。

在使用的時候在內存中創建目錄項對象,其實通過索引節點已經可以定位到指定的文件,

但是索引節點對象的屬性非常多,在查找,比較文件時,直接用索引節點效率不高,所以引入了目錄項的概念。

?

路徑中的每個部分都是一個目錄項,比如路徑: /mnt/cdrom/foo/bar 其中包含5個目錄項,/ mnt cdrom foo bar

?

每個目錄項對象都有3種狀態:被使用,未使用和負狀態

- 被使用:對應一個有效的索引節點,并且該對象由一個或多個使用者

- 未使用:對應一個有效的索引節點,但是VFS當前并沒有使用這個目錄項

- 負狀態:沒有對應的有效索引節點(可能索引節點被刪除或者路徑不存在了)

?

目錄項的目的就是提高文件查找,比較的效率,所以訪問過的目錄項都會緩存在slab中。

slab中緩存的名稱一般就是 dentry,可以通過如下命令查看:

[wangyubin@localhost kernel]$ sudo cat /proc/slabinfo | grep dentry dentry 212545 212625 192 21 1 : tunables 0 0 0 : slabdata 10125 10125 0

?

目錄項定義在:<linux/dcache.h>

/* 目錄項對象結構 */ struct dentry {atomic_t d_count; /* 使用計數 */unsigned int d_flags; /* 目錄項標識 */spinlock_t d_lock; /* 單目錄項鎖 */int d_mounted; /* 是否登錄點的目錄項 */struct inode *d_inode; /* 相關聯的索引節點 */struct hlist_node d_hash; /* 散列表 */struct dentry *d_parent; /* 父目錄的目錄項對象 */struct qstr d_name; /* 目錄項名稱 */struct list_head d_lru; /* 未使用的鏈表 *//** d_child and d_rcu can share memory*/union {struct list_head d_child; /* child of parent list */struct rcu_head d_rcu;} d_u;struct list_head d_subdirs; /* 子目錄鏈表 */struct list_head d_alias; /* 索引節點別名鏈表 */unsigned long d_time; /* 重置時間 */const struct dentry_operations *d_op; /* 目錄項操作相關函數 */struct super_block *d_sb; /* 文件的超級塊 */void *d_fsdata; /* 文件系統特有數據 */unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* 短文件名 */ };/* 目錄項相關操作函數 */ struct dentry_operations {/* 該函數判斷目錄項對象是否有效。VFS準備從dcache中使用一個目錄項時會調用這個函數 */int (*d_revalidate)(struct dentry *, struct nameidata *);/* 為目錄項對象生成hash值 */int (*d_hash) (struct dentry *, struct qstr *);/* 比較 qstr 類型的2個文件名 */int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);/* 當目錄項對象的 d_count 為0時,VFS調用這個函數 */int (*d_delete)(struct dentry *);/* 當目錄項對象將要被釋放時,VFS調用該函數 */void (*d_release)(struct dentry *);/* 當目錄項對象丟失其索引節點時(也就是磁盤索引節點被刪除了),VFS會調用該函數 */void (*d_iput)(struct dentry *, struct inode *);char *(*d_dname)(struct dentry *, char *, int); }; View Code

2.4 文件對象

文件對象表示進程已打開的文件,從用戶角度來看,我們在代碼中操作的就是一個文件對象。

文件對象反過來指向一個目錄項對象(目錄項反過來指向一個索引節點)

其實只有目錄項對象才表示一個已打開的實際文件,雖然一個文件對應的文件對象不是唯一的,但其對應的索引節點和目錄項對象卻是唯一的。

?

文件對象的定義在: <linux/fs.h>

/* * 文件對象結構中定義的字段非常多,* 這里只介紹一些重要的屬性*/ struct file {union {struct list_head fu_list; /* 文件對象鏈表 */struct rcu_head fu_rcuhead; /* 釋放之后的RCU鏈表 */} f_u;struct path f_path; /* 包含的目錄項 */const struct file_operations *f_op; /* 文件操作函數 */atomic_long_t f_count; /* 文件對象引用計數 */ };/** 其中的 f_op 中定義了文件對象的操作方法* 這里只介紹一些相對重要的函數*/ struct file_operations {/* 用于更新偏移量指針,由系統調用lleek()調用它 */loff_t (*llseek) (struct file *, loff_t, int);/* 由系統調用read()調用它 */ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);/* 由系統調用write()調用它 */ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);/* 由系統調用 aio_read() 調用它 */ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);/* 由系統調用 aio_write() 調用它 */ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);/* 將給定文件映射到指定的地址空間上,由系統調用 mmap 調用它 */int (*mmap) (struct file *, struct vm_area_struct *);/* 創建一個新的文件對象,并將它和相應的索引節點對象關聯起來 */int (*open) (struct inode *, struct file *);/* 當已打開文件的引用計數減少時,VFS調用該函數 */int (*flush) (struct file *, fl_owner_t id); }; View Code

2.5 四個對象之間關系圖

上面分別介紹了4種對象分別的屬性和方法,下面用圖來展示這4個對象的和VFS之間關系以及4個對象之間的關系。

(這個圖是根據我自己的理解畫出來的,如果由錯誤請幫忙指出,謝謝!)

?

?

3. 文件系統相關的數據結構

處理上面4個主要的對象之外,VFS中還有2個專門針對文件系統的2個對象,

- struct file_system_type: 用來描述文件系統的類型(比如ext3,ntfs等等)

- struct vfsmount??????? : 描述一個安裝文件系統的實例

?

file_system_type 結構體位于:<linux/fs.h>

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; }; View Code

?

每種文件系統,不管由多少個實例安裝到系統中,還是根本沒有安裝到系統中,都只有一個 file_system_type 結構。

?

當文件系統被實際安裝時,會在安裝點創建一個 vfsmount 結構體。

結構體代表文件系統的實例,也就是文件系統被安裝幾次,就會創建幾個 vfsmount

vfsmount 的定義參見:<linux/mount.h>

struct vfsmount {struct list_head mnt_hash; /* 散列表 */struct vfsmount *mnt_parent; /* 父文件系統,也就是要掛載到哪個文件系統 */struct dentry *mnt_mountpoint; /* 安裝點的目錄項 */struct dentry *mnt_root; /* 該文件系統的根目錄項 */struct super_block *mnt_sb; /* 該文件系統的超級塊 */struct list_head mnt_mounts; /* 子文件系統鏈表 */struct list_head 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; /* 到期鏈表的入口 */struct list_head mnt_share; /* 共享安裝鏈表的入口 */struct list_head mnt_slave_list;/* 從安裝鏈表 */struct list_head mnt_slave; /* 從安裝鏈表的入口 */struct vfsmount *mnt_master; /* 從安裝鏈表的主人 */struct mnt_namespace *mnt_ns; /* 相關的命名空間 */int mnt_id; /* 安裝標識符 */int mnt_group_id; /* 組標識符 *//** 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 */int mnt_pinned; /* "釘住"進程計數 */int mnt_ghosts; /* "鏡像"引用計數 */ #ifdef CONFIG_SMPint *mnt_writers; /* 寫者引用計數 */ #elseint mnt_writers; /* 寫者引用計數 */ #endif }; View Code

4. 進程相關的數據結構

以上介紹的都是在內核角度看到的 VFS 各個結構,所以結構體中包含的屬性非常多。

而從進程的角度來看的話,大多數時候并不需要那么多的屬性,所有VFS通過以下3個結構體和進程緊密聯系在一起。

- struct files_struct? :由進程描述符中的 files 目錄項指向,所有與單個進程相關的信息(比如打開的文件和文件描述符)都包含在其中。

- struct fs_struct???? :由進程描述符中的 fs 域指向,包含文件系統和進程相關的信息。

- struct mmt_namespace :由進程描述符中的 mmt_namespace 域指向。

?

struct files_struct 位于:<linux/fdtable.h>

struct files_struct {atomic_t count; /* 使用計數 */struct fdtable *fdt; /* 指向其他fd表的指針 */struct fdtable fdtab;/* 基 fd 表 */spinlock_t file_lock ____cacheline_aligned_in_smp; /* 單個文件的鎖 */int next_fd; /* 緩存下一個可用的fd */struct embedded_fd_set close_on_exec_init; /* exec()時關閉的文件描述符鏈表 */struct embedded_fd_set open_fds_init; /* 打開的文件描述符鏈表 */struct file * fd_array[NR_OPEN_DEFAULT]; /* 缺省的文件對象數組 */ }; View Code

struct fs_struct 位于:<linux/fs_struct.h>

struct fs_struct {int users; /* 用戶數目 */rwlock_t lock; /* 保護結構體的讀寫鎖 */int umask; /* 掩碼 */int in_exec; /* 當前正在執行的文件 */struct path root, pwd; /* 根目錄路徑和當前工作目錄路徑 */ };

?

struct mmt_namespace 位于:<linux/mmt_namespace.h>

但是在2.6內核之后似乎沒有這個結構體了,而是用 struct nsproxy 來代替。

以下是 struct task_struct 結構體中關于文件系統的3個屬性。

struct task_struct 的定義位于:<linux/sched.h>

/* filesystem information */struct fs_struct *fs; /* open file information */struct files_struct *files; /* namespaces */struct nsproxy *nsproxy;

?

5. 小結

VFS 統一了文件系統的實現框架,使得在linux上實現新文件系統的工作變得簡單。

目前linux內核中已經支持60多種文件系統,具體支持的文件系統可以查看 內核源碼 fs 文件夾下的內容。

轉載于:https://www.cnblogs.com/GoogleGetZ/p/7424690.html

總結

以上是生活随笔為你收集整理的《Linux内核设计与实现》读书笔记(十三)- 虚拟文件系统的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。