Linux fd與FILE結構體

2021-08-17 21:48:56 字數 2386 閱讀 4572

學習檔案描述符fd和file結構體前,我們先了解一下系統i/o

(1)系統檔案i/o

我們學習c語言的時候,通過fopen(),fclose(),fread(),fwrite()等 i/o函式來操作檔案,同樣的,我們也可以採用系統介面open、close、write、read等來進行檔案訪問。

往檔案裡寫

#include

#include

#include

#include

#include

#include

int main()

int count = 5;

const

char* msg = "hello world\n";

int len = strlen(msg);

while(count--)

close(fd);

return

0;}

讀檔案

通過上圖我們可以很明顯的看出系統呼叫介面和庫函式的關係,可以認為,f#系列的函式,都是對系統呼叫的封裝,方便二次開發。

(2)檔案描述符fd

當我們開啟檔案時,作業系統在記憶體中要建立相應的資料結構來描述目標檔案,即file結構體,來表示已經開啟的檔案。程序執行open系統呼叫時必須讓程序和檔案關聯起來。每個程序都有乙個*file指標,指向一張表files_struct,這張表包含乙個檔案指標陣列,每個元素都是乙個指向開啟檔案的指標。所以,檔案描述符本質上是檔案指標陣列的下標。只要拿著fd,就可以找到對應的檔案。

從上面這張圖可以看出檔案描述符fd是乙個從0開始的小整數。

那當我們關閉標準輸入0時,重新開啟乙個檔案,它的fd是多少呢?

#include

#include

#include

#include

#include

int main()

printf("fd:%d\n",fd);

close(fd);

return

0;}

結果:

我們可以得出檔案描述符的分配規則:在files_struct陣列當中,找到沒有被使用的最小乙個下標,作為新的檔案描述符。而當關閉標準輸出1時,會發生重定向,他將本來應該顯示在螢幕上的內容顯示到了乙個開啟的檔案中。因為底層訪問檔案時,找的還是fd:1,而此時fd:1下標所表示的內容已經變成了乙個新開啟檔案的位址,而不再是顯示器的位址,所以會發生重定向。

(3)file結構體

從上面介紹我們可以得出訪問檔案都是通過fd訪問的,所以file結構體裡面一定封裝了fd。那file裡面還封裝了什麼?

先來看段**:

#include

#include

int main()

結果:

但是對程序實現輸出重定向後,發現結果變成:

除了write其他都輸出了兩次,這是為什麼?

其實,這就牽扯到了緩衝區的概念。緩衝資料有三種方式:無緩衝、行緩衝和全緩衝。當資料寫入顯示器時是行緩衝,遇到 「\n」就輸出,所以列印了三條語句。而往檔案裡面寫入時是全緩衝,fork後,父子資料寫時拷貝,當父程序準備重新整理的時候,子程序有了相同的乙份資料,隨機產生兩份資料,等程序退出後統一重新整理,這兩份資料都寫入了檔案中。

從上述例子可以看出,fwrite,printf庫函式自帶緩衝區,而write系統呼叫沒有,足以說明,該緩衝區是二次加上的,又因為是c,所以由c庫提供。

所以,c庫當中的file結構體內部一定也封裝了緩衝區。

file結構體和inode結構體

3 索引節點物件由inode結構體表示,定義檔案在linux fs.h中。inode 譯成中文就是索引節點。每個儲存裝置或儲存裝置的分割槽 儲存裝置是硬碟 軟盤 u盤 被格式化為檔案系統後,應該有兩部份,一部份是inode,另一部份是block,block是用來儲存資料用的。而inode呢,就是用來...

file結構體和inode結構體

3 索引節點物件由inode結構體表示,定義檔案在linux fs.h中。inode 譯成中文就是索引節點。每個儲存裝置或儲存裝置的分割槽 儲存裝置是硬碟 軟盤 u盤 被格式化為檔案系統後,應該有兩部份,一部份是inode,另一部份是block,block是用來儲存資料用的。而inode呢,就是用來...

FILE結構體與檔案描述符

首先解釋下為什麼要對這個結構體進行分析,我麼在進行c的學習時曾學習過這個file可以使用file 型別生成乙個指向檔案的指標,並且用於進行一系列檔案操作的傳值與接收。但對於file這個型別並沒有進行深究,那麼首先我們從題目可以知道這個我們熟悉的file型別其實是乙個結構體。既然是結構體,那麼就會有各...