522
京東網上商城
linux文件係統(二)——VFS四個主要對象的實現
聲明:本Linux文件係統博客,共分四節,是根據網上多個相關博客,以及自己的理解加上相關資料總結而成。(作者:lvyilong316)
VFS采用的是麵向對象的設計思想,使用一簇數據結構來代表通用文件對象。所有內核中的數據結構都使用C結構體實現。
1.superblock(超級塊)對象
保存一個掛在的文件係統的相關信息(Stores information concerning a mounted filesystem. For disk-based filesystems, this object usually corresponds to a filesystem control block stored on disk.)
(1)超級塊用來描述特定文件係統的信息。它存放在磁盤特定的扇區中 ,它在使用的時候將信息存在於內存中。
(2)當內核對一個文件係統進行初始化和注冊時在內存為其分配一個超級塊,這就是VFS超級塊。即,VFS超級塊是各種具體文件係統在安裝時建立的,並在這些文件係統卸載時被自動刪除 。
1.1 數據結構
(3)超級塊對象由結構體 super_block來體現。VFS超級塊的數據結構為 super_block在include/linux/fs.h中可以查看
struct super_block {
…….
};
我們先來看一個圖,再來具體解釋:
其中主要的數據成員和解釋如下:
(1) s_list :所有的超級塊形成一個雙聯表,s_list.prev和s_list.next分別指向與當前超級塊相鄰的前一個元素和後一個元素。
(2) s_lock :保護鏈表免受多處理器係統上的同時訪問。
(3) s_fs_info: 字段指向具體文件係統的超級塊。
例如:超級塊對象指的是Ext2文件係統,該字段就指向ext2_sb_info數據結構。
(4) s_dirt :來表示該超級塊是否是髒的,也就是說,磁盤上的數據是否必須要更新。
(5) 超級塊對象是通過函數alloc_super()創建並初始化的。在文件係統安裝時,內核會調用該函數以便從磁盤讀取文件係統超級塊,並且將其信息填充到內存中的超級塊對象中 。
1.2操作定義
超級對象中最重要的就是s_op,每一種文件係統都應該有自己的super_operations操作實例。它指向超級塊的操作函數表, 它由struct super_operations結構體來表示。
現在來看一下它的定義:它的定義在 include/linux/fs.h頭文件中可以看到
1560struct super_operations {
1561 struct inode *(*alloc_inode)(struct super_block *sb);
1562 void (*destroy_inode)(struct inode *);
1563
1564 void (*dirty_inode) (struct inode *);
1565 int (*write_inode) (struct inode *, struct writeback_control *wbc);
1566 int (*drop_inode) (struct inode *);
1567 void (*evict_inode) (struct inode *);
1568 void (*put_super) (struct super_block *);
1569 void (*write_super) (struct super_block *);
1570 int (*sync_fs)(struct super_block *sb, int wait);
1571 int (*freeze_fs) (struct super_block *);
1572 int (*unfreeze_fs) (struct super_block *);
1573 int (*statfs) (struct dentry *, struct kstatfs *);
1574 int (*remount_fs) (struct super_block *, int *, char *);
1575 void (*umount_begin) (struct super_block *);
1576
1577 int (*show_options)(struct seq_file *, struct vfsmount *);
1578 int (*show_stats)(struct seq_file *, struct vfsmount *);
1579#ifdef CONFIG_QUOTA
1580 ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
1581 ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
1582#endif
1583 int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
1584};
(1) 可以看到該結構體中的每一項都是一個指向超級塊操作函數的指針,超級塊操作函數執行文件係統和索引節點的底層操作。
(2)當文件係統需要對超級塊執行操作時,要在超級塊對象中尋找需要的操作方法。
例如:一個文件係統要寫自己的超級塊,需要調用:
sturct super_block * sb;
sb->s_op->write_super(sb);
sb是指向文件係統超級塊的指針,沿著該指針進入超級塊操作函數表,並從表中取得writ_super()函數,該函數執行寫入超級塊的實際操作。
說明:
盡管writ_super()方法來自超級塊,但是在調用時,還是要把超級塊作為參數傳遞給它。因為沒有C++的this指針。
(3)具體操作說明
struct inode * alloc_inode(struct super_block * sb) :創建和初始化一個新的索引結點。
void destroy_inode(struct super_block *sb) :釋放指定的索引結點 。
void dirty_inode(struct inode *inode) :VFS在索引節點被修改時會調用此函數。
void write_inode(struct inode *inode, struct writeback_control *wbc) 將指定的inode寫回磁盤。
void drop_inode( struct inode * inode):刪除索引節點。
void put_super(struct super_block *sb) :用來釋放超級塊。
void write_super(struct super_block *sb):更新磁盤上的超級塊。
void sync_fs(struct super_block *sb,in wait):使文件係統的數據元素與磁盤上的文件係統同步,wait參數指定操作是否同步。
int statfs(struct super_block *sb,struct statfs *statfs):獲取文件係統狀態。把文件係統相關的統計信息放在statfs中。
2.VFS的索引節點(ls查看的信息)
(文件或目錄的靜態描述信息,不隨進程不同而變化)
(1) 保存一個文件的通用信息,每個inode有一個inode number,在文件係統中,一個inode number能夠唯一地標識一個文件(Stores general information about a specific file. For disk-based filesystems, this object usually corresponds to a file control block stored on disk. Each inode object is associated with an inode number, which uniquely identifies the file within the filesystem.)
(2) 文件係統處理文件或目錄時的所有信息都存放在稱為索引節點的數據結構中。文件名可以隨時改,但是索引節點對文件是唯一的(它是隨文件的存在而存在)。
(3) 具體文件係統的索引節點是存放在磁盤上的,是一種靜態結構,要使用它,必須將其調入內存,填寫 VFS的索引節點。VFS索引節點也稱為動態節點。(即索引節點僅當文件被訪問時才在內存中創建)
2.1數據結構
它的定義在 /include/linux/fs.h中有這個結構體的定義
struct inode {
……
};
還記的我們在終端下輸入命令:ls 命令後可以看到文件的信息,這些信息就是記錄在這裏的。這是為什麼呢?
我們知道,文件是由FCB(文件控製塊控製的),而具體到Linux下,文件是有索引節點結構控製的。所以在struct inode 裏存放了文件的基本信息。大家有沒有發現在怎麼在索引節點裏麵會包含超級塊的對象呢,有些人可能不明白了,先看看下麵的圖,再來解釋把。
從上麵對的圖我們可以看出索引節點 對象靠i_sb指回到了超級塊對象。
成員說明:
i_hash :為了提高查找inode的效率,每一個inode都會有一個hash值。該字段指向hash值相同的inode所形成的雙鏈表該字段包含prev和next兩個指針,分別指向上述鏈表的前一個元素和後一個元素;
i_list :所有索引結點形成的雙聯表,(從圖上可以看出,索引節點對象是靠它來鏈接的)
i_dentry :所有引用該inode的目錄項將形成一個雙聯表,該字段即為這個雙聯表的頭結點
i_ino :索引結點號。通過ls -i命令可以查看文件的索引節點號;
i_count :引用計數;
i_nlink :硬鏈接數。當該inode描述一個目錄時,這個值至少為2,代表.和..的數目;
(注:索引節點沒有軟連接數,軟連接會對應單獨的索引節點)
i_uid :inode所屬文件的擁有者的id,通過ls -n可查看擁有者id;
i_gid :inode所屬文件所在組的id,通過ls -n可查看組id;
i_rdev :如果該inode描述的是一個設備文件,此值為設備號;
i_blkbits :以位為單位的塊大小;
i_atime :文件最近一次被訪問的時間。通過ls -lu可查看該時間;
i_mtime :文件最近一次被修改的時間,這裏的修改隻文件內容被修改。通過ls -l可查看該時間;
i_ctime :文件最近一次被修改的時間,這裏的修改除了指文件內容被修改外,更強調的是文件的屬性被修改。通過ls -lc可查看該時間;
i_blocks :文件使用塊的個數,通過ls -s可以查看該某個文件的塊使用數目;
i_mode :文件的訪問權限;
i_op : 指向索引結點操作結構體的指針;
i_fop : 指向文件操作街頭體的指針;
i_sb : 指向inode所屬文件係統的超級塊的指針;
i_pipe :如果inode所代表的文件是一個管道,則使用該字段;
i_bdev :如果inode所代表的文件是一個塊設備,則使用該字段;
i_cdev :如果inode所代表的文件是一個字符設備,則使用該字段;
i_state : 索引節點的狀態信息。
說明:
(1) 在同一個文件係統中,每個索引節點號都是唯一的,內核可以根據索引節點號的散列值來查找其inode結構。
(2) inode中有兩個設備號i_dev和i_rdev。
a. 除特別文件外,每個節點都存儲在某個設備上,這就是i_dev。
b. 如果索引節點所代表的並不是常規文件,而是某個設備,則需要另一個設備號,這就是i_rdev。
(3) 對i_state的說明:
每個VFS索引節點都會複製磁盤索引節點包含的一些數據,比如文件占有的磁盤數。如果i_state 的值等於I_DIR,該索引節點就是“髒“的。也就是說,對應的磁盤索引節點必須被更新。
(4) 三個重要的雙向鏈表:
a.未用索引節點鏈表,正在使用索引節點鏈表和髒索引節點鏈表。每個索引節點對象總是出現在上麵三種的一個。
b.這3個鏈表都是通過索引節點的i_list 域鏈接在一起的。
c.屬於“正在使用“或“髒“鏈表的索引節點對象也同時存放在一個散列表中。
(4) 一個索引節點代表文件係統中的一個文件,它也可以是設備或管道這樣的特殊文件。所以在索引節點結構體中有一些和特殊文件相關的項。
(6) 有時候某些文件係統並不能完整地包含索引節點結構體要求的所有信息。那麼此時剛怎麼辦呢?
此時,可以給它賦一些其它的值。例如:一個文件係統可能並不記錄文件的訪問時間,這時就可以在i_atime中存儲0。
(7) i_list和i_sb_list的區別
a.i_list:VFS中使用四個鏈表來管理不同狀態的inode結點。inode_unused將當前未使用的inode鏈接起來,inode_in_use將當前正在被使用的inode鏈接起來,超級塊中的s_dirty將所有髒inode鏈接起來,i_hash將所有hash值相同的inode鏈接起來。i_list中包含prev和next兩個指針,分別指向與當前inode處於同一個狀態鏈表的前後兩個元素
b.i_sb_list:每個文件係統中的inode都會形成一個雙聯表,這個雙鏈表的頭結點存放在超級塊的s_inodes中。而該字段中的prev和next指針分別指向在雙鏈表中與其相鄰的前後兩個元素
c.索引結點中i_sb_list鏈表是鏈接一個文件係統中所有inode的鏈表,因此相鄰的inode之間均會由此鏈表鏈接;而i_list鏈接的是處於同一個狀態的所有inode。所以,相鄰inode之間並不一定鏈接在一起。
2.2操作說明
與索引節點關聯的方法叫索引節點操作表,它是在 struct inode_operations這個結構體中具體描述的。它的定義在 include/linux/fs.h頭文件中定義。
1516struct inode_operations {
1517 int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
1518 struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
1519 int (*link) (struct dentry *,struct inode *,struct dentry *);
1520 int (*unlink) (struct inode *,struct dentry *);
1521 int (*symlink) (struct inode *,struct dentry *,const char *);
1522 int (*mkdir) (struct inode *,struct dentry *,int);
1523 int (*rmdir) (struct inode *,struct dentry *);
1524 int (*mknod) (struct inode *,struct dentry *,int,dev_t);
1525 int (*rename) (struct inode *, struct dentry *,
1526 struct inode *, struct dentry *);
1527 int (*readlink) (struct dentry *, char __user *,int);
1528 void * (*follow_link) (struct dentry *, struct nameidata *);
1529 void (*put_link) (struct dentry *, struct nameidata *, void *);
1530 void (*truncate) (struct inode *);
1531 int (*permission) (struct inode *, int);
1532 int (*check_acl)(struct inode *, int);
1533 int (*setattr) (struct dentry *, struct iattr *);
1534 int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *);
1535 int (*setxattr) (struct dentry *, const char *,const void *,size_t,int);
1536 ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
1537 ssize_t (*listxattr) (struct dentry *, char *, size_t);
1538 int (*removexattr) (struct dentry *, const char *);
1539 void (*truncate_range)(struct inode *, loff_t, loff_t);
1540 long (*fallocate)(struct inode *inode, int mode, loff_t offset,
1541 loff_t len);
1542 int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
1543 u64 len);
1544};
現在我們對其中一些重要的結果進行分析:
create() :如果該inode描述一個目錄文件,那麼當在該目錄下創建或打開一個文件時,內核必須為這個文件創建一個inode。VFS通過調用該inode的i_op->create()函數來完成上述新inode的創建。該函數的第一個參數為該目錄的 inode,第二個參數為要打開新文件的dentry,第三個參數是對該文件的訪問權限。如果該inode描述的是一個普通文件,那麼該inode永遠都不會調用這個create函數;
lookup() :查找指定文件的dentry;
link :用於在指定目錄下創建一個硬鏈接。這個link函數最終會被係統調用link()調用。該函數的第一個參數是原始文件的dentry,第二個參數即為上述指定目錄的inode,第三個參數是鏈接文件的dentry。
symlink ():在某個目錄下新建軟連接(符號鏈接),第一個參數是原始文件所在目錄的inode,第二個參數是原始文件的dentry,第三個參數是符號鏈接的名字(const char *)。
(關於硬鏈接,軟連接與dentry和inode的關係以及的具體創建參考後麵)
unlink ():在某個目錄下刪除dentry指定的索引節點對象。這個unlink函數最終會被係統調用unlink()調用。 第一個參數即為上述硬鏈接所在目錄的inode,第二個參數為要刪除文件的dentry。
(可以看到硬鏈接的創建就是dentry的創建,刪除就是刪除一個dentry)
mkdir:在指定的目錄下創建一個子目錄,當前目錄的inode會調用i_op->mkdir()。該函數會被係統調用mkdir()調用。第一個參數即為指定目錄的inode,第二個參數為子目錄的dentry,第三個參數為子目錄權限;(目錄與子目錄是通過目錄inode中的dentry鏈相連的,而子目錄的dentry又指向子目錄自身的inode)
rmdir ():從inode所描述的目錄中刪除一個指定的子目錄時,該函數會被係統調用rmdir()最終調用;
mknod() :在指定的目錄下創建一個特殊文件,比如管道、設備文件或套接字等。
說明:
1. 對於不同的文件係統,上麵的每個函數的具體實現是不同的,也不是每個函數都必須實現,沒有實現的函數對應的域應當設置為NULL 。
2. 上麵我們說了兩個主要的操作對像:superblock和inode。它們兩個對象中都包含一個操作對象。super_operations和inode_opetations它們有什麼區別呢
a.super_operations對象:其中包括內核針對特定文件係統所有調用的方法。
b.inode_operations對象: 其中包括內核對特定文件的所有調用的方法。
所以它們一個是針對文件係統,一個是針對文件 。
3.本來inode中應該包括“目錄節點”的名稱,但由於硬鏈接的存在,導致一個物理文件可能有多個文件名,因此把和“目錄節點”名稱相關的部分從 inode 中分開,放在一個專門的 dentry 結構(目錄項)中。
3.VFS 中的目錄項對象
為了方便查找,VFS引入了目錄項,每個dentry代表路徑中的一個特定部分。目錄項也可包括安裝點。 可能還是不明白,沒關係,看看老外怎麼說的——保存一個目錄的鏈接信息(Stores information about the linking of a directory entry (that is, a particular name of the file) with the corresponding file. Each disk-based filesystem stores this information in its own particular way on disk.)個人理解:描述一個文件和一個名字的對應關係,或者說dentry就是一個“文件名”。
3.1數據結構
目錄項對象由dentry結構體表示 ,定義在文件linux/dcache.h 頭文件中。
struct dentry {
……
};
說明:
1.索引節點中的i_dentry指向了它目錄項,目錄項中的d_alias,d_inode又指會了索引節點對象,目錄項中的d_sb又指回了超級塊對象。
2.我們可以看到不同於VFS 中的索引節點對象和超級塊對象,目錄項對象中沒有對應磁盤的數據結構,所以說明目錄項對象並沒有真正標存在磁盤上,那麼它也就沒有髒標誌位。
3.目錄項的狀態(被使用,未被使用和負狀態)
它們是靠d_count的值來進行區分的,當d_count為正值說明目錄項處於被使用狀態。當d_count=0時表示該目錄項是一個未被使用的目錄項, 但其d_inode指針仍然指向相關的的索引節點。該目錄項仍然包含有效的信息,隻是當前沒有人引用他。d_count=NULL表示負(negative)狀態,與目錄項相關的inode對象不複存在(相應的磁盤索引節點可能已經被刪除),dentry對象的d_inode 指針為NULL。但這種dentry對象仍然保存在dcache中,以便後續對同一文件名的查找能夠快速完成。這種dentry對象在回收內存時將首先被釋放。
4. d_subdirs:如果當前目錄項是一個目錄,那麼該目錄下所有的子目錄(一級子目錄)形成一個鏈表。該字段是這個鏈表的表頭;
5. d_child:如果當前目錄項是一個目錄,那麼該目錄項通過這個字段加入到父目錄的d_subdirs鏈表當中。這個字段中的next和prev指針分別指向父目錄中的另外兩個子目錄;
6. d_alias:一個inode可能對應多個目錄項,所有的目錄項形成一個鏈表。inode結構中的i_dentry即為這個鏈表的頭結點。當前目錄項以這個字段處於i_dentry鏈表中。該字段中的prev和next指針分別指向與該目錄項同inode的其他兩個(如果有的話)目錄項。
3.2dentry和inode的區別
inode(可理解為ext2 inode)對應於物理磁盤上的具體對象,dentry是一個內存實體,其中的d_inode成員指向對應的inode。也就是說,一個inode可以在運行的時候鏈接多個dentry,而d_count記錄了這個鏈接的數量。所謂"文件", 就是按一定的形式存儲在介質上的信息,所以一個文件其實包含了兩方麵的信息,一是存儲的數據本身,二是有關該文件的組織和管理的信息。在內存中, 每個文件都至少有一個dentry(目錄項)和inode(索引節點)結構,dentry記錄著文件名,上級目錄等信息,正是它形成了我們所看到的樹狀結構;而有關該文件的組織和管理的信息主要存放inode裏麵,它記錄著文件在存儲介質上的位置與分布。同時dentry->d_inode指向相應的inode結構。dentry與inode是多對一的關係,因為有可能一個文件有好幾個文件名(硬鏈接)。
3.3 操作定義
對目錄項進行操作的一組函數叫目錄項操作表,由dentry_operation結構描述。它可以在 include/linux/dcache.h 中查到
134struct dentry_operations {
135 int (*d_revalidate)(struct dentry *, struct nameidata *);
136 int (*d_hash) (struct dentry *, struct qstr *);
137 int (*d_compare) (struct dentry *, struct qstr *, struct qstr *);
138 int (*d_delete)(struct dentry *);
139 void (*d_release)(struct dentry *);
140 void (*d_iput)(struct dentry *, struct inode *);
141 char *(*d_dname)(struct dentry *, char *, int);
142};
(1) int d_reavlidate(struct dentry *dentry ,int flags) 該函數判斷目錄對象是否有效。VFS準備從dcache中使用一個目錄項時,會調用該函數.
(2) int d_hash(struct dentry *dentry ,struct qstr *name):該目錄生成散列值,當目錄項要加入到散列表時,VFS要調用此函數。
(3) int d_compare( struct dentry *dentry, struct qstr *name1, struct qstr *name2) 該函數來比較name1和name2這兩個文件名。使用該函數要加dcache_lock鎖。
(4) int d_delete(struct dentry *dentry):當d_count=0時,VFS調用次函數。使用該函數要叫 dcache_lock鎖。
(5) void d_release(struct dentry *dentry):當該目錄對象將要被釋放時,VFS調用該函數。
(6) void d_iput(struct dentry *dentry,struct inode *inode)當一個目錄項丟失了其索引節點時,VFS就掉用該函數。
4.VFS中的文件對象 (與進程有關)
保存一個打開的文件與一個進程的關係(Stores information about the interaction between an open file and a process. This information exists only in kernel memory during the period when a process has the file open.)
1.文件對象表示進程已經打開的文件 在內存中的表示,該對象不是物理上的文件。它是由相應的open()係統調用創建,由close()係統調用銷毀。多個進程可以打開和操作同一個文件,所以同一個文件也可能存在多個對應的文件對象。
2一個文件對應的文件對象不是唯一的,但對應的索引節點和超級塊對象是唯一的。
3.file結構中保存了文件位置,此外,還把指向該文件索引節點的指針也放在其中。
4.1數據結構
file結構形成一個雙鏈表,稱為係統打開文件表 。它的定義在 include/linux/fs.h 中可以看到
struct file {
……
};
1.文件對象實際上沒有對應的磁盤數據,所以在結構體中沒有代表其對象是否為髒,是否需要寫回磁盤的標誌。文件對象通過f_path.dentry指針指向相關的目錄項對象。目錄項會指向相關的索引節點,索引節點會記錄文件是否是髒的。
2.fu_list:每個文件係統中以被打開的文件都會形成一個雙聯表,這個雙聯表的頭結點存放在超級塊的s_files字段中。該字段的prev和next指針分別指向在鏈表中與當前文件結構體相鄰的前後兩個元素.
說明:
file結構中主要保存了文件當前的偏移量,此外還把指向該文件索引節點的指針也放在其中。有人就問了,問什麼不直接把文件位置存放在索引節點中呢?
因為:Linux中的文件是能夠共享的,假如把文件位置存放在索引節點中,當有兩個或更多個進程同時打開一個文件時,它們將去訪問同一個索引節點,那麼一個進程的lseek操作將影響到另一個進程的讀操作,這顯然是致命的錯誤。
4.2 操作定義
對文件進行操作的一組函數叫文件操作表,由file_operations結構定義:可以在include/linux/fs.h 中查看
1488struct file_operations {
1489 struct module *owner;
1490 loff_t (*llseek) (struct file *, loff_t, int);
1491 ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
1492 ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
1493 ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1494 ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
1495 int (*readdir) (struct file *, void *, filldir_t);
1496 unsigned int (*poll) (struct file *, struct poll_table_struct *);
1497 long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
1498 long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
1499 int (*mmap) (struct file *, struct vm_area_struct *);
1500 int (*open) (struct inode *, struct file *);
1501 int (*flush) (struct file *, fl_owner_t id);
1502 int (*release) (struct inode *, struct file *);
1503 int (*fsync) (struct file *, int datasync);
1504 int (*aio_fsync) (struct kiocb *, int datasync);
1505 int (*fasync) (int, struct file *, int);
1506 int (*lock) (struct file *, int, struct file_lock *);
1507 ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
1508 unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
1509 int (*check_flags)(int);
1510 int (*flock) (struct file *, int, struct file_lock *);
1511 ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
1512 ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
1513 int (*setlease)(struct file *, long, struct file_lock **);
1514};
(1) owner:用於指定擁有這個文件操作結構體的模塊,通常取THIS_MODULE;
(2) llseek:用於設置文件的偏移量。第一個參數指明要操作的文件,第二個參數為偏移量,第三個參數為開始偏移的位置(可取SEEK_SET,SEEK_CUR和SEEK_END之一)。
(3) read:從文件中讀數據。第一個參數為源文件,第二個參數為目的字符串,第三個參數指明欲讀數據的總字節數,第四個參數指明從源文件的某個偏移量處開始讀數據。由係統調用read()調用;
(4) write:往文件裏寫數據。第一個參數為目的文件,第二個參數源字符串,第三個參數指明欲寫數據的總字節數,第四個參數指明從目的文件的某個偏移量出開始寫數據。由係統調用write()調用;
(5) mmap:將指定文件映射到指定的地址空間上。由係統調用mmap()調用;
(6) open:打開指定文件,並且將這個文件和指定的索引結點關聯起來。由係統調用open()調用;
(7) release:釋放以打開的文件,當打開文件的引用計數(f_count)為0時,該函數被調用;
(8) fsync():文件在緩衝的數據寫回磁盤
5.四大VFS對象總結
1、超級塊對象和inode對象分別對應有物理數據,在磁盤上有靜態信息。而目錄項對象和文件對象描述的是一種關係,前者描述的文件與文件名的關係,後者描述的是進程與文件的關係,所以沒有對應物理數據。
eg:有三個不同的進程打開同一個文件,其中有兩個進程使用了相同的硬鏈接。三個進程擁有各自的file object,而隻有兩個dentry(同一個硬鏈接對應一個dentry,dentry不隨進程打開文件而增加或改變)。兩個dentry都指向同一個inode。
2、進程每打開一個文件,就會有一個file結構與之對應。同一個進程可以多次打開同一個文件而得到多個不同的file結構,file結構描述被打開文件的屬性,如文件的當前偏移量等信息。
3、兩個不同的file結構可以對應同一個dentry結構。進程多次打開同一個文件時,對應的隻有一個dentry結構。
4、在存儲介質中,每個文件對應唯一的inode結點,但是每個文件又可以有多個文件名。即可以通過不同的文件名訪問同一個文件。這裏多個文件名對應一個文件的關係在數據結構中表示就是dentry和inode的關係。
4)Inode中不存儲文件的名字,它隻存儲節點號;而dentry則保存有名字和與其對應的節點號,所以就可以通過不同的dentry訪問同一個inode。
5)不同的dentry則是同個文件鏈接(ln命令)來實現的。
最後更新:2017-04-03 12:55:35