1. 程式人生 > >Linux 檔案系統(一)---虛擬檔案系統VFS----超級塊、inode、dentry、file

Linux 檔案系統(一)---虛擬檔案系統VFS----超級塊、inode、dentry、file

一:

什麼是檔案系統,詳見:http://zh.wikipedia.org/zh/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F

其實一句話就是管理這塊檔案的機制(組織方式,資料結構之類...)

Linux系統中存在很多的檔案系統,例如常見的ext2,ext3,ext4,sysfs,rootfs,proc...很多很多。。。我們知道每個檔案系統是獨立的,有自己的組織方法,操作方法。那麼對於使用者來說,不可能所有的檔案系統都瞭解,那麼怎麼做到讓使用者透明的去處理檔案呢?例如:我想寫檔案,那就直接read就OK,不管你是什麼檔案系統,具體怎麼去讀!OK,這裡就需要引入虛擬檔案系統。

所以虛擬檔案系統就是:對於一個system,可以存在多個“實際的檔案系統”,例如:ext2ext3fat32ntfs...例如我現在有多個分割槽,對於每一個分割槽我們知道可以是不同的“實際檔案系統”,例如現在三個磁碟分割槽分別是:ext2ext3fat32,那麼每個“實際的檔案系統”的操作和資料結構什麼肯定不一樣,那麼,使用者怎麼能透明使用它們呢?那麼這個時候就需要VFS作為中間一層!使用者直接和VFS打交道。例如readwrite,那麼對映到VFS中就是sys_readsys_write,那麼VFS可以根據你操作的是哪個“實際檔案系統”(哪個分割槽)來進行不同的實際的操作!那麼這個技術也是很熟悉的“鉤子結構”(此名稱不知道是否合理,自己一直這樣叫了)技術來處理的。其實就是VFS中提供一個抽象的struct結構體,然後對於每一個具體的檔案系統要把自己的欄位和函式填充進去,這樣就解決了異構問題。

如圖:

                                                

二:

Linux虛擬檔案系統四大物件:

1)超級塊(super block)

2)索引節點(inode)

3)目錄項(dentry)

4)檔案物件(file)

=> 超級塊:一個超級塊對應一個檔案系統(已經安裝的檔案系統型別如ext2,此處是實際的檔案系統哦,不是VFS)。之前我們已經說了檔案系統用於管理這些檔案的資料格式和操作之類的,系統檔案有系統檔案自己的檔案系統,同時對於不同的磁碟分割槽也有可以是不同的檔案系統。那麼一個超級塊對於一個獨立的檔案系統。儲存檔案系統的型別、大小、狀態等等。

(“檔案系統”和“檔案系統型別”不一樣!一個檔案系統型別下可以包括很多檔案系統即很多的super_block)

既然我們知道對於不同的檔案系統有不同的super_block,那麼對於不同的super_block的操作肯定也是不同的,所以我們在下面的super_block結構中可以看到上面說的抽象的struct結構(例如下面的:struct super_operations):

(linux核心2.4.37)

