Linux-文件描述符的本質及與文件指針的區別

文章參考:文件描述符的本質文件描述符和文件指針的區別文件描述符fd和文件指針flip的理解html

推薦:task_struct 和文件系統的關係node

系統中文件相關表linux

  右側的表稱爲i節點表,在整個系統中只有1張。該表能夠視爲結構體數組,該數組的一個元素對應於一個物理文件。數組

  中間的表稱爲文件表,在整個系統中只有1張。該表能夠視爲結構體數組,一個結構體中有不少字段,其中有3個字段比較重要:緩存

    file status flags:用於記錄文件被打開來讀的,仍是寫的。其實記錄的就是open調用中用戶指定的第2個參數
    current file offset:用於記錄文件的當前讀寫位置(指針)。正是因爲此字段的存在,使得一個文件被打開並讀取後,下一次讀取將從上一次讀取的字符後開始讀取
    v-node ptr:該字段是指針,指向右側表的一個元素,從而關聯了物理文件。數據結構

  左側的表稱爲文件描述符表,每一個進程有且僅有1張。該表能夠視爲指針數組,數組的元素指向文件表的一個元素。最重要的是:數組元素的下標就是大名鼎鼎的文件描述符,數組元素的值就是指向 File 結構體的指針函數

 

系統調用時的操做ui

  文件描述符的操做函數 open, 返回一個文件描述符,內核會在每一個進程空間中維護一個文件描述符表,全部打開的文件都將經過此表中的文件描述符來引用。spa

    新建一個i節點表元素,讓其對應打開的物理文件(若是對應於該物理文件的i節點元素已經創建,就不作任何操做);.net

    新建一個文件表的元素,根據open的第2個參數設置file status flags字段,將current file offset字段置0,將v-node ptr指向剛創建的i節點表元素;

    在文件描述符表中,尋找1個還沒有使用的元素,在該元素中填入一個指針值,讓其指向剛創建的文件表元素。最重要的是:將該元素的下標做爲open的返回值返回。

  文件描述符的操做函數 read(write,)根據傳入的文件描述符,OS就能夠找到對應的文件描述符表元素,進而找到文件表的元素,進而找到i節點表元素,從而完成對物理文件的讀寫。

  而流操做函數 fopen, 返回的是一個FILE結構指針,FILE結構是包含有文件描述符的,FILE結構函數能夠看做是對fd直接操做的系統調用的封裝,它的優勢是帶有I/O緩存。

 

文件描述符和文件指針的概念一總

  文件描述符:在linux系統中打開文件就會得到文件描述符,它是個很小的正整數。每一個進程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是這個表的索引,每一個表項都有一個指向已打開文件的指針。即已打開的文件在內核中用 File 結構體表示,文件描述符表中的指針指向 File 結構體優勢是兼容POSIX標準,許多系統調用都依賴於它;缺點是不能移植到unix以外的系統上去

  文件指針:C語言中使用文件指針而不是文件描述符作爲I/O的句柄。文件指針指向進程用戶區中的一個被稱爲FILE結構的數據結構。FILE結構主要包括一個I/O緩衝區和一個文件描述符。而文件描述符是文件描述符表中的一個索引,所以從某種意義上說文件指針就是句柄的句柄(在Windows系統上,文件描述符被稱做文件句柄)。至關於在上圖中最左側又虛擬出一個 struct File,其中 struct 中有個元素是文件描述符,指向進程表項中的 fd 索引(本身的理解,不知道正不正確)。文件指針的優勢是C語言中的通用格式,便於移植。

  既然FILE結構中含有文件描述符,那麼可使用fopen來得到文件指針,而後從文件指針獲取文件描述符,文件描述符應該是惟一的,而文件指針卻不是惟一的,但指向的對象是惟一的

 

進程與文件描述符

  內核會在每一個進程空間中維護一個文件描述符表, 全部打開的文件都將經過此表中的文件描述符來引用; 而流(如: fopen)返回的是一個FILE結構指針, FILE結構是包含有文件描述符的,FILE結構函數能夠看做是對fd直接操做的系統調用的封裝, 它的優勢是帶有I/O 緩存。

  每一個進程在PCB(Process Control Block)即進程控制塊中都保存着一份文件描述符表,文件描述符就是這個表的索引,文件描述表中每一個表項都有一個指向已打開文件的指針,如今咱們明確一下:已打開的文件在內核中用 FILE 結構體表示,文件描述符表中的指針指向 FILE 結構體

 

fork 對文件描述符的影響

  fork會致使子進程繼承父進程打開的文件描述符,其本質是將父進程的整個文件描述符表複製一份,放到子進程的PCB中。所以父、子進程中相同文件描述符(文件描述符爲整數)指向的是同一個文件表元素,這將致使父(子)進程讀取文件後,子(父)進程將讀取同一文件的後續內容。因此在建立守護進程時,都使用 close 關閉掉從父進程繼承的文件描述符

 

FILE的結構

struct _iobuf {
  char *_ptr; //緩衝區當前指針
  int _cnt; //文件的引用計數
  char *_base; //緩衝區基址
  int _flag; //文件讀寫模式
  int _file; //文件描述符
  int _charbuf; //緩衝區剩餘本身個數
  int _bufsiz; //緩衝區大小
  char *_tmpfname;
};
typedef struct _iobuf FILE;

 

open和fopen的區別

  open:返回一個文件描述符,無緩衝,與 write、read 配合使用

  fopen:返回 File *,有緩衝,與 fwrite、fread 配合使用

相關文章
相關標籤/搜索