一文講解VFS的數(shù)據(jù)結構
每個VFS對象都存放在一個適當?shù)臄?shù)據(jù)結構中,其中包括對象的屬性和指定對象方法表的指針。內(nèi)核可以動態(tài)地修改對象的方法,因此可以為對象建立專用的行為。下面我們來具體的看一下VFS中的數(shù)據(jù)結構。
超級塊對象(super_block)
? ? 超級塊用來描述整個文件系統(tǒng)的信息。對每個具體的文件系統(tǒng)來說,都有各自的超級塊,如Ext2超級塊,它們存放于磁盤上。當內(nèi)核在對一個文件系統(tǒng)進行初始化和注冊時在內(nèi)存為其分配一個超級塊,這就是VFS超級塊。也就是說,VFS超級塊是在文件系統(tǒng)安裝時建立的,并在這些文件系統(tǒng)卸載時被自動刪除,可見,VFS超級塊只存在于內(nèi)存中。看一下超級塊在內(nèi)核中的數(shù)據(jù):
s_list; ?指向超級塊的指針,超級塊是個雙向循環(huán)鏈表,通常我們通過list_entry宏來獲取s_list所在超級塊結構體的地址。超級塊鏈表的頭結點是變量super_blocks,sb_lock自旋鎖保護鏈表免受多處理器系統(tǒng)上的同時訪問。 s_dev; ?具體文件系統(tǒng)的塊設備標志符,比如,ext2文件系統(tǒng)所在設備為磁盤,則該設備號即為該磁盤在系統(tǒng)中的設備號。 s_dirt; ?修改臟標識,超級塊在內(nèi)存中被修改后,該標志為1,則修改后的超級塊必須寫回磁盤. s_blocksize_bits; ? 以位為單位的塊大小。例如,如果塊大小為1024字節(jié),則該值為10. s_blocksize; ? ?以字節(jié)為單位的塊大小,該值即代表這個塊的具體大小. s_maxbytes; ? 文件的最長長度。 *s_type; ? ? 指向具體文件系統(tǒng)的文件系統(tǒng)類型。 *s_op; ? ? ?超級塊方法。 *dq_op; ? ?磁盤限額處理方法。 *s_qcop; ? ?磁盤限額管理方法。 *s_export_op;網(wǎng)絡文件系統(tǒng)使用的輸出操作。 s_flags; ? ? 安裝文件系統(tǒng)時的標志,記錄比如只讀或可讀可寫等這樣的標志。 s_root:該文件系統(tǒng)根目錄的目錄項結構指針。利用該根目錄項,可以訪問到這個文件系統(tǒng)中的任何一個文件。 s_count:對該超級塊的引用計數(shù); s_lock: 超級塊信號量; s_inodes:該文件系統(tǒng)中所有的索引結點形成一個雙鏈表,該字段存放這個鏈表的頭結點; s_files:該文件系統(tǒng)中所有已被打開的文件形成一個雙鏈表,該字段存放這個鏈表的頭結點; s_instances:某個具體文件系統(tǒng)中所有超級塊會組成一個雙鏈表。這個鏈表的頭結點為super_block,頭結點定義在該文件系統(tǒng)對應的file_system_type結構體中; s_id[32]:文件系統(tǒng)的名稱。比如ext3文件系統(tǒng),該值為“ext3”;
與超級塊關聯(lián)的方法就是超級塊操作,這些操作是super_operations來描述的,該結構的起始地址存放在超級塊的s_op字段中。
【文章福利】小編推薦自己的Linux內(nèi)核技術交流群:【891587639】整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)? ?