<span style="font-size:14px;">struct super_block {
746         struct list_head        s_list;         /* Keep this first */
747         kdev_t                  s_dev;
748         unsigned long           s_blocksize;
749         unsigned char           s_blocksize_bits;
750         unsigned char           s_dirt;
751         unsigned long long      s_maxbytes;     /* Max file size */
752         struct file_system_type *s_type;
753         struct super_operations *s_op;
754         struct dquot_operations *dq_op;
755         struct quotactl_ops     *s_qcop;
756         unsigned long           s_flags;
757         unsigned long           s_magic;
758         struct dentry           *s_root;
759         struct rw_semaphore     s_umount;
760         struct semaphore        s_lock;
761         int                     s_count;
762         atomic_t                s_active;
763 
764         struct list_head        s_dirty;        /* dirty inodes */
765         struct list_head        s_locked_inodes;/* inodes being synced */
766         struct list_head        s_files;
767 
768         struct block_device     *s_bdev;
769         struct list_head        s_instances;
770         struct quota_info       s_dquot;        /* Diskquota specific options */
771 
772         union {
773                 struct minix_sb_info    minix_sb;
774                 struct ext2_sb_info     ext2_sb;
775                 struct ext3_sb_info     ext3_sb;
776                 struct hpfs_sb_info     hpfs_sb;
777                 struct ntfs_sb_info     ntfs_sb;
778                 struct msdos_sb_info    msdos_sb;
779                 struct isofs_sb_info    isofs_sb;
780                 struct nfs_sb_info      nfs_sb;
781                 struct sysv_sb_info     sysv_sb;
782                 struct affs_sb_info     affs_sb;
783                 struct ufs_sb_info      ufs_sb;
784                 struct efs_sb_info      efs_sb;
785                 struct shmem_sb_info    shmem_sb;
786                 struct romfs_sb_info    romfs_sb;
787                 struct smb_sb_info      smbfs_sb;
788                 struct hfs_sb_info      hfs_sb;
789                 struct adfs_sb_info     adfs_sb;
790                 struct qnx4_sb_info     qnx4_sb;
791                 struct reiserfs_sb_info reiserfs_sb;
792                 struct bfs_sb_info      bfs_sb;
793                 struct udf_sb_info      udf_sb;
794                 struct ncp_sb_info      ncpfs_sb;
795                 struct usbdev_sb_info   usbdevfs_sb;
796                 struct jffs2_sb_info    jffs2_sb;
797                 struct cramfs_sb_info   cramfs_sb;
798                 void                    *generic_sbp;
799         } u;
800         /*
801          * The next field is for VFS *only*. No filesystems have any business
802          * even looking at it. You had been warned.
803          */
804         struct semaphore s_vfs_rename_sem;      /* Kludge */
805 
806         /* The next field is used by knfsd when converting a (inode number based)
807          * file handle into a dentry. As it builds a path in the dcache tree from
808          * the bottom up, there may for a time be a subpath of dentrys which is not
809          * connected to the main tree.  This semaphore ensure that there is only ever
810          * one such free path per filesystem.  Note that unconnected files (or other
811          * non-directories) are allowed, but not unconnected diretories.
812          */
813         struct semaphore s_nfsd_free_path_sem;
814 };</span>

解釋欄位:

s_list:指向超級塊連結串列的指標,這個struct list_head是很熟悉的結構了,裡面其實就是用於連線關係的prev和next欄位。

核心中的結構處理都是有講究的(核心協議棧中也說過),核心單獨使用一個簡單的結構體將所有的super_block都連結起來,但是這個結構不是super_block本身,因為本身資料結構太大,效率不高,所有僅僅使用

struct

{

list_head prev;

list_head next;

}

這樣的結構來將super_block中的s_list連結起來,那麼遍歷到s_list之後,直接讀取super_block這麼長的一個記憶體塊,就可以將這個

super_block直接讀進來!這樣就很快捷方便!這也是為什麼s_list必須放在第一個欄位的原因。

s_dev:包含該具體檔案系統的塊裝置識別符號。例如,對於 /dev/hda1,其裝置識別符號為 0x301

s_blocksize:檔案系統中資料塊大小,以位元組單位

s_blocksize_bits:上面的size大小佔用位數,例如512位元組就是9 bits

s_dirt:髒位,標識是否超級塊被修改

s_maxbytes:允許的最大的檔案大小(位元組數)

struct file_system_type *s_type:檔案系統型別(也就是當前這個檔案系統屬於哪個型別?ext2還是fat32)

要區分“檔案系統”和“檔案系統型別”不一樣!一個檔案系統型別下可以包括很多檔案系統即很多的super_block,後面會說!

struct super_operations *s_op:指向某個特定的具體檔案系統的用於超級塊操作的函式集合

struct dquot_operations *dq_op:指向某個特定的具體檔案系統用於限額操作的函式集合

struct quotactl_ops     *s_qcop:用於配置磁碟限額的的方法,處理來自使用者空間的請求
s_flags:安裝標識

s_magic:區別於其他檔案系統的標識

