linux 程序檔案 檔案描述符
阿新 • • 發佈:2019-02-12
簡單歸納:fd只是一個整數,在open時產生。起到一個索引的作用,程序通過PCB中的檔案描述符表找到該fd所指向的檔案指標filp。
檔案描述符的操作(如: open)返回的是一個檔案描述符,核心會在每個程序空間中維護一個檔案描述符表, 所有開啟的檔案都將通過此表中的檔案描述符來引用;
而流(如: fopen)返回的是一個FILE結構指標, FILE結構是包含有檔案描述符的,FILE結構函式可以看作是對fd直接操作的系統呼叫的封裝, 它的優點是帶有I/O快取
Linux支援各種各樣的檔案系統格式,如ext2、ext3、reiserfs、FAT、NTFS、iso9660等等,不同的磁碟分割槽、光碟或其它儲存裝置都有不同的檔案系統格式,然而這些檔案系統都可以mount
ls
命令看起來是一樣的,讀寫操作用起來也都是一樣的,這是怎麼做到的呢?Linux核心在各種不同的檔案系統格式之上做了一個抽象層,使得檔案、目錄、讀寫訪問等概念成為抽象層的概念,因此各種檔案系統看起來用起來都一樣,這個抽象層稱為虛擬檔案系統(VFS,Virtual
Filesystem)。上一節我們介紹了一種典型的檔案系統在磁碟上的儲存佈局,這一節我們介紹執行時檔案系統在核心中的表示。
3.1. 核心資料結構
Linux核心的VFS子系統可以圖示如下:
查詢方法:
cd /usr/src/kernels/任意核心/include/linux
grep -r -n struct\ file ./* | grep { //很多都是指標,只有包含 { 的行才是定義
- struct file
- {
- struct list_head f_list; /*所有開啟的檔案形成一個連結串列*/
- struct dentry *f_dentry; /*指向相關目錄項的指標*/
- struct vfsmount *f_vfsmnt; /*指向VFS安裝點的指標*/
- struct file_operations *f_op;
- mode_t f_mode; /*檔案的開啟模式*/
- loff_t f_pos; /*檔案的當前位置*/
- unsigned short f_flags; /*開啟檔案時所指定的標誌*/
- unsigned short f_count; /*使用該結構的程序數*/
- unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;
- /*預讀標誌、要預讀的最多頁面數、上次預讀後的檔案指標、預讀的位元組數以及預讀的頁面數*/
- int f_owner; /* 通過訊號進行非同步I/O資料的傳送*/
- unsigned int f_uid, f_gid; /*使用者的UID和GID*/
- int f_error; /*網路寫操作的錯誤碼*/
- unsigned long f_version; /*版本號*/
- void *private_data; /* tty驅動程式所需 */
- };
核心中,對應於每個程序都有一個檔案描述符表,表示這個程序開啟的所有檔案。檔案描述表中每一項都是一個指標,指向一個用於描述開啟的檔案的資料塊———file物件,file物件中描述了檔案的開啟模式,讀寫位置等重要資訊,當程序開啟一個檔案時,核心就會建立一個新的file物件。需要注意的是,file物件不是專屬於某個程序的,不同程序的檔案描述符表中的指標可以指向相同的file物件,從而共享這個開啟的檔案。file物件有引用計數,記錄了引用這個物件的檔案描述符個數,只有當引用計數為0時,核心才銷燬file物件,因此某個程序關閉檔案,不影響與之共享同一個file物件的程序.
file物件中包含一個指標,指向dentry物件。dentry物件代表一個獨立的檔案路徑,如果一個檔案路徑被開啟多次,那麼會建立多個file物件,但它們都指向同一個dentry物件。 dentry物件中又包含一個指向inode物件的指標,也就是在file——struct。inode物件代表一個獨立檔案。因為存在硬連結與符號連結,因此不同的dentry物件可以指向相同的inode物件.inode 物件包含了最終對檔案進行操作所需的所有資訊,如檔案系統型別、檔案的操作方法、檔案的許可權、訪問日期等。 開啟檔案後,程序得到的檔案描述符實質上就是檔案描述符表的下標,核心根據這個下標值去訪問相應的檔案物件,從而實現對檔案的操作。注意,同一個程序多次開啟同一個檔案時,核心會建立多個file物件。 當程序使用fork系統呼叫建立一個子程序後,子程序將繼承父程序的檔案描述符表,因此在父程序中開啟的檔案可以在子程序中用同一個描述符訪問。