1. 程式人生 > >linux 程序檔案 檔案描述符

linux 程序檔案 檔案描述符

簡單歸納: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子系統可以圖示如下:

33

查詢方法:

cd  /usr/src/kernels/任意核心/include/linux

grep -r -n  struct\ file ./*  |   grep  {                              //很多都是指標,只有包含 { 的行才是定義

  1. struct file    
  2. {   
  3.  struct list_head        f_list;    /*所有開啟的檔案形成一個連結串列*/
  4.  struct dentry           *f_dentry; /*指向相關目錄項的指標*/
  5.  struct vfsmount         *f_vfsmnt; /*指向VFS安裝點的指標*/
  6.  struct file_operations  *f_op;     
    /*指向檔案操作表的指標*/
  7.  mode_t f_mode;                                  /*檔案的開啟模式*/
  8.  loff_t f_pos;                                   /*檔案的當前位置*/
  9.  unsigned short f_flags;                         /*開啟檔案時所指定的標誌*/
  10.  unsigned short f_count;                           /*使用該結構的程序數*/
  11.  unsigned long f_reada, f_ramax, f_raend, f_ralen, f_rawin;  
  12.  /*預讀標誌、要預讀的最多頁面數、上次預讀後的檔案指標、預讀的位元組數以及預讀的頁面數*/
  13.  int f_owner;                  /* 通過訊號進行非同步I/O資料的傳送*/
  14.  unsigned int         f_uid, f_gid;  /*使用者的UID和GID*/
  15.  int                 f_error;       /*網路寫操作的錯誤碼*/
  16.  unsigned long f_version;           /*版本號*/
  17.  void *private_data;                      /* tty驅動程式所需 */
  18. };

核心中,對應於每個程序都有一個檔案描述符表,表示這個程序開啟的所有檔案。檔案描述表中每一項都是一個指標,指向一個用於描述開啟的檔案的資料塊———file物件,file物件中描述了檔案的開啟模式,讀寫位置等重要資訊,當程序開啟一個檔案時,核心就會建立一個新的file物件。需要注意的是,file物件不是專屬於某個程序的,不同程序的檔案描述符表中的指標可以指向相同的file物件,從而共享這個開啟的檔案。file物件有引用計數,記錄了引用這個物件的檔案描述符個數,只有當引用計數為0時,核心才銷燬file物件,因此某個程序關閉檔案,不影響與之共享同一個file物件的程序.

file物件中包含一個指標,指向dentry物件。dentry物件代表一個獨立的檔案路徑,如果一個檔案路徑被開啟多次,那麼會建立多個file物件,但它們都指向同一個dentry物件。 dentry物件中又包含一個指向inode物件的指標,也就是在file——struct。inode物件代表一個獨立檔案。因為存在硬連結與符號連結,因此不同的dentry物件可以指向相同的inode物件.inode 物件包含了最終對檔案進行操作所需的所有資訊,如檔案系統型別、檔案的操作方法、檔案的許可權、訪問日期等。 開啟檔案後,程序得到的檔案描述符實質上就是檔案描述符表的下標,核心根據這個下標值去訪問相應的檔案物件,從而實現對檔案的操作。

注意,同一個程序多次開啟同一個檔案時,核心會建立多個file物件。 當程序使用fork系統呼叫建立一個子程序後,子程序將繼承父程序的檔案描述符表,因此在父程序中開啟的檔案可以在子程序中用同一個描述符訪問。