s_root:指向該具體檔案系統安裝目錄的目錄項

s_umount:對超級塊讀寫時進行同步

s_lock鎖標誌位,若置該位,則其它程序不能對該超級塊操作

s_count:對超級塊的使用計數

s_active:引用計數

s_dirty已修改的索引節點inode形成的連結串列,一個檔案系統中有很多的inode,有些inode節點的內容會被修改,那麼會先被記錄,然後寫回磁碟。

s_locked_inodes要進行同步的索引節點形成的連結串列

s_files:所有的已經開啟檔案的連結串列,這個file和實實在在的程序相關的

s_bdev:指向檔案系統被安裝的塊裝置

u聯合體域包括屬於具體檔案系統的超級塊資訊

s_instances:具體的意義後來會說的!(同一型別的檔案系統通過這個子墩將所有的super_block連線起來)

s_dquot:磁碟限額相關選項

=>索引節點inode:儲存的其實是實際的資料的一些資訊,這些資訊稱為“元資料”(也就是對檔案屬性的描述)。例如:檔案大小,裝置識別符號,使用者識別符號,使用者組識別符號,檔案模式,擴充套件屬性,檔案讀取或修改的時間戳,連結數量,指向儲存該內容的磁碟區塊的指標,檔案分類等等。

( 注意資料分成:元資料+資料本身 )

同時注意:inode有兩種,一種是VFS的inode,一種是具體檔案系統的inode。前者在記憶體中,後者在磁碟中。所以每次其實是將磁碟中的inode調進填充記憶體中的inode,這樣才是算使用了磁碟檔案inode。

注意inode怎樣生成的:每個inode節點的大小,一般是128位元組或256位元組。inode節點的總數,在格式化時就給定(現代OS可以動態變化),一般每2KB就設定一個inode。一般檔案系統中很少有檔案小於2KB的,所以預定按照2KB分,一般inode是用不完的。所以inode在檔案系統安裝的時候會有一個預設數量,後期會根據實際的需要發生變化。

注意inode號:inode號是唯一的,表示不同的檔案。其實在Linux內部的時候,訪問檔案都是通過inode號來進行的,所謂檔名僅僅是給使用者容易使用的。當我們開啟一個檔案的時候,首先,系統找到這個檔名對應的inode號;然後,通過inode號,得到inode資訊,最後,由inode找到檔案資料所在的block,現在可以處理檔案資料了。

inode和檔案的關係:當建立一個檔案的時候,就給檔案分配了一個inode。一個inode只對應一個實際檔案,一個檔案也會只有一個inode。inodes最大數量就是檔案的最大數量。

