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

轉自:http://blog.csdn.net/shanshanpt/article/details/38943731node

           http://elixir.free-electrons.com/linux/v4.14.9/source/arch/arm64/kernel/acpi.clinux

一:數組

什麼是文件系統,詳見: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,這裏就須要引入虛擬文件系統。app

因此虛擬文件系統就是:對於一個system,能夠存在多個「實際的文件系統」,例如:ext2,ext3,fat32,ntfs...例如我如今有多個分區,對於每個分區咱們知道能夠是不一樣的「實際文件系統」,例如如今三個磁盤分區分別是:ext2,ext3,fat32,那麼每一個「實際的文件系統」的操做和數據結構什麼確定不同,那麼,用戶怎麼能透明使用它們呢?那麼這個時候就須要VFS做爲中間一層!用戶直接和VFS打交道。例如read,write,那麼映射到VFS中就是sys_read,sys_write,那麼VFS能夠根據你操做的是哪一個「實際文件系統」(哪一個分區)來進行不一樣的實際的操做!那麼這個技術也是很熟悉的「鉤子結構」(此名稱不知道是否合理,本身一直這樣叫了)技術來處理的。其實就是VFS中提供一個抽象的struct結構體,而後對於每個具體的文件系統要把本身的字段和函數填充進去,這樣就解決了異構問題。異步

如圖:electron

                                                

 

二:socket

Linux虛擬文件系統四大對象:ide

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)

 