alloc_inode(sb):為索引結點分配空間,包括具體文件系統(tǒng)的的數(shù)據(jù)所需要的空間。 destroy_inode(inode):釋放指定的索引結點; write_inode(inode,flag):將指定的inode寫回磁盤,用于指定inode的更新;flag參數(shù)表示I/O操作是否同步; drop_inode(inode):移走指定的inode,與write_inode成對出現(xiàn); delete_inode(inode) : ?在必須撤銷索引結點時調(diào)用,刪除內(nèi)存中的VFS索引結點和磁盤上的文件數(shù)據(jù)及元數(shù)據(jù)。 put_super(super):釋放指定的超級塊,文件系統(tǒng)被卸載時使用; write_super(super):如果該超級塊被修改,即s_dirt為1時,則要將超級塊寫回磁盤,同時還要將s_dirt重設為0; 當文件系統(tǒng)需要對其所對應的超級塊進行操作時,就應該使用超級塊操作類中的具體函數(shù)。比如,定義sb為指向某個超級塊的指針,如果該超級塊需要將自己寫回磁盤,則這樣調(diào)用:sb->s_op->write_super(sb); 可以看到,雖然write_super函數(shù)是由sb所指的超級塊所調(diào)用的,但是仍然將sb傳遞給write_super函數(shù)。
索引節(jié)點對象:
? 文件系統(tǒng)處理文件所需要的所有信息都存放在稱為索引結點的 數(shù)據(jù)結構中,文件名可以隨時更改,但是索引結點對文件是唯一的,并且隨文件的存在而存在。具體文件系統(tǒng)的索引結點是存放在磁盤上的,是一種靜態(tài)結構,要使用它。必須調(diào)用內(nèi)存,填寫VFS的索引結點。VFS的主要域定義如下:
i_hash:為了提高查找正在被使用的inode的效率,每一個inode都會有一個hash值,所有hash值相同的inode形成一個雙鏈表。該字段包含prev和next兩個指針,分別指向上述鏈表的前一個元素和后一個元素; i_list:VFS中使用四個鏈表來管理不同狀態(tài)的inode結點。inode_unused將當前未使用的inode鏈接起來,inode_in_use將當前正在被使用的inode鏈接起來,超級塊中的s_dirty將所有臟inode鏈接起來,i_hash將所有hash值相同的inode鏈接起來。i_list中包含prev和next兩個指針,分別指向與當前inode處于同一個狀態(tài)鏈表的前后兩個元素。 i_sb_list:每個文件系統(tǒng)中的inode都會形成一個雙聯(lián)表,這個雙鏈表的頭結點存放在超級塊的s_inodes中。而該字段中的prev和next指針分別指向在雙鏈表中與其相鄰的前后兩個元素; i_dentry:所有引用該inode的目錄項將形成一個雙聯(lián)表,該字段即為這個雙聯(lián)表的頭結點; i_ino:索引結點號。通過ls -l命令可以查看文件的索引節(jié)點號; i_count:引用計數(shù); i_nlink:硬鏈接數(shù)。當該inode描述一個目錄時,這個值至少為2,代表.和..的數(shù)目; 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:文件最近一次被修改的時間,這里的修改只文件內(nèi)容被修改。通過ls -l可查看該時間; i_ctime:文件最近一次被修改的時間,這里的修改除了指文件內(nèi)容被修改外,更強調(diào)的是文件的屬性被修改。通過ls -lc可查看該時間; i_blocks:文件使用塊的個數(shù),通過ls -s可以查看該某個文件的塊使用數(shù)目; i_mode:文件的訪問權限; i_op:指向索引結點操作結構體的指針; i_fop:指向文件操作結構體的指針,這個字段用來初始化文件結構體(struct file)中的f_op字段; i_sb:指向inode所屬文件系統(tǒng)的超級塊的指針; i_pipe:如果inode所代表的文件是一個管道,則使用該字段; i_bdev:如果inode所代表的文件是一個塊設備,則使用該字段; i_cdev:如果inode所代表的文件是一個字符設備,則使用該字段;
每個索引結點對象總是出現(xiàn)在下列雙向循環(huán)鏈表的某個鏈表中(所有情況下,指向相鄰元素的指針存放在i_list字段中):有效未使用的索引結點鏈表、正在使用的索引結點鏈表、臟索引結點的鏈表。
與索引結點對象相關聯(lián)的方法叫索引結點操作:
create():創(chuàng)建一個新的磁盤索引結點。 lookup():查詐一個索引結點所在的目錄。 link():創(chuàng)建一個新的硬鏈接。 unlink():刪除一個硬鏈接。 symlink():為符號鏈接創(chuàng)建一個新的索引結點。 mkdir():為目錄項創(chuàng)建一個新的索引結點。