<span style="font-size:14px;">440 struct inode {
441         struct list_head        i_hash;
442         struct list_head        i_list;
443         struct list_head        i_dentry;
444         
445         struct list_head        i_dirty_buffers;
446         struct list_head        i_dirty_data_buffers;
447 
448         unsigned long           i_ino;
449         atomic_t                i_count;
450         kdev_t                  i_dev;
451         umode_t                 i_mode;
452         unsigned int            i_nlink;
453         uid_t                   i_uid;
454         gid_t                   i_gid;
455         kdev_t                  i_rdev;
456         loff_t                  i_size;
457         time_t                  i_atime;
458         time_t                  i_mtime;
459         time_t                  i_ctime;
460         unsigned int            i_blkbits;
461         unsigned long           i_blksize;
462         unsigned long           i_blocks;
463         unsigned long           i_version;
464         unsigned short          i_bytes;
465         struct semaphore        i_sem;
466         struct rw_semaphore     i_alloc_sem;
467         struct semaphore        i_zombie;
468         struct inode_operations *i_op;
469         struct file_operations  *i_fop; /* former ->i_op->default_file_ops */
470         struct super_block      *i_sb;
471         wait_queue_head_t       i_wait;
472         struct file_lock        *i_flock;
473         struct address_space    *i_mapping;
474         struct address_space    i_data;
475         struct dquot            *i_dquot[MAXQUOTAS];
476         /* These three should probably be a union */
477         struct list_head        i_devices;
478         struct pipe_inode_info  *i_pipe;
479         struct block_device     *i_bdev;
480         struct char_device      *i_cdev;
481 
482         unsigned long           i_dnotify_mask; /* Directory notify events */
483         struct dnotify_struct   *i_dnotify; /* for directory notifications */
484 
485         unsigned long           i_state;
486 
487         unsigned int            i_flags;
488         unsigned char           i_sock;
489 
490         atomic_t                i_writecount;
491         unsigned int            i_attr_flags;
492         __u32                   i_generation;
493         union {
494                 struct minix_inode_info         minix_i;
495                 struct ext2_inode_info          ext2_i;
496                 struct ext3_inode_info          ext3_i;
497                 struct hpfs_inode_info          hpfs_i;
498                 struct ntfs_inode_info          ntfs_i;
499                 struct msdos_inode_info         msdos_i;
500                 struct umsdos_inode_info        umsdos_i;
501                 struct iso_inode_info           isofs_i;
502                 struct nfs_inode_info           nfs_i;
503                 struct sysv_inode_info          sysv_i;
504                 struct affs_inode_info          affs_i;
505                 struct ufs_inode_info           ufs_i;
506                 struct efs_inode_info           efs_i;
507                 struct romfs_inode_info         romfs_i;
508                 struct shmem_inode_info         shmem_i;
509                 struct coda_inode_info          coda_i;
510                 struct smb_inode_info           smbfs_i;
511                 struct hfs_inode_info           hfs_i;
512                 struct adfs_inode_info          adfs_i;
513                 struct qnx4_inode_info          qnx4_i;
514                 struct reiserfs_inode_info      reiserfs_i;
515                 struct bfs_inode_info           bfs_i;
516                 struct udf_inode_info           udf_i;
517                 struct ncp_inode_info           ncpfs_i;
518                 struct proc_inode_info          proc_i;
519                 struct socket                   socket_i;
520                 struct usbdev_inode_info        usbdev_i;
521                 struct jffs2_inode_info         jffs2_i;
522                 void                            *generic_ip;
523         } u;
524 };</span>

解釋一些欄位:

i_hash:指向hash連結串列指標,用於inode的hash表,下面會說

i_list:指向索引節點連結串列指標,用於inode之間的連線,下面會說

i_dentry:指向目錄項鍊表指標,注意一個inodes可以對應多個dentry,因為一個實際的檔案可能被連結到其他的檔案,那麼就會有另一個dentry,這個連結串列就是將所有的與本inode有關的dentry都連在一起。

i_dirty_buffersi_dirty_data_buffers:髒資料緩衝區

i_ino:索引節點號,每個inode都是唯一的

i_count:引用計數

i_dev:如果inode代表裝置,那麼就是裝置號

i_mode:檔案的型別和訪問許可權

i_nlink:與該節點建立連結的檔案數(硬連結數)

i_uid:檔案擁有者標號

i_gid:檔案所在組標號

i_rdev:實際的裝置標識

注意i_dev和i_rdev之間區別:如果是普通的檔案,例如磁碟檔案,儲存在某塊磁碟上,那麼i_dev代表的就是儲存這個檔案的磁碟號,但是如果此處是特殊檔案例如就是磁碟本身(因為所有的裝置也看做檔案處理),那麼i_rdev就代表這個磁碟實際的磁碟號。

i_size:inode所代表的的檔案的大小,以位元組為單位

i_atime:檔案最後一次訪問時間

i_mtime:檔案最後一次修改時間

i_ctime:inode最後一次修改時間

i_blkbits:塊大小,位元組單位

i_blksize:塊大小,bit單位

i_blocks:檔案所佔塊數

i_version:版本號

i_bytes:檔案中最後一個塊的位元組數

i_sem指向用於同步操作的訊號量結構

i_alloc_sem:保護inode上的IO操作不被另一個打斷

i_zombie:殭屍inode訊號量

i_op:索引節點操作

i_fop:檔案操作

