1.引言
本文所述關於文件管理的系列文章主要是對陳莉君老師所講述的文件系統管理知識講座的整理。
Linux可以支持不同的文件系統,它源於unix文件系統,也是unix文件系統的一大特色。
Linux文件系統1--概述 中我們了解了文件系統的作用,以及為了使得所有的文件系統能在同一個操作系統上工作,而產生的虛擬文件系統。
本章我們開始分析萬能的虛擬文件系統是怎么構成的,虛擬文件文件系統由四個主要的對象構成,分別是:超級塊,索引結點,目錄項,文件對象。
而所謂的文件系統主要是對文件對象進行管理,那么,其余的三個結構體是用來做什么的呢?
想一下,如果,你要查一份文件,必須要核對文件對象,那么文件對象越大,CPU則會浪費很多時間在核對上。
所以,我們給文件對象學着外國人一樣, 起了三層結構的名字,目錄項--索引結點--超級塊,是不是很有趣。
2.文件系統的四個主要對象概述
- 超級塊對象
存放系統中已安裝文件系統的信息
- 索引節點對象
存放關於具體文件的一般信息
- 目錄項對象
存放目錄項與對應文件進行鏈接的信息
- 文件對象
存放打開文件與進程之間進行交互的有關信息
3. 超級塊super_block
3.1 struct super_block
1 struct super_block { 2 struct list_head s_list; /* Keep this first 指向超級塊鏈表的指針*/ 3 dev_t s_dev; /* search index; _not_ kdev_t 具體文件系統的塊設備描述符*/ 4 unsigned char s_blocksize_bits; 5 unsigned long s_blocksize; /*以字節為單位的數據塊的大小*/ 6 loff_t s_maxbytes; /* Max file size */ 7 struct file_system_type *s_type; /*文件系統類型*/ 8 const struct super_operations *s_op; /*指向超級塊操作的函數集合*/ 9 const struct dquot_operations *dq_op; 10 const struct quotactl_ops *s_qcop; 11 const struct export_operations *s_export_op; 12 unsigned long s_flags; 13 unsigned long s_iflags; /* internal SB_I_* flags */ 14 unsigned long s_magic; 15 struct dentry *s_root; 16 struct rw_semaphore s_umount; 17 int s_count; 18 atomic_t s_active; 19 #ifdef CONFIG_SECURITY 20 void *s_security; 21 #endif 22 const struct xattr_handler **s_xattr; 23 24 struct hlist_bl_head s_anon; /* anonymous dentries for (nfs) exporting */ 25 struct list_head s_mounts; /* list of mounts; _not_ for fs use */ 26 struct block_device *s_bdev; 27 struct backing_dev_info *s_bdi; 28 struct mtd_info *s_mtd; 29 struct hlist_node s_instances; 30 unsigned int s_quota_types; /* Bitmask of supported quota types */ 31 struct quota_info s_dquot; /* Diskquota specific options */ 32 33 struct sb_writers s_writers; 34 35 char s_id[32]; /* Informational name */ 36 u8 s_uuid[16]; /* UUID */ 37 38 void *s_fs_info; /* Filesystem private info 具體文件系統的私有數據*/ 39 unsigned int s_max_links; 40 fmode_t s_mode; 41 42 /* Granularity of c/m/atime in ns. 43 Cannot be worse than a second */ 44 u32 s_time_gran; 45 46 /* 47 * The next field is for VFS *only*. No filesystems have any business 48 * even looking at it. You had been warned. 49 */ 50 struct mutex s_vfs_rename_mutex; /* Kludge */ 51 52 /* 53 * Filesystem subtype. If non-empty the filesystem type field 54 * in /proc/mounts will be "type.subtype" 55 */ 56 char *s_subtype; 57 58 /* 59 * Saved mount options for lazy filesystems using 60 * generic_show_options() 61 */ 62 char __rcu *s_options; 63 const struct dentry_operations *s_d_op; /* default d_op for dentries */ 64 65 /* 66 * Saved pool identifier for cleancache (-1 means none) 67 */ 68 int cleancache_poolid; 69 70 struct shrinker s_shrink; /* per-sb shrinker handle */ 71 72 /* Number of inodes with nlink == 0 but still referenced */ 73 atomic_long_t s_remove_count; 74 75 /* Being remounted read-only */ 76 int s_readonly_remount; 77 78 /* AIO completions deferred from interrupt context */ 79 struct workqueue_struct *s_dio_done_wq; 80 struct hlist_head s_pins; 81 82 /* 83 * Keep the lru lists last in the structure so they always sit on their 84 * own individual cachelines. 85 */ 86 struct list_lru s_dentry_lru ____cacheline_aligned_in_smp; 87 struct list_lru s_inode_lru ____cacheline_aligned_in_smp; 88 struct rcu_head rcu; 89 struct work_struct destroy_work; 90 91 struct mutex s_sync_lock; /* sync serialisation lock */ 92 93 /* 94 * Indicates how deep in a filesystem stack this SB is 95 */ 96 int s_stack_depth; 97 98 /* s_inode_list_lock protects s_inodes */ 99 spinlock_t s_inode_list_lock ____cacheline_aligned_in_smp; 100 struct list_head s_inodes; /* all inodes 所有的inodes*/ 101 };
- 超級塊用來描述整個文件系統的信息
- 每個具體的文件系統都有自己的超級塊
- VFS超級塊是各種文件系統在安裝時建立的,並在卸載時被自動刪除,其數據結構是super_block
- 所有超級塊對象都以雙向循環鏈表的形式鏈接在一起
圖 所有超級塊鏈接在一起
3.2 struct super_operations
圖 超級塊對象的操作函數
- 與超級塊關聯的方法就是超級塊操作表,這些操作是由struct super_operations來描述
3.3 打印超級塊信息
4.索引節點inode
4.1 struct inode
1 struct inode { 2 umode_t i_mode; 3 unsigned short i_opflags; 4 kuid_t i_uid; 5 kgid_t i_gid; 6 unsigned int i_flags; 7 8 #ifdef CONFIG_FS_POSIX_ACL 9 struct posix_acl *i_acl; 10 struct posix_acl *i_default_acl; 11 #endif 12 13 const struct inode_operations *i_op; 14 struct super_block *i_sb; 15 struct address_space *i_mapping; 16 17 #ifdef CONFIG_SECURITY 18 void *i_security; 19 #endif 20 21 /* Stat data, not accessed from path walking */ 22 unsigned long i_ino; 23 /* 24 * Filesystems may only read i_nlink directly. They shall use the 25 * following functions for modification: 26 * 27 * (set|clear|inc|drop)_nlink 28 * inode_(inc|dec)_link_count 29 */ 30 union { 31 const unsigned int i_nlink; 32 unsigned int __i_nlink; 33 }; 34 dev_t i_rdev; 35 loff_t i_size; 36 struct timespec i_atime; 37 struct timespec i_mtime; 38 struct timespec i_ctime; 39 spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ 40 unsigned short i_bytes; 41 unsigned int i_blkbits; 42 blkcnt_t i_blocks; 43 44 #ifdef __NEED_I_SIZE_ORDERED 45 seqcount_t i_size_seqcount; 46 #endif 47 48 /* Misc */ 49 unsigned long i_state; /*索引節點的狀態標志*/ 50 struct mutex i_mutex; 51 52 unsigned long dirtied_when; /* jiffies of first dirtying */ 53 unsigned long dirtied_time_when; 54 55 struct hlist_node i_hash; /*指向哈希鏈表的指針*/ 56 struct list_head i_io_list; /* backing dev IO list */ 57 #ifdef CONFIG_CGROUP_WRITEBACK 58 struct bdi_writeback *i_wb; /* the associated cgroup wb */ 59 60 /* foreign inode detection, see wbc_detach_inode() */ 61 int i_wb_frn_winner; 62 u16 i_wb_frn_avg_time; 63 u16 i_wb_frn_history; 64 #endif 65 struct list_head i_lru; /* inode LRU list 指向索引節點鏈表的指針*/ 66 struct list_head i_sb_list; /*指向超級塊的指針*/ 67 union { 68 struct hlist_head i_dentry; 69 struct rcu_head i_rcu; 70 }; 71 u64 i_version; 72 atomic_t i_count; 73 atomic_t i_dio_count; 74 atomic_t i_writecount; 75 #ifdef CONFIG_IMA 76 atomic_t i_readcount; /* struct files open RO */ 77 #endif 78 const struct file_operations *i_fop; /* former ->i_op->default_file_ops */ 79 struct file_lock_context *i_flctx; 80 struct address_space i_data; 81 struct list_head i_devices; 82 union { 83 struct pipe_inode_info *i_pipe; 84 struct block_device *i_bdev; 85 struct cdev *i_cdev; 86 char *i_link; 87 }; 88 89 __u32 i_generation; 90 91 #ifdef CONFIG_FSNOTIFY 92 __u32 i_fsnotify_mask; /* all events this inode cares about */ 93 struct hlist_head i_fsnotify_marks; 94 #endif 95 96 void *i_private; /* fs or device private pointer */ 97 };
- 文件系統處理文件所需要的所有信息都保存在稱為索引節點的inode結構體中
- 同一個文件系統中,每個文件的索引節點號都是唯一的
- 與索引節點關聯的方法由struct inode_operations來描述
- inode有兩個設備號:i_dev(常規文件的設備號),i_rdev(某一設備的設備號)
- LInux文件系統的另外一大特色:設備即文件。驅動中設備號的來源
4.2 struct inode_operations
圖 索引節點的操作函數
5.目錄項dentry
5.1 struct dentry
84 struct dentry { 85 /* RCU lookup touched fields */ 86 unsigned int d_flags; /* protected by d_lock */ 87 seqcount_t d_seq; /* per dentry seqlock */ 88 struct hlist_bl_node d_hash; /* lookup hash list */ 89 struct dentry *d_parent; /* parent directory */ 90 struct qstr d_name; 91 struct inode *d_inode; /* Where the name belongs to - NULL is 92 * negative */ 93 unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */ 94 95 /* Ref lookup also touches following */ 96 struct lockref d_lockref; /* per-dentry lock and refcount */ 97 const struct dentry_operations *d_op; 98 struct super_block *d_sb; /* The root of the dentry tree */ 99 unsigned long d_time; /* used by d_revalidate */ 100 void *d_fsdata; /* fs-specific data */ 101 102 union { 103 struct list_head d_lru; /* LRU list */ 104 wait_queue_head_t *d_wait; /* in-lookup ones only */ 105 }; 106 struct list_head d_child; /* child of parent list */ 107 struct list_head d_subdirs; /* our children */ 108 /* 109 * d_alias and d_rcu can share memory 110 */ 111 union { 112 struct hlist_node d_alias; /* inode alias list */ 113 struct hlist_bl_node d_in_lookup_hash; /* only for in-lookup ones */ 114 struct rcu_head d_rcu; 115 } d_u; 116 };
- 每個文件除了一個struct inode結構體外,還要一個目錄項struct dentry結構
- dentry代表的邏輯意義上的文件,描述的是文件邏輯上的屬性,目錄項對象在磁盤上並沒有對應的映像
- inode代表的是物理意義上的文件,記錄的是物理上的屬性,對於一個具體的文件系統,其inode在磁盤上有對應的映像
- 一個索引節點可能對應多個目錄項對象
5.2 struct dentry_operations
圖 目錄項的操作函數
6. 文件對象(file)
6.1 struct file
struct file { 836 union { 837 struct llist_node fu_llist;//文件對象鏈表 838 struct rcu_head fu_rcuhead; //釋放之后的RCU鏈表 839 } f_u; 840 struct path f_path; 841 struct inode *f_inode; /* cached value */ 842 const struct file_operations *f_op; 843 844 /* 845 * Protects f_ep_links, f_flags. 846 * Must not be taken from IRQ context. 847 */ 848 spinlock_t f_lock; 849 atomic_long_t f_count; //文件對象的使用計數 850 unsigned int f_flags; //當打開文件時所使用的標志 851 fmode_t f_mode; //文件的訪問模式 852 struct mutex f_pos_lock; 853 loff_t f_pos; //文件當前的位移量 854 struct fown_struct f_owner; //擁有者通過信號量進行異步I/O傳輸 855 const struct cred *f_cred; 856 struct file_ra_state f_ra; 857 858 u64 f_version; 859 #ifdef CONFIG_SECURITY 860 void *f_security; //安全模塊 861 #endif 862 /* needed for tty driver, and maybe others */ 863 void *private_data; //tty 設備驅動的鈎子 864 865 #ifdef CONFIG_EPOLL 866 /* Used by fs/eventpoll.c to link all the hooks to this file */ 867 struct list_head f_ep_links; //事件池鎖 868 struct list_head f_tfile_llink; 869 #endif /* #ifdef CONFIG_EPOLL */ 870 struct address_space *f_mapping; //頁緩存映射 871 } __attribute__((aligned(4))); /* lest something weird decides that 2 is OK */
- 進程通過文件描述符來訪問文件
- LInux用一個file文件對象來保存打開文件的位置,這個對象稱為打開的文件描述符
- file結構主要保存了文件位置,還把指向文件索引節點的指針也放在其中
- file結構形成一個雙鏈表,稱為系統打開文件表
6.2 struct file_operations
6.3 struct files_struct
- 文件描述符用來描述打開的文件
- 每個進程用一個files_struct結構來記錄文件描述符的使用情況
- 這個files_stuct結構稱為用戶打開文件表,它是進程的私有數據
圖 用戶打開文件表
6.4 struct fs_struct
8 struct fs_struct { 9 int users; 10 spinlock_t lock; 11 seqcount_t seq; 12 int umask; //用於為新創建的文件設置初始文件許可權限 13 int in_exec; 14 struct path root, pwd; 15 };
- 描述進程與文件系統的關系
7. 主要數據結構之間的關系
圖 主要數據結構之間的關系
- 超級塊是對一個文件系統的描述
- 索引節點是對一個文件物理屬性的描述
- 目錄項是對一個文件邏輯屬性的描述
- 一個進程所處的位置由fs_struct描述
- 一個進程(或用戶)打開的文件由files_struct描述
- 整個系統所打開的文件由 file結構來描述