FILE結構體與fd檔案識別符號

2021-08-01 01:48:17 字數 3371 閱讀 9509

開啟檔案:file *fopen(const

char *path,const

char* mode)

關閉檔案:int fclose(filee *fp)

讀檔案:size_t fread(void *ptr,size_t size,size_t nmemb,file *stream)

寫入檔案:size_t fwrite(const

void *ptr,size_t size,size_t nmemb,file* stream)

這裡提一下,上面這些函式都是通過流的形式來進行的,是和快取區打交道的東西,下面說到緩衝機制會詳細說。

先拿fopen來說,函式的返回值是file*,這是乙個檔案指標型別,

第乙個引數是檔案的路徑,第二個引數是開啟的方式。

如下:

「r」:開啟唯讀檔案,若不存在,則會報錯。

「w」:開啟只寫檔案,如果檔案內有內容則會被直接清空,若不存在,則會自動建立。

「a」:以追加方式開啟只寫檔案,若檔案不存在,則會自動建立,如果檔案存在,則在內容的最後進行寫入。

諸如"a+","w+","r+"則都是以可讀寫的方式,不在贅述

「b」:以二進位制的方式。

例:「ab+」 讀寫開啟乙個二進位制檔案,允許讀或在檔案末追加資料

說完這個文題,就該正式說下 file這個結構體了,file這個結構體包含了檔案操作的基礎屬性,其中重要的就是關於這個fd(檔案識別符號)的東西,因為在底層,作業系統是不會通過什麼檔案指標來查詢到檔案,而是通過檔案識別符號來操作的,所以,fd是file結構體很重要的東西。所以我們重點來看這個。

首先,檔案識別符號以一系列整數,它是從0開始,依次遞增的。但是一般的檔案識別符號都是從3開始的,這是因為系統預設開啟三個流(stdin,stdout,stderr)它們的識別符號依次為0,1,2,所以正常的檔案識別符號從3開始,但是當我們比如關掉0後,檔案識別符號就會先填滿0,然後繼續向後累加。所以,它的機制是從最低的空位開始。

每個程序在pcb(process control block)即程序控制塊中都儲存著乙份檔案描述符表(struct files_struct ),檔案描述符就是這個表的索引,檔案描述表中每個表項都有乙個指向已開啟檔案的指標,已開啟的檔案在核心中用file結構體表,檔案描述符表中的指標指向file結構體。

如下圖:

檔案描述符與檔案指標的區別

檔案描述符:在linux系統中開啟檔案就會獲得檔案描述符,它是個很小的正整數。每個程序在pcb(process control block)中儲存著乙份檔案描述符表,檔案描述符就是這個表的索引,每個表項都有乙個指向已開啟檔案的指標。檔案指標:c語言中使用檔案指標做為i/o的控制代碼。檔案指標指向程序使用者區中的乙個被稱為file結構的資料結構。file結構包括乙個緩衝區和乙個檔案描述符。而檔案描述符是檔案描述符表的乙個索引,因此從某種意義上說檔案指標就是控制代碼的控制代碼(在windows系統上,檔案描述符被稱作檔案控制代碼)。

首先,緩衝機制有三種

行緩衝:遇到\n換行即從緩衝區重新整理

全緩衝:當緩衝區資料填滿時重新整理

無緩衝:直接將資料輸出,不經過緩衝區

當然緩衝機制是可以更改的,你可以呼叫setbuf()setvbuf()函式來進行,不過我們重點用下面這個程式來介紹緩衝機制。

#include

#include

#include

#include

#include

#include

int main()

else(id == 0)

else

return

0;}

執行結果如下圖:

結果是不是和預料一樣,列印了5句話,那麼我們試下將執行結果寫入乙個檔案試試。

那麼這個結果呢?意不意外?為什麼5個輸出語句,卻列印出來了7句。更要注意的是,到底是哪兩句多打了。

這裡我們就要來分析一下了,先把文章開頭沒說的知識點說一下,就是對檔案的操作大致是兩種:

一、流式檔案操作:

fopen() 開啟流

fclose() 關閉流

fputc() 寫乙個字元到流中

fgetc() 從流中讀乙個字元

fseek() 在流中定位到指定的字元

fputs() 寫字串到流

fgets() 從流中讀一行或指定個字元

fprintf() 按格式輸出到流

fscanf() 從流中按格式讀取

feof() 到達檔案尾時返回真值

ferror() 發生錯誤時返回其值

rewind() 復位檔案定位器到檔案開始處

remove() 刪除檔案

fread() 從流中讀指定個數的字元

fwrite() 向流中寫指定個數的字元

tmpfile() 生成乙個臨時檔案流

tmpnam() 生成乙個唯一的檔名

這些函式都是先將資料交給緩衝區,然後在進行資料的一系列操作。

二、直接i/o檔案操作

open() 開啟乙個檔案並返回它的控制代碼

close() 關閉乙個控制代碼

lseek() 定位到檔案的指定位置

read() 塊讀檔案

write() 塊寫檔案

eof() 測試檔案是否結束

filelength() 取得檔案長度

rename() 重新命名檔案

chsize() 改變檔案長度

直接的i/o是不經過緩衝區的。

還有一點,當資料直接往顯示器輸出時,採用行緩衝,而一旦將資料寫入檔案,則由行緩衝變為全緩衝。(這裡的緩衝概念上面提過了,不贅述)

接下來仔細分析程式:

write不經過緩衝區,所以首先被列印出來(雖然程式中先定義printf和fwrite)

由於printf和fwrite是全緩衝,所以此時這兩個輸出結果在緩衝區中

fork()之後,產生子程序,**共享,資料各自持有乙份

fork()結束,父子程序各自重新整理,都會執行一次緩衝區中的資料

這個經典的例子如果搞明白,想必對這塊的知識理解能更加透徹。

以上是個人目前對這塊知識淺顯的認知,真心希望可以得到更多學習上的指點。

Linux 檔案描述符fd與FILE結構體

在linux中不是用檔案指標來識別乙個檔案,而是用檔案描述符來識別的。檔案描述符簡稱fd,它是linux核心所建立的索引,目的就是為了高效管理已經被開啟的檔案。它是乙個非負整數,用來表示被開啟的檔案,而對該檔案所有的i o操作都是通過該檔案的檔案描述符來執行的。在乙個程式剛剛啟動時,系統就已經佔了三...

fd與FILE結構體的縱向對比

檔案描述符 fd 對於linux而言,所有對裝置 對於linux而言,一切皆檔案 和檔案的操作都使用檔案描述符來進行的。檔案描述符是用來訪問檔案的。檔案描述符是乙個非負的整數,是乙個索引值,指向核心中每個程序開啟檔案的記錄表。當開啟乙個現存盤案或建立乙個新檔案時,核心就向程序返回乙個檔案描述符用於後...

FILE結構體與檔案描述符

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