i_sb:inode所屬檔案系統的超級塊指標

i_wait:指向索引節點等待佇列指標

i_flock:檔案鎖鏈表

注意下面:address_space不是代表某個地址空間,而是用於描述頁快取記憶體中的頁面的。一個檔案對應一個address_space,一個address_space和一個偏移量可以確定一個頁快取記憶體中的頁面。

i_mapping:表示向誰請求頁面

i_data:表示被inode讀寫的頁面

i_dquot:inode的磁碟限額

關於磁碟限額:在多工環境下,對於每個使用者的磁碟使用限制是必須的,起到一個公平性作用。

磁碟限額分為兩種:block限額和inode限額,而且對於一個特檔案系統來說,使用的限額機制都是一樣的,所以限額的操作函式

放在super_block中就OK!

i_devices:裝置連結串列。共用同一個驅動程式的裝置形成的連結串列。

i_pipe:指向管道檔案(如果檔案是管道檔案時使用)

i_bdev:指向塊裝置檔案指標(如果檔案是塊裝置檔案時使用)

i_cdev:指向字元裝置檔案指標(如果檔案是字元裝置時使用)

i_dnotify_mask:目錄通知事件掩碼

i_dnotify:用於目錄通知

i_state:索引節點的狀態標識:I_NEW,I_LOCK,I_FREEING

i_flags:索引節點的安裝標識

i_sock:如果是套接字檔案則為True

i_write_count:記錄多少程序以刻寫模式開啟此檔案

i_attr_flags:檔案建立標識

i_generation:保留

u:具體的inode資訊

注意管理inode的四個連結串列

inode_unused:將目前還沒有使用的inode連結起來(通過i_list域連結)

inode_in_use:目前正在使用的inode連結起來(通過i_list域連結)

super_block中的s_dirty:將所有修改過的inode連結起來,這個欄位在super_block中(通過i_list域連結起來)

inode_hashtable:注意為了加快inode的查詢效率,將正在使用的inode和髒inode也會放在inode_hashtable這樣一個hash結構中,

但是,不同的inode的hash值可能相等,所以將hash值相等的這些inode通過這個i_hash欄位連線起來。

=>目錄項:目錄項是描述檔案的邏輯屬性,只存在於記憶體中,並沒有實際對應的磁碟上的描述,更確切的說是存在於記憶體的目錄項快取,為了提高查詢效能而設計。注意不管是資料夾還是最終的檔案,都是屬於目錄項,所有的目錄項在一起構成一顆龐大的目錄樹。例如:open一個檔案/home/xxx/yyy.txt,那麼/、home、xxx、yyy.txt都是一個目錄項,VFS在查詢的時候,根據一層一層的目錄項找到對應的每個目錄項的inode,那麼沿著目錄項進行操作就可以找到最終的檔案。

注意:目錄也是一種檔案(所以也存在對應的inode)。開啟目錄,實際上就是開啟目錄檔案。

<span style="font-size:14px;"> 67 struct dentry {
 68         atomic_t d_count;
 69         unsigned int d_flags;
 70         struct inode  * d_inode;        /* Where the name belongs to - NULL is negative */
 71         struct dentry * d_parent;       /* parent directory */
 72         struct list_head d_hash;        /* lookup hash list */
 73         struct list_head d_lru;         /* d_count = 0 LRU list */
 74         struct list_head d_child;       /* child of parent list */
 75         struct list_head d_subdirs;     /* our children */
 76         struct list_head d_alias;       /* inode alias list */
 77         int d_mounted;
 78         struct qstr d_name;
 79         unsigned long d_time;           /* used by d_revalidate */
 80         struct dentry_operations  *d_op;
 81         struct super_block * d_sb;      /* The root of the dentry tree */
 82         unsigned long d_vfs_flags;
 83         void * d_fsdata;                /* fs-specific data */
 84         unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */
 85 };</span>
解釋一些欄位:
d_count:引用計數

d_flags:目錄項快取標識,可取DCACHE_UNUSED、DCACHE_REFERENCED等

