檔案?
1:磁碟檔案,有組織有次序地儲存於任何介質中的一組訊息。
2:外部裝置當成檔案,凡是可以產生和消耗訊息的都是檔案。
struct file_operations {
00774: struct module *owner;
00775: loff_t (*llseek) (struct file *, loff_t, int);
00776: ssize_t (*read) (struct file *, char *, size_t, loff_t *);
00777: ssize_t (*write) (struct file *, const char *, size_t, loff_t *);
00778: int (*readdir) (struct file *, void *, filldir_t);
00779: unsigned int (*poll) (struct file *, struct poll_table_struct *);
00780: int (*ioctl) (struct inode *, struct file *, unsigned int, unsignedlong);
00781: int (*mmap) (struct file *, struct vm_area_struct *);
00782: int (*open) (struct inode *, struct file *);
00783: int (*flush) (struct file *);
00784: int (*release) (struct inode *, struct file *);
00785: int (*fsync) (struct file *, struct dentry *, int datasync);
00786: int (*fasync) (int, struct file *, int);
00787: int (*lock) (struct file *, int, struct file_lock *);
00788: ssize_t (*readv) (struct file *, const struct iovec *, unsigned long,loff_t *);
00789: ssize_t (*writev) (struct file *, const struct iovec *, unsigned long,loff_t *);
00790: };
這個結構作為一種函數跳轉表。每個file結構中都有一個file_operation的指標f_op
可以通過f_op來指向具體的檔案操作函數,實現虛擬檔案系統。:
1、
總之,具體檔案系統與虛擬檔案系統 VFS 間的介面是一組資料結構,包括 file_operations、
dentry_operations、inode_operations,還有其他(此處暫從略)。
一、磁碟檔案
以磁碟為儲存介質的檔案,檔案就是按一定的組織形式儲存在介質上的資訊。所以 一個“檔案”包含了2方面的資訊:
1、 資料本身。
2、檔案組織和管理的資訊。(主要儲存在“索引節點”和“目錄項”中)。每個檔案並且只有一個索引節點,索引節點總是存在的,即使沒有資料也是存在的。
二、裝置檔案
1、檔案組織和管理的資訊。
2、不一定有儲存著的資料。
它可以用於儲存、讀出的,如磁碟。也可以用於接收、發送的,如網路卡。也可以是採集、控制的(如某些機電裝置),也可以是這幾種的組合。不管什麼裝置,都是要通過控制/狀態器進行。
三、特殊檔案
特殊檔案一般與外部裝置無關,所涉及的介質一般都是記憶體和CPU本身。
總之,三種檔案都有一個共同點,都有組織和管理的一些資訊,每個檔案都有一個inode。要訪問一個檔案時,必須要知道通過inode來瞭解檔案的一些基本資料(類型,組織圖,資料量,地址,驅動程式等等)。
Inode包含了關於檔案的組織和管理的資訊,但是沒有建立起檔案名稱和INODE節點之間的關係,因此就出現了分類樹結構,檔案都是葉子節點,目錄也是一種檔案,其檔案名稱就是目錄名,也有索引節點和資料部分,其資料部分只包含目錄項。對Ext2_dir_entry既是其目錄項資料結構。
#defineEXT2_NAME_LEN 255
……………………
00483: /*
00484: * The new version of the directoryentry. Since EXT2 structures are
00485: * stored in intel byte order, and thename_len field could never be
00486: * bigger than 255 chars, it's safe toreclaim the extra byte for the
00487: * file_type field.
00488: */
00489: struct ext2_dir_entry_2 {
00490: __u32 inode; /* Inode number */
00491: __u16 rec_len; /* Directory entrylength */
00492: __u8 name_len; /* Name length */
00493: __u8 file_type;
00494: char name[EXT2_NAME_LEN]; /* Filename */
00495: };
磁碟上的ex2_inode資料結構在記憶體中的對應物為inode結構,但二者有很大不同;同樣,目錄項ext2_dir_extry2在記憶體中對應為dentry結構,二者也有很大的不同。
struct dentry {
00060: atomic_t d_count;
00061: unsigned intd_flags;
00062: struct inode * d_inode; /* Where the name belongs to - NULL is negative */
00063: struct dentry *d_parent; /* parent directory */
00064: struct list_headd_vfsmnt;
00065: struct list_headd_hash; /* lookup hash list */
00066: struct list_headd_lru; /* d_count = 0 LRU list */
00067: struct list_headd_child; /* child of parent list */
00068: struct list_headd_subdirs; /* our children */
00069: struct list_headd_alias; /* inode alias list */
00070: struct qstrd_name;
00071: unsigned longd_time; /* used by d_revalidate */
00072: structdentry_operations *d_op;
00073: struct super_block* d_sb; /* The root of the dentry tree*/
00074: unsigned longd_reftime; /* last time referenced */
00075: void *d_fsdata; /* fs-specific data */
00076: unsigned chard_iname[DNAME_INLINE_LEN]; /* small names */
00077: };
前者包含了許多動態資訊之外,還是後者的一種抽象和擴充。
要訪問一個檔案-------------à必須訪問一個目錄----------------------------à根據檔案名稱在該目錄中找到該檔案的目錄項------------------------------------------à進而找到i節點。
目錄本身也是一個檔案。
根檔案系統的目錄項不在其它目錄中,可以在固定的一個位置上或者通過一個固定的演算法可以找到,並且從這個目錄出發可以找到任何檔案。
每個Ext2經過格式化的磁碟:
四、磁碟檔案的讀出方法:
1,根據超級快資訊以及索引節點號計算出索引節點在磁碟中的位置,然後利用裝置驅動程式讀入磁碟那一塊的資料,再根據索引節點號讀出檔案的資料內容。
2,裝置檔案:一個線性儲存空間。
file 結構、dentry結構、inode 結構、super_block結構以及關於超級塊位置的約定都屬於VFS 層。
雖然每個檔案都有目錄項和索引節點在磁碟上,但是只有在需要的時候才在記憶體中為之建立起相應的 dentry 和 inode 資料結構。
五、從路徑名到目標節點
Path_init()和Path_walk()一起使用可以根據給定的檔案路徑名在記憶體中找到或建立代表著目錄檔案或目錄的dentry結構和inode節點。
int __user_walk(const char *name, unsigned flags, struct nameidata*nd)
{ //name:路徑中的檔案名稱flags:標誌位
char *tmp;
int err;
tmp = getname(name); //先在系統空間中分配一個頁面,並把檔案名稱複製到這個頁面中,
err = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
err = 0;
if (path_init(tmp,flags, nd))
err =path_walk(tmp, nd);
putname(tmp); //釋放記憶體。
}
return err;
}
以下是路徑初始化函數
int path_init(const char *name, unsigned int flags, struct nameidata*nd)
00692: {
00693: nd->last_type =LAST_ROOT; /* if there are only slashes... */
00694: nd->flags =flags;
00695: if (*name=='/')
00696: returnwalk_init_root(name,nd);
00697: read_lock(¤t->fs->lock);
00698: nd->mnt =mntget(current->fs->pwdmnt);
00699: nd->dentry =dget(current->fs->pwd);
00700: read_unlock(¤t->fs->lock);
00701: return 1;
00702: }
enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};