Linux下 文件描述符(fd)與 文件指針(FILE*)

轉載。 https://blog.csdn.net/mm_hh/article/details/71374474

一、文件描述符(fd)
我們都知道在Linux下一切皆文件。當然設備也不例外,如果要對某個設備進行操作,就不得不打開此設備文件,打開文件就會獲得該文件的文件描述符fd( file discriptor), 它就是一個很小的整數,每個進程在PCB(Process Control Block)中保存着一份文件描述符表,文件描述符就是這個表的索引,每個表項都有一個指向已打開文件的指針。 

è¿éåå¾çæè¿°

圖中文件描述符即爲文件描述符數組的下標 
文件描述符的分配規律:從當前未使用的最小的整數開始分配; 
文件描述符的缺點: 
不能移植到UNIX以外的系統上去,也不直觀。

舉一個系統函數的例子:ssize_t write ( int fd, const void *buf, size_t count); 
write: 是系統寫函數 fd: 文件描述符 (一個整數) *buf: 內容寫在哪裏 count: 一次寫多少個;

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

fd詳解
fd:爲打開文件的文件描述符,而每個進程都有一張文件描述符表,fd文件描述符就是這張表的索引,同樣這張表中有一表項,該表項又是指向前面提到打開文件的file結構體,file結構體纔是內核中用來描述文件屬性的結構體。

FILE結構體
1、FILE結構體中的成員
緩衝區基址,緩衝區當前指針,緩衝區大小,緩衝區剩餘字節數,文件讀寫方式等。

struct FILE
{
    char *_ptr;//文件輸入的下一個位置
    int _cnt;//當前緩衝區的相對位置
    char *_base;//指基礎位置(文件的起始位置)
    int _flag;//文件標誌
    int _file;//文件的有效性驗證
    int _charbuf;//檢查緩衝區狀況,如果緩衝區則不讀取
    int _bufsiz;//文件的大小
    char *_tmpfname;//臨時文件名
};
2、(FILE*)文件指針
文件指針指向進程用戶區中一個被叫做FILE結構的結構數據。FILE結構包括一個緩衝區和一個文件描述符 。而文件描述符是文件描述符表的一個索引,因此從某種意義上說文件指針就是句柄的句柄(在Windows系統上,文件描述符被稱作文件句柄)。 
通常,任何程序運行起來之後都會默認的打開三個標準輸入流(stdin:鍵盤),標準輸出流(stdout:顯示器),標準錯誤流(stderr:顯示器)。

文件描述符與文件指針的區別
簡單歸納:fd只是一個整數,在open時產生,起到一個索引的作用,進程通過PCB中的文件描述符表找到該fd所指向的文件指針file。 
open:文件描述符的操作(如:open)返回的是一個文件描述符(int fd),內核會在每個進程空間中維護一個文件描述符表,所有打開的文件都將通過,此表中的文件描述符來引用。 
fopen:流(如:fopen)返回的是一個文件指針(即指向FILE結構體的指針),FILE結構是包含有文件描述符的,fopen可以看做是open(fd直接操作的系統調用)的封裝,它的優點是帶有I/O緩存。 
C語言的文件指針與文件描述符的相互轉換可通過fdopen和fileno兩個函數實現。它們都包含在頭文件stdio.h中。 
fdopen的原型:

FILE *fdopen(int filedes,const char *opentype);

第一個參數filedes是一個打開的文件描述符,opentype是表示打開方式的字符串,和fopen函數具有相同的取值,比如”w”或”w+”等。但是你必須保證該字符串的描述和文件實際的打開方式是匹配的。函數fopen()就是返回打開文件的指針;如果操作失敗,返回空指針null。

把文件流指針轉換成文件描述符用fileno函數, 
其原型爲:

int fileno(FILE *stream);

它返回的是和stream文件流對應的文件描述符。如果失敗,返回-1; 
當程序執行時,就已經有三個標準文件流打開了,它們分別是(標準輸入)stdin,(標準輸出)stdout,(標準錯誤輸出)stderr,和流式文件相對應的是,也有三個文件描述符被預先佔用(它們分別是: 
0((標準輸入)stdin),1((標準輸出)stdout),2((標準錯誤輸)stderr));\

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章