[cpp]  view plain  copy
 
 print?
  1. <span style="font-size:14px;">struct super_block {  
  2. 746         struct list_head        s_list;         /* Keep this first */  
  3. 747         kdev_t                  s_dev;  
  4. 748         unsigned long           s_blocksize;  
  5. 749         unsigned char           s_blocksize_bits;  
  6. 750         unsigned char           s_dirt;  
  7. 751         unsigned long long      s_maxbytes;     /* Max file size */  
  8. 752         struct file_system_type *s_type;  
  9. 753         struct super_operations *s_op;  
  10. 754         struct dquot_operations *dq_op;  
  11. 755         struct quotactl_ops     *s_qcop;  
  12. 756         unsigned long           s_flags;  
  13. 757         unsigned long           s_magic;  
  14. 758         struct dentry           *s_root;  
  15. 759         struct rw_semaphore     s_umount;  
  16. 760         struct semaphore        s_lock;  
  17. 761         int                     s_count;  
  18. 762         atomic_t                s_active;  
  19. 763   
  20. 764         struct list_head        s_dirty;        /* dirty inodes */  
  21. 765         struct list_head        s_locked_inodes;/* inodes being synced */  
  22. 766         struct list_head        s_files;  
  23. 767   
  24. 768         struct block_device     *s_bdev;  
  25. 769         struct list_head        s_instances;  
  26. 770         struct quota_info       s_dquot;        /* Diskquota specific options */  
  27. 771   
  28. 772         union {  
  29. 773                 struct minix_sb_info    minix_sb;  
  30. 774                 struct ext2_sb_info     ext2_sb;  
  31. 775                 struct ext3_sb_info     ext3_sb;  
  32. 776                 struct hpfs_sb_info     hpfs_sb;  
  33. 777                 struct ntfs_sb_info     ntfs_sb;  
  34. 778                 struct msdos_sb_info    msdos_sb;  
  35. 779                 struct isofs_sb_info    isofs_sb;  
  36. 780                 struct nfs_sb_info      nfs_sb;  
  37. 781                 struct sysv_sb_info     sysv_sb;  
  38. 782                 struct affs_sb_info     affs_sb;  
  39. 783                 struct ufs_sb_info      ufs_sb;  
  40. 784                 struct efs_sb_info      efs_sb;  
  41. 785                 struct shmem_sb_info    shmem_sb;  
  42. 786                 struct romfs_sb_info    romfs_sb;  
  43. 787                 struct smb_sb_info      smbfs_sb;  
  44. 788                 struct hfs_sb_info      hfs_sb;  
  45. 789                 struct adfs_sb_info     adfs_sb;  
  46. 790                 struct qnx4_sb_info     qnx4_sb;  
  47. 791                 struct reiserfs_sb_info reiserfs_sb;  
  48. 792                 struct bfs_sb_info      bfs_sb;  
  49. 793                 struct udf_sb_info      udf_sb;  
  50. 794                 struct ncp_sb_info      ncpfs_sb;  
  51. 795                 struct usbdev_sb_info   usbdevfs_sb;  
  52. 796                 struct jffs2_sb_info    jffs2_sb;  
  53. 797                 struct cramfs_sb_info   cramfs_sb;  
  54. 798                 void                    *generic_sbp;  
  55. 799         } u;  
  56. 800         /* 
  57. 801          * The next field is for VFS *only*. No filesystems have any business 
  58. 802          * even looking at it. You had been warned. 
  59. 803          */  
  60. 804         struct semaphore s_vfs_rename_sem;      /* Kludge */  
  61. 805   
  62. 806         /* The next field is used by knfsd when converting a (inode number based) 
  63. 807          * file handle into a dentry. As it builds a path in the dcache tree from 
  64. 808          * the bottom up, there may for a time be a subpath of dentrys which is not 
  65. 809          * connected to the main tree.  This semaphore ensure that there is only ever 
  66. 810          * one such free path per filesystem.  Note that unconnected files (or other 
  67. 811          * non-directories) are allowed, but not unconnected diretories. 
  68. 812          */  
  69. 813         struct semaphore s_nfsd_free_path_sem;  
  70. 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:指向文件系統被安裝的塊設備

uu 聯合體域包括屬於具體文件系統的超級塊信息

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最大數量就是文件的最大數量。

維基上說的也比較詳細:維基-inode

 

 

[cpp]  view plain  copy
 
 print?
  1. <span style="font-size:14px;">440 struct inode {  
  2. 441         struct list_head        i_hash;  
  3. 442         struct list_head        i_list;  
  4. 443         struct list_head        i_dentry;  
  5. 444           
  6. 445         struct list_head        i_dirty_buffers;  
  7. 446         struct list_head        i_dirty_data_buffers;  
  8. 447   
  9. 448         unsigned long           i_ino;  
  10. 449         atomic_t                i_count;  
  11. 450         kdev_t                  i_dev;  
  12. 451         umode_t                 i_mode;  
  13. 452         unsigned int            i_nlink;  
  14. 453         uid_t                   i_uid;  
  15. 454         gid_t                   i_gid;  
  16. 455         kdev_t                  i_rdev;  
  17. 456         loff_t                  i_size;  
  18. 457         time_t                  i_atime;  
  19. 458         time_t                  i_mtime;  
  20. 459         time_t                  i_ctime;  
  21. 460         unsigned int            i_blkbits;  
  22. 461         unsigned long           i_blksize;  
  23. 462         unsigned long           i_blocks;  
  24. 463         unsigned long           i_version;  
  25. 464         unsigned short          i_bytes;  
  26. 465         struct semaphore        i_sem;  
  27. 466         struct rw_semaphore     i_alloc_sem;  
  28. 467         struct semaphore        i_zombie;  
  29. 468         struct inode_operations *i_op;  
  30. 469         struct file_operations  *i_fop; /* former ->i_op->default_file_ops */  
  31. 470         struct super_block      *i_sb;  
  32. 471         wait_queue_head_t       i_wait;  
  33. 472         struct file_lock        *i_flock;  
  34. 473         struct address_space    *i_mapping;  
  35. 474         struct address_space    i_data;  
  36. 475         struct dquot            *i_dquot[MAXQUOTAS];  
  37. 476         /* These three should probably be a union */  
  38. 477         struct list_head        i_devices;  
  39. 478         struct pipe_inode_info  *i_pipe;  
  40. 479         struct block_device     *i_bdev;  
  41. 480         struct char_device      *i_cdev;  
  42. 481   
  43. 482         unsigned long           i_dnotify_mask; /* Directory notify events */  
  44. 483         struct dnotify_struct   *i_dnotify; /* for directory notifications */  
  45. 484   
  46. 485         unsigned long           i_state;  
  47. 486   
  48. 487         unsigned int            i_flags;  
  49. 488         unsigned char           i_sock;  
  50. 489   
  51. 490         atomic_t                i_writecount;  
  52. 491         unsigned int            i_attr_flags;  
  53. 492         __u32                   i_generation;  
  54. 493         union {  
  55. 494                 struct minix_inode_info         minix_i;  
  56. 495                 struct ext2_inode_info          ext2_i;  
  57. 496                 struct ext3_inode_info          ext3_i;  
  58. 497                 struct hpfs_inode_info          hpfs_i;  
  59. 498                 struct ntfs_inode_info          ntfs_i;  
  60. 499                 struct msdos_inode_info         msdos_i;  
  61. 500                 struct umsdos_inode_info        umsdos_i;  
  62. 501                 struct iso_inode_info           isofs_i;  
  63. 502                 struct nfs_inode_info           nfs_i;  
  64. 503                 struct sysv_inode_info          sysv_i;  
  65. 504                 struct affs_inode_info          affs_i;  
  66. 505                 struct ufs_inode_info           ufs_i;  
  67. 506                 struct efs_inode_info           efs_i;  
  68. 507                 struct romfs_inode_info         romfs_i;  
  69. 508                 struct shmem_inode_info         shmem_i;  
  70. 509                 struct coda_inode_info          coda_i;  
  71. 510                 struct smb_inode_info           smbfs_i;  
  72. 511                 struct hfs_inode_info           hfs_i;  
  73. 512                 struct adfs_inode_info          adfs_i;  
  74. 513                 struct qnx4_inode_info          qnx4_i;  
  75. 514                 struct reiserfs_inode_info      reiserfs_i;  
  76. 515                 struct bfs_inode_info           bfs_i;  
  77. 516                 struct udf_inode_info           udf_i;  
  78. 517                 struct ncp_inode_info           ncpfs_i;  
  79. 518                 struct proc_inode_info          proc_i;  
  80. 519                 struct socket                   socket_i;  
  81. 520                 struct usbdev_inode_info        usbdev_i;  
  82. 521                 struct jffs2_inode_info         jffs2_i;  
  83. 522                 void                            *generic_ip;  
  84. 523         } u;  
  85. 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)。打開目錄,實際上就是打開目錄文件。

 

[cpp]  view plain  copy
 
 print?
  1. <span style="font-size:14px;"> 67 struct dentry {  
  2.  68         atomic_t d_count;  
  3.  69         unsigned int d_flags;  
  4.  70         struct inode  * d_inode;        /* Where the name belongs to - NULL is negative */  
  5.  71         struct dentry * d_parent;       /* parent directory */  
  6.  72         struct list_head d_hash;        /* lookup hash list */  
  7.  73         struct list_head d_lru;         /* d_count = 0 LRU list */  
  8.  74         struct list_head d_child;       /* child of parent list */  
  9.  75         struct list_head d_subdirs;     /* our children */  
  10.  76         struct list_head d_alias;       /* inode alias list */  
  11.  77         int d_mounted;  
  12.  78         struct qstr d_name;  
  13.  79         unsigned long d_time;           /* used by d_revalidate */  
  14.  80         struct dentry_operations  *d_op;  
  15.  81         struct super_block * d_sb;      /* The root of the dentry tree */  
  16.  82         unsigned long d_vfs_flags;  
  17.  83         void * d_fsdata;                /* fs-specific data */  
  18.  84         unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */  
  19.  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結構造成一個雙鏈表,稱爲系統打開文件表

 

[cpp]  view plain  copy
 
 print?
  1. <span style="font-size:14px;">565 struct file {  
  2. 566         struct list_head        f_list;  
  3. 567         struct dentry           *f_dentry;  
  4. 568         struct vfsmount         *f_vfsmnt;  
  5. 569         struct file_operations  *f_op;  
  6. 570         atomic_t                f_count;  
  7. 571         unsigned int            f_flags;  
  8. 572         mode_t                  f_mode;  
  9. 573         loff_t                  f_pos;  
  10. 574         unsigned long           f_reada, f_ramax, f_raend, f_ralen, f_rawin;  
  11. 575         struct fown_struct      f_owner;  
  12. 576         unsigned int            f_uid, f_gid;  
  13. 577         int                     f_error;  
  14. 578   
  15. 579         size_t                  f_maxcount;  
  16. 580         unsigned long           f_version;  
  17. 581   
  18. 582         /* needed for tty driver, and maybe others */  
  19. 583         void                    *private_data;  
  20. 584   
  21. 585         /* preallocated helper kiobuf to speedup O_DIRECT */  
  22. 586         struct kiobuf           *f_iobuf;  
  23. 587         long                    f_iobuf_lock;  
  24. 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

 

[cpp]  view plain  copy
 
 print?
  1. <span style="font-size:14px;">172 struct files_struct {  
  2. 173         atomic_t count;  
  3. 174         rwlock_t file_lock;     /* Protects all the below members.  Nests inside tsk->alloc_lock */  
  4. 175         int max_fds;  
  5. 176         int max_fdset;  
  6. 177         int next_fd;  
  7. 178         struct file ** fd;      /* current fd array */  
  8. 179         fd_set *close_on_exec;  
  9. 180         fd_set *open_fds;  
  10. 181         fd_set close_on_exec_init;  
  11. 182         fd_set open_fds_init;  
  12. 183         struct file * fd_array[NR_OPEN_DEFAULT];  
  13. 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結構體。

 

[cpp]  view plain  copy
 
 print?
  1. <span style="font-size:14px;">  5 struct fs_struct {  
  2.   6         atomic_t count;  
  3.   7         rwlock_t lock;  
  4.   8         int umask;  
  5.   9         struct dentry * root, * pwd, * altroot;  
  6.  10         struct vfsmount * rootmnt, * pwdmnt, * altrootmnt;  
  7.  11 };</span>  


解釋一些字段:

 

count:引用計數

lock:保護鎖

umask:打開文件時候默認的文件訪問權限

root:進程的根目錄

pwd:進程當前的執行目錄

altroot:用戶設置的替換根目錄

注意:實際運行時,這三個目錄不必定都在同一個文件系統中。例如,進程的根目錄一般是安裝於「/」節點上的ext文件系統,而當前工做目錄多是安裝於/etc的一個文件系統,替換根目錄也能夠不一樣文件系統中。

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

 

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

相關文章
相關標籤/搜索