d_inode:與該目錄項關聯的inode

d_parent:父目錄的目錄項

d_hash:核心使用dentry_hashtable對dentry進行管理,dentry_hashtable是由list_head組成的連結串列,一個dentry建立之後,就通過

d_hash連結進入對應的hash值的連結串列中。

d_lru:最近未使用的目錄項的連結串列

d_child:目錄項通過這個加入到父目錄的d_subdirs中

d_subdirs:本目錄的所有孩子目錄連結串列頭

d_alias:一個有效的dentry必然與一個inode關聯,但是一個inode可以對應多個dentry,因為一個檔案可以被連結到其他檔案,所以,這個dentry就是通過這個欄位連結到屬於自己的inode結構中的i_dentry連結串列中的。(inode中講過)

d_mounted:安裝在該目錄的檔案系統的數量!注意一個檔案目錄下可以有不同的檔案系統!

d_name:目錄項名稱

d_time:重新變為有效的時間!注意只要操作成功這個dentry就是有效的,否則無效。

d_op:目錄項操作

d_sb:這個目錄項所屬的檔案系統的超級塊

d_vfs_flags:一些標誌

d_fsdata:檔案系統私有資料

d_iname:存放短的檔名

一些解釋一個有效的dentry結構必定有一個inode結構,這是因為一個目錄項要麼代表著一個檔案,要麼代表著一個目錄,而目錄實際上也是檔案。所以,只要dentry結構是有效的,則其指標d_inode必定指向一個inode結構。但是inode卻可以對應多個

dentry,上面已經說過兩次了。

注意:整個結構其實就是一棵樹。

=>檔案物件:注意檔案物件描述的是程序已經開啟的檔案。因為一個檔案可以被多個程序開啟,所以一個檔案可以存在多個檔案物件。但是由於檔案是唯一的,那麼inode就是唯一的,目錄項也是定的!

程序其實是通過檔案描述符來操作檔案的,注意每個檔案都有一個32位的數字來表示下一個讀寫的位元組位置,這個數字叫做檔案位置。一般情況下開啟檔案後,開啟位置都是從0開始,除非一些特殊情況。Linux用file結構體來儲存開啟的檔案的位置,所以file稱為開啟的檔案描述。這個需要好好理解一下!file結構形成一個雙鏈表,稱為系統開啟檔案表

<span style="font-size:14px;">565 struct file {
566         struct list_head        f_list;
567         struct dentry           *f_dentry;
568         struct vfsmount         *f_vfsmnt;
569         struct file_operations  *f_op;
570         atomic_t                f_count;
571         unsigned int            f_flags;
572         mode_t                  f_mode;
573         loff_t                  f_pos;
574         unsigned long           f_reada, f_ramax, f_raend, f_ralen, f_rawin;
575         struct fown_struct      f_owner;
576         unsigned int            f_uid, f_gid;
577         int                     f_error;
578 
579         size_t                  f_maxcount;
580         unsigned long           f_version;
581 
582         /* needed for tty driver, and maybe others */
583         void                    *private_data;
584 
585         /* preallocated helper kiobuf to speedup O_DIRECT */
586         struct kiobuf           *f_iobuf;
587         long                    f_iobuf_lock;
588 };</span>
解釋一些欄位:

f_list:所有的開啟的檔案形成的連結串列!注意一個檔案系統所有的開啟的檔案都通過這個連結到super_block中的s_files連結串列中!

f_dentry:與該檔案相關的dentry

f_vfsmnt:該檔案在這個檔案系統中的安裝點

f_op:檔案操作,當程序開啟檔案的時候,這個檔案的關聯inode中的i_fop檔案操作會初始化這個f_op欄位

f_count:引用計數

f_flags:開啟檔案時候指定的標識

f_mode:檔案的訪問模式

f_pos:目前檔案的相對開頭的偏移

unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin預讀標誌、要預讀的最多頁面數、上次預讀後的檔案指標、預讀的位元組數以及預讀的頁面數

f_owner:記錄一個程序ID,以及當某些事發送的時候傳送給該ID程序的訊號

