轉自:http://blog.csdn.net/shanshanpt/article/details/38943731
http://elixir.free-electrons.com/linux/v4.14.9/source/arch/arm64/kernel/acpi.c
一:
什么是文件系統,詳見: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,可以存在多個“實際的文件系統”,例如:ext2,ext3,fat32,ntfs...例如我現在有多個分區,對於每一個分區我們知道可以是不同的“實際文件系統”,例如現在三個磁盤分區分別是:ext2,ext3,fat32,那么每個“實際的文件系統”的操作和數據結構什么肯定不一樣,那么,用戶怎么能透明使用它們呢?那么這個時候就需要VFS作為中間一層!用戶直接和VFS打交道。例如read,write,那么映射到VFS中就是sys_read,sys_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: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最大數量就是文件的最大數量。
維基上說的也比較詳細:維基-inode
- <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_buffers和i_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:對應於上面三個的安裝點。
基本的概念和基本的結構總結完了,后面會總結看看這些之間的關系。
