fd與FILE結構體的縱向對比

文件描述符(fd)
對於Linux而言,所有對設備(對於Linux而言,一切皆文件)和文件的操作都使用文件描述符來進行的。文件描述符是用來訪問文件的。
文件描述符是一個非負的整數,是一個索引值,指向內核中每個進程打開文件的記錄表。
當打開一個現存文件或創建一個新文件時,內核就向進程返回一個文件描述符用於後續對文件的讀寫操作;當需要讀文件時,也需要把文件描述符作爲參數傳遞給相應的函數。
通常情況下,將一個程序從硬盤加載到內存後,這個程序就化身爲了一個進程,這時系統會默認打開三個文件:標準輸入(stdin)、標準輸出(stdout)、標準錯誤(stderr)。
這三個文件相對應的三個文件描述符分別爲0、1、2.所以後面如果創建新的文件,那麼此時這個新文件的文件描述符就是3了。這是因爲在Linux中,文件的描述符分配是從小到大逐個查詢文件描述符是否已經使用,然後再分配。
相應的如果你提前關閉了文件描述符1,那麼新建的文件描述符就是1。
這裏寫圖片描述
一個進程的文件描述符與對應的文件的關係簡圖:
這裏寫圖片描述

FILE結構體
C語言的stdio.h頭文件中,定義了用於文件操作的結構體FILE。這樣,我們通過fopen返回一個文件指針(指向FILE結構體的指針)來進行文件操作。
FILE結構體中最重要的兩個成員變量是:
文件描述符和緩衝區的大小

//C語言文件指針域文件描述符之間可以相互轉換
int fileno(FILE* stream)
FILE* fdopen(int fd,const char* mode)
struct _iobuf
{
    char* _ptr; //緩衝區當前指針
    int _cnt;
    char* _base;//緩衝區基址
    int _flag;//文件讀寫模式
    int _file;//文件描述符
    int _charbuf;//緩衝區剩餘自己個數
    int _bufsiz;//緩衝區大小
    char* _tmpfname;
}
typedef struct _iobuf FILE;

FILE結構體與文件描述符之間的關係:
這裏寫圖片描述
對上圖內容的簡要介紹:
1.進程打開一個文件的過程:
進程通過系統調用open()來打開一個文件,實質上是獲得一個文件描述符,以便於進程通過文件描述符來讀寫該文件、進程打開文件時,會爲該文件創建一個file對象,並將一個指向該file對象的指針存入進程描述符表(進程描述符數組),進而確定了打開文件的文件描述符(數組下標)。
open()系統調用是在內核裏通過sys_open()實現的;sys_open()將創建文件的dentry、inode和file對象。
創建file對象時,將file對象f_op指向了所屬文件系統的操作函數集file_operations,而該函數集又來自具體文件的i節點,於是虛擬文件系統就與實際文件系統的操作銜接起來了。
並在file_struct結構體的進程打開文件表fd_array[NR_OPEN_DEFAULT]中查找一個空閒表項(也就是此時數組中最小的未被佔用的表項),然後返回該表項的下標(文件描述符)。
2.
描述符數組存放在進程打開的文件表files_struct結構體中。
文件描述符數組中存放了一個進程所打開的所有文件
3.file_struct結構體定義:

struct files_struct { atomic_t count; /* 共享該表的進程數 */
rwlock_t file_lock; /* 保護以下的所有域,以免在tsk->alloc_lock中的嵌套*/
int max_fds; /*當前文件對象的最大數*/
int max_fdset;/*當前文件描述符的最大數*/
int next_fd; /*已分配的文件描述符加1*/
struct file ** fd; /* 指向文件描述符數組的指針 */
fd_set *close_on_exec; /*指向執行exec( )時需要關閉的文件描述符*/
fd_set *open_fds; /*指向打開文件描述符的指針*/
fd_set close_on_exec_init;/* 執行exec( )時需要關閉的文件描述符的初 值集合*/
fd_set open_fds_init; /*文件描述符的初值集合*/
struct file * fd_array[32];/* 文件對象指針的初始化數組*/};

4.file結構體:

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驅動程序所需 */
};

5.file結構體的幾個重要的成員變量:
f_flags:表示打開文件的權限
f_pos:表示當前讀寫文件的位置
f_count:表示打開文件的引用計數,如果有多個文件指針指向他,就會增加f_count的值
f_mode:設置對文件的訪問模式,例如:只讀、只寫、可讀可寫等

6.小結:
file_struct是操作系統用來管理文件的數據結構,當我們創建一個進程時,會創建文件描述符,進程控制塊PCB中的fs指針指向文件描述符表,當我們創建文件時,會爲指向該文件的指針FILE*關聯一個文件描述符並添加在文件描述符表中。在文件描述符表中fd相當於數組的索引,FILE*相當於數組的內容,指向一個文件結構體。

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