EXT4檔案系統學習(14)VFS之VFS inode
不同的檔案系統inode也不一樣,對inode的操作函式也不一樣,VFS inode的作用就是隱藏下面具體檔案系統的inode差異,向上層提供統一的介面。
inode
struct inode {
umode_t i_mode;
unsigned short i_opflags;
kuid_t i_uid;
kgid_t i_gid;
unsigned int i_flags;
#ifdef CONFIG_FS_POSIX_ACL
struct posix_acl *i_acl;
struct posix_acl *i_default_acl;
#endif
const struct inode_operations *i_op; 指定一組對inode的操作函式
struct super_block *i_sb;
struct address_space *i_mapping;
#ifdef CONFIG_SECURITY
void *i_security;
#endif
/* Stat data, not accessed from path walking */
unsigned long i_ino;
/*
* Filesystems may only read i_nlink directly. They shall use the
* following functions for modification:
*
* (set|clear|inc|drop)_nlink 硬連結數量
* inode_(inc|dec)_link_count
*/
union {
const unsigned int i_nlink;
unsigned int __i_nlink;
};
dev_t i_rdev;
loff_t i_size;
struct timespec i_atime;
struct timespec i_mtime;
struct timespec i_ctime;
spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */
unsigned short i_bytes;
unsigned int i_blkbits;
blkcnt_t i_blocks;
#ifdef __NEED_I_SIZE_ORDERED
seqcount_t i_size_seqcount;
#endif
/* Misc */
unsigned long i_state;
struct mutex i_mutex;
unsigned long dirtied_when; /* jiffies of first dirtying */
unsigned long dirtied_time_when;
struct hlist_node i_hash;
struct list_head i_wb_list; /* backing dev IO list */
struct list_head i_lru; /* inode LRU list */
struct list_head i_sb_list;
union {
struct hlist_head i_dentry;
struct rcu_head i_rcu;
};
u64 i_version;
atomic_t i_count; 引用計數
atomic_t i_dio_count;
atomic_t i_writecount;
#ifdef CONFIG_IMA
atomic_t i_readcount; /* struct files open RO */
#endif
const struct file_operations *i_fop; 指定對檔案內容本身的操作函式
struct file_lock_context *i_flctx;
struct address_space i_data;
struct list_head i_devices;
union {
struct pipe_inode_info *i_pipe;特殊檔案系統,如字元裝置
struct block_device *i_bdev;
struct cdev *i_cdev;
};
__u32 i_generation;
#ifdef CONFIG_FSNOTIFY
__u32 i_fsnotify_mask; /* all events this inode cares about */
struct hlist_head i_fsnotify_marks;
#endif
void *i_private; /* fs or device private pointer */
};
結構體大部分成員都是根據磁碟的inode初始化的,詳細見上一章。
根據inode編號獲取inode結構操作是很繁瑣的,因此核心使用hash表讓每一個inode通過i_hash連結到hash表。
VFS inode的i_op和i_fop指標操作具體檔案系統的inode,但是目錄檔案、連結檔案等是分開的,具體可分為4中情況:
普通檔案和目錄的inode_operations
- 普通檔案
const struct inode_operations ext4_file_inode_operations = {
.setattr = ext4_setattr,
.getattr = ext4_getattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
.get_acl = ext4_get_acl,
.set_acl = ext4_set_acl,
.fiemap = ext4_fiemap,
};
- 普通目錄
const struct inode_operations ext4_dir_inode_operations = {
.create = ext4_create, 建立檔案
.lookup = ext4_lookup,
.link = ext4_link, 硬連結
.unlink = ext4_unlink,
.symlink = ext4_symlink, 軟連結
.mkdir = ext4_mkdir, 建立目錄
.rmdir = ext4_rmdir,
.mknod = ext4_mknod, 建立裝置節點
.tmpfile = ext4_tmpfile,
.rename2 = ext4_rename2,
.setattr = ext4_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
.get_acl = ext4_get_acl,
.set_acl = ext4_set_acl,
.fiemap = ext4_fiemap,
};
普通檔案和目錄都有一個對應的inode結構,在某個目錄下建立一個檔案,會呼叫目錄對應的inode結構的ext4_create()函式,ext4_create()會呼叫__ext4_new_inode從磁碟上分配一個空閒的inode,同時初始化ext4記憶體中的inode機構。
建立一個子目錄,使用函式ext4_mkdir,也會呼叫__ext4_new_inode從磁碟上分配一個空閒的inode,同時初始化ext4記憶體中的inode機構。
連結檔案的inode_operations
普通檔案的定位:找到direntry,然後從direntry中的檔名讀出inode號,最後讀出inode資訊。
硬連結檔案:因為硬連結檔案的inode號與原始檔一致的,所以定位比較簡單。
軟連結檔案:需要特殊處理,由於inode號不一致,所以需要先讀取inode號獲取出原始檔的路徑,再根據路徑定位出目標檔案。如果目標檔案路徑小於60位元組,那麼稱為Fast Symbol link,因為這樣的話路徑資訊就直接儲存在inode所在的block,就不需要額外的block了。
const struct inode_operations ext4_fast_symlink_inode_operations = {
.readlink = generic_readlink, 在inode的block中讀出目標檔案路徑
.follow_link = ext4_follow_fast_link, 把對連結檔案的操作直接轉到目標檔案
.setattr = ext4_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
};
目標檔案路徑大於60位元組的,稱為普通符號連結,需要根據inode中的資料塊地址讀出目標檔案的地址:
const struct inode_operations ext4_symlink_inode_operations = {
.readlink = generic_readlink,
.follow_link = ext4_follow_link,
.put_link = ext4_put_link,
.setattr = ext4_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ext4_listxattr,
.removexattr = generic_removexattr,
};
多出一個put_link函式,且follow_link與快速連結不同,follow_link把inode地址對應的資料資料讀出到記憶體解析,處理我拿出後由put_link來釋放記憶體。
根據前面分析的ext4_fill_super函式中ext4_iget對檔案和目錄的i_fop賦值也是不一樣的,下面繼續分析i_fop:
檔案的file_operations
const struct file_operations ext4_file_operations = {
.llseek = ext4_llseek, 調整檔案讀寫指標
.read_iter = generic_file_read_iter,
.write_iter = ext4_file_write_iter,
.unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext4_compat_ioctl, 向裝置檔案傳送ioctl命令
#endif
.mmap = ext4_file_mmap,
.open = ext4_file_open,
.release = ext4_release_file,
.fsync = ext4_sync_file,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.fallocate = ext4_fallocate,
};
read使用的是通用檔案系統讀函式generic_file_read_iter,支援IOCB_DIRECT直接讀模式和快取模式,IOCB_DIRECT模式在open檔案時傳入模式引數,繞過快取直接對磁碟讀寫操作;使用快取模式是do_generic_file_read函式中體現,函式中會檢查資料是否已經快取,如果沒有就會預讀取,將資料載入入快取頁。
mmap函式把一個檔案內容對映到程式的虛擬地址空間中(利用頁表),這樣可以通過記憶體指標p[n]來訪問檔案內容。
open函式開啟檔案操作,建立相關的記憶體管理結構,如inode物件。
release函式減少檔案的引用計數,當引用計數為0時,會關閉檔案物件,同時釋放相關的記憶體管理結構。
fsync函式把記憶體中檔案內容資料寫入磁碟,splice_read/write用於管道操作。
目錄的dir_operations
const struct file_operations ext4_dir_operations = {
.llseek = ext4_dir_llseek,
.read = generic_read_dir,
.iterate = ext4_readdir,
.unlocked_ioctl = ext4_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = ext4_compat_ioctl,
#endif
.fsync = ext4_sync_file,
.release = ext4_release_dir,
};
read是一個空函式,為啥呢?
iterate是readdir函式,從目錄的資料塊中把目錄項讀出來,目錄項direntry資料塊中儲存了目錄下儲存的檔名資訊等。
總結
每當初始化一個inode時,設定好i_op和i_fop後,就能夠正確的找到這個檔案的操作函式,每個inode對應一個檔案,耶就能在磁碟中讀寫到這個檔案。
相關文章
- EXT4檔案系統學習(15)VFS之VFS 檔案/目錄物件物件
- EXT4檔案系統學習(9)VFS之磁碟結構inode和direntry
- EXT4檔案系統學習(13)VFS之VFS超級塊super_blockBloC
- EXT4檔案系統學習(11)VFS之記憶體結構sb和inode記憶體
- EXT4檔案系統學習(12)VFS之檔案系統物件file_system_type物件
- EXT4檔案系統學習(10)VFS之磁碟結構Group和superblockBloC
- Linux VFSLinux
- 理解Linux檔案系統之 inodeLinux
- Linux檔案系統iNode及stat命令Linux
- VFS簡介和核心操作函式函式
- 簡單瞭解EXT4檔案系統
- 恢復ext4檔案系統被誤刪的檔案
- 檔案系統(六):一文看懂linux ext4檔案系統工作原理Linux
- 深入理解 ext4 等 Linux 檔案系統Linux
- 如何系統學習C 語言(下)之 檔案篇
- ros學習檔案系統介紹ROS
- 在FreeBSD上mount Ext4檔案系統的行動硬碟硬碟
- NTFS、exFAT、FAT32、Ext4檔案系統的區別
- ext4和xfs檔案系統的擴容和收縮
- Linux 虛擬檔案系統四大物件:超級塊、inode、dentry、file之間關係Linux物件
- Hadoop學習(一)——HDFS分散式檔案系統Hadoop分散式
- 記憶體檔案系統的再學習記憶體
- Linux學習之檔案操作Linux
- Linux系統檔案學習內容多嗎?linux系統命令Linux
- Linux系統中檔案被刪除後的恢復方法(ext4)Linux
- Google分散式檔案系統GFS論文學習Go分散式
- (十七)Python學習之檔案操作Python
- python學習之讀寫檔案Python
- Linux EXT4檔案系統TF卡空間容量顯示和計算Linux
- 表`t`的INODE結構檔案分析
- 分散式檔案系統之 FastDFS分散式AST
- 【python系統學習17】python中的檔案讀寫Python
- C#學習 [型別系統] 記錄(14)C#型別
- Linux 檔案系統之入門必看!Linux
- 不點兒之Linux檔案系統Linux
- 『學了就忘』Linux檔案系統管理 — 57、Linux檔案系統介紹Linux
- Linux系統篇-檔案系統&虛擬檔案系統Linux
- 檔案和檔案系統