linux kernel 2009-07-14 16:30:37 閱讀83 評(píng)論0 字號(hào):大中小 訂閱
前面說過,只要知道文件的索引節(jié)點(diǎn)號(hào),就可以得到那個(gè)文件。但是我們?cè)诓僮魑募r(shí),從沒聽說誰會(huì)拿著索引節(jié)點(diǎn)號(hào)來操作文件,我們只知道文件名而已。它們是如何"和諧"起來的呢?linux把目錄也看成一種文件,里面記錄著文件名與索引節(jié)點(diǎn)號(hào)的對(duì)應(yīng)關(guān)系。比如在ext3文件系統(tǒng)中,如果文件是一個(gè)目錄,那么它的內(nèi)容就是一系列ext3_dir_entry_2的結(jié)構(gòu)
struct ext3_dir_entry_2 {
__u32 inode; /* Inode number */
__u16 rec_len; /* Directory entry length */
__u8 name_len; /* Name length */
__u8 file_type;
char name[EXT3_NAME_LEN]; /* File name */
};
舉個(gè)例子,比如要打開/home/test/hello.c。首先,找到‘/’,讀入其內(nèi)容,找到名為"home"的文件的索引節(jié)點(diǎn)號(hào),打開/home這個(gè) "文件",讀入內(nèi)容,找到名為 "test" 的的文件的索引節(jié)點(diǎn)號(hào),同理,再打開文件"/home/test",找到找到名為"hello.c”的文件的索引節(jié)點(diǎn)號(hào),最后就得到 /home/test/hello.c了。這就是path_walk()函數(shù)的原理。
其中,根據(jù)一個(gè)文件夾的inode,和一個(gè)文件名來獲取該文件的inode結(jié)構(gòu)的函數(shù),就叫l(wèi)ookup,它是inode_operations里面的函數(shù)。
struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
lookup,顧名思義,就是查找,比如查查在test這個(gè)文件夾下,有沒有叫hello.c的文件,有的話,就從存儲(chǔ)介質(zhì)中讀取其inode結(jié)構(gòu)。并用dentry- >d_inode指向它。所以,我們只要知道了文件的路徑和名字,總可以從根目錄開始,一層一層的往下走,定位到某一個(gè)文件。
superblock與vfsmount
接下來還要介紹兩個(gè)數(shù)據(jù)結(jié)構(gòu),superblock和vfsmount。super_block結(jié)構(gòu)是從所有具體的文件系統(tǒng)所抽象出來的一個(gè)結(jié)構(gòu),每一個(gè)文件系統(tǒng)實(shí)例都會(huì)有一對(duì)應(yīng)super_block結(jié)構(gòu)。比如每一個(gè)ext2的分區(qū)就有一個(gè)super_block結(jié)構(gòu),它記錄了該文件系統(tǒng)實(shí)例(分區(qū))的某些描述性的信息,比如該文件系統(tǒng)實(shí)例的文件系統(tǒng)類型,有多大,磁盤上每一塊的大小, 還有就是super_operations。它與inode,dentry一樣,只是某些內(nèi)容在內(nèi)存中的映像。就ext2文件系統(tǒng)而言,設(shè)備上的超級(jí)塊為 ext2_super_block。由于sysfs是虛擬的文件系統(tǒng),獨(dú)一無二, 并且只能被mount一次,sysfs的super_block結(jié)構(gòu)是sysfs_sb。sysfs_sb也是動(dòng)態(tài)的從內(nèi)存中生成的。
還有要提一下super_operations,它也算是VFS的一個(gè)接口。實(shí)現(xiàn)一個(gè)文件系統(tǒng)file_operations, dentry_operations, inode_operations, super_operations這四個(gè)結(jié)構(gòu)都要實(shí)現(xiàn)。
把一個(gè)設(shè)備安裝到一個(gè)目錄節(jié)點(diǎn)時(shí)要用一個(gè)vfsmount的作為連接件。vfsmount結(jié)構(gòu)定義如下:
struct vfsmount {
struct list_head mnt_hash;
struct vfsmount *mnt_parent; /* fs we are mounted on */
struct dentry *mnt_mountpoint; /* dentry of mountpoint */
struct dentry *mnt_root; /* root of the mounted tree */
struct super_block *mnt_sb; /* pointer to superblock */
..........
}
對(duì) 于某個(gè)文件系統(tǒng)實(shí)例,內(nèi)存中super_block和vfsmount都是唯一的。比如,我們將某個(gè)掛載硬盤分區(qū)mount -t vfat /dev/hda2 /mnt/d。實(shí)際上就是新建一個(gè)vfsmount結(jié)構(gòu)作為連接件,vfsmount->mnt_sb = /dev/hda2的超級(jí)塊結(jié)構(gòu);vfsmount->mntroot = /dev/hda2的"根"目錄的dentry;vfsmount->mnt_mountpoint = /mnt/d的dentry; vfsmount->mnt_parent = /mnt/d所屬的文件系統(tǒng)的vfsmount。并且把這個(gè)新建的vfsmount連入一個(gè)全局的hash表mount_hashtable中。
從 而我們就可以從總根’/’開始,沿著dentry往下找。假如碰到一個(gè)某個(gè)目錄的dentry是被mount了的,那么我們就從 mount_hashtable表中去尋找相應(yīng)的vfsmount結(jié)構(gòu) (函數(shù)是lookup_mnt())。然后我們得到vfsmount ->mnt_root,就可以找到mount在該目錄的文件系統(tǒng)的"根"dentry結(jié)構(gòu)。然后又繼續(xù)往下走,就可以暢通無阻了。
關(guān)于path_walk()的代碼我就不貼了,太長(zhǎng)了。其實(shí)懂了原理后再去看,很簡(jiǎn)單,跟看故事會(huì)差不多。我當(dāng)年就是看完這個(gè)函數(shù)后,信心倍增阿。pathwalk,不管前面是高速公路,或是泥濘的鄉(xiāng)間小路,我們都要走到底。
聯(lián)系客服