f_uid:使用者ID

f_gid:組ID

f_error:寫操作錯誤碼

f_version:版本號,當f_pos改變時候,version遞增

private_data:私有資料( 檔案系統和驅動程式使用 )

重點解釋一些重要欄位

首先,f_flags、f_mode和f_pos代表的是這個程序當前操作這個檔案的控制資訊。這個非常重要,因為對於一個檔案,可以被多個程序同時開啟,那麼對於每個程序來說,操作這個檔案是非同步的,所以這個三個欄位就很重要了。

第二:對於引用計數f_count,當我們關閉一個程序的某一個檔案描述符時候,其實並不是真正的關閉檔案,僅僅是將f_count減一,當f_count=0時候,才會真的去關閉它。對於dup,fork這些操作來說,都會使得f_count增加,具體的細節,以後再說。

第三:f_op也是很重要的!是涉及到所有的檔案的操作結構體。例如:使用者使用read,最終都會呼叫file_operations中的讀操作,而file_operations結構體是對於不同的檔案系統不一定相同。裡面一個重要的操作函式式release函式,當用戶執行close時候,其實在核心中是執行release函式,這個函式僅僅將f_count減一,這也就解釋了上面說的,使用者close一個檔案其實是將f_count減一。只有引用計數減到0才關閉檔案。

注意:對於“正在使用”和“未使用”的檔案物件分別使用一個雙向連結串列進行管理。

注意上面的file只是對一個檔案而言,對於一個程序(使用者)來說,可以同時處理多個檔案,所以需要另一個結構來管理所有的files!

即:使用者開啟檔案表--->files_struct

<span style="font-size:14px;">172 struct files_struct {
173         atomic_t count;
174         rwlock_t file_lock;     /* Protects all the below members.  Nests inside tsk->alloc_lock */
175         int max_fds;
176         int max_fdset;
177         int next_fd;
178         struct file ** fd;      /* current fd array */
179         fd_set *close_on_exec;
180         fd_set *open_fds;
181         fd_set close_on_exec_init;
182         fd_set open_fds_init;
183         struct file * fd_array[NR_OPEN_DEFAULT];
184 };</span>

解釋一些欄位:

count:引用計數

file_lock:鎖,保護下面的欄位

max_fds:當前檔案物件的最大的數量

max_fdset:檔案描述符最大數

next_fd:已分配的最大的檔案描述符+1

fd:指向檔案物件指標陣列的指標,一般就是指向最後一個欄位fd_arrray,當檔案數超過NR_OPEN_DEFAULT時候,就會重新分配一個數組,然後指向這個新的陣列指標!

close_on_exec:執行exec()時候需要關閉的檔案描述符

open_fds:指向開啟的檔案描述符的指標

close_on_exec_init執行exec()時候需要關閉的檔案描述符初始化值

open_fds_init:檔案描述符初值集合

fd_array檔案物件指標的初始化陣列

注意上面的file和files_struct記錄的是與程序相關的檔案的資訊,但是對於程序本身來說,自身的一些資訊用什麼表示,這裡就涉及到fs_struct結構體。

<span style="font-size:14px;">  5 struct fs_struct {
  6         atomic_t count;
  7         rwlock_t lock;
  8         int umask;
  9         struct dentry * root, * pwd, * altroot;
 10         struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;
 11 };</span>

解釋一些欄位:

count:引用計數

lock:保護鎖

umask:開啟檔案時候預設的檔案訪問許可權

root:程序的根目錄

pwd:程序當前的執行目錄

altroot:使用者設定的替換根目錄

注意:實際執行時,這三個目錄不一定都在同一個檔案系統中。例如,程序的根目錄通常是安裝於“/”節點上的ext檔案系統,而當前工作目錄可能是安裝於/etc的一個檔案系統,替換根目錄也可以不同檔案系統中。

rootmnt,pwdmnt,altrootmnt:對應於上面三個的安裝點。

基本的概念和基本的結構總結完了,後面會總結看看這些之間的關係。