Linux中的file結構體解析

2021-07-27 05:09:35 字數 3399 閱讀 9186

struct file(file結構體):

struct file結構體定義在include/linux/fs.h中定義。檔案結構體代表乙個開啟的檔案,系統中的每個開啟的檔案在核心空間都有乙個關聯的 struct file。

它由核心在開啟檔案時建立,並傳遞給在檔案上進行操作的任何函式。在檔案的所有例項都關閉後,核心釋放這個資料結構。在核心建立和驅動原始碼中,

struct file的指標通常被命名為file或filp。其有兩個非常重要的字段:檔案描述符和緩衝區。

檔案描述符fd:

fd只是乙個小整數,在open時產生。起到乙個索引的作用,程序通過pcb中的檔案描述符表找到該fd所指向的檔案指標filp。

檔案描述符的操作(如: open)返回的是乙個檔案描述符,核心會在每個程序空間中維護乙個檔案描述符表, 所有開啟的檔案都將通過此表中的檔案描述符來引用;

而流(如: fopen)返回的是乙個file結構指標, file結構是包含有檔案描述符的,file結構函式可以看作是對fd直接操作的系統呼叫的封裝, 它的優點是帶有i/o快取。

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

緩衝區:

a)緩衝區機制

根據應用程式對檔案的訪問方式,即是否存在緩衝區,對檔案的訪問可以分為帶緩衝區的操作和非緩衝區的檔案操作:

a) 帶緩衝區檔案操作:高階標準檔案i/o操作,將會在使用者空間中自動為正在使用的檔案開闢記憶體緩衝區。

b) 非緩衝區檔案操作:低階檔案i/o操作,讀寫檔案時,不會開闢對檔案操作的緩衝區,直接通過系統呼叫對磁碟進行操作(讀、寫等),當然用於可以在自己

的程式中為每個檔案設定緩衝區。

兩種檔案操作的解釋和比較:

1、非緩衝的檔案操作訪問方式,每次對檔案進行一次讀寫操作時,都需要使用讀寫系統呼叫來處理此操作,即需要執行一次系統呼叫,執行一次系統呼叫將涉

及到cpu狀態的切換,即從使用者空間切換到核心空間,實現程序上下文的切換,這將損耗一定的cpu時間,頻繁的磁碟訪問對程式的執行效率造成很大的影響。

2、ansi標準c庫函式 是建立在底層的系統呼叫之上,即c函式庫檔案訪問函式的實現中使用了低階檔案i/o系統呼叫,ansi標準c庫中的檔案處理函式為了減

少使用系統呼叫的次數,提高效率,採用緩衝機制,這樣,可以在磁碟檔案進行操作時,可以一次從檔案中讀出大量的資料到緩衝區中,以後對這部分的訪問就不需

要再使用系統呼叫了,即需要少量的cpu狀態切換,提高了效率。

b)緩衝型別

標準i/o提供了3種型別的緩衝區。

1、全緩衝區:這種緩衝方式要求填滿整個緩衝區後才進行i/o系統呼叫操作。對於磁碟檔案的操作通常使用全緩衝的方式訪問。第一次執行i/o操作時,ansi標

準的檔案管理函式通過呼叫malloc函式獲得需要使用的緩衝區,預設大小為8192。

2、行緩衝區:在行緩衝情況下,當在輸入和輸出中遇到換行符時,標準i/o庫函式將會執行系統呼叫操作。當所操作的流涉及乙個終端時(例如標準輸入和標準

輸出),使用行緩衝方式。因為標準i/o庫每行的緩衝區長度是固定的,所以只要填滿了緩衝區,即使還沒有遇到換行符,也會執行i/o系統呼叫操作,預設行緩衝區

的大小為1024。

3、無緩衝區:

無緩衝區是指標準i/o庫不對字元進行快取,直接呼叫系統呼叫。標準出錯流stderr通常是不帶緩衝區的,這使得出錯資訊能夠盡快地顯示出來。

注:1、標準輸入和標準輸出裝置:當且僅當不涉及互動作用裝置時,標準輸入流和標準輸出流才是全緩衝的。

2、標準錯誤輸出裝置:標準出錯絕不會是全緩衝方式的。

3、對於任何乙個給定的流,可以呼叫setbuf()和setvbuf()函式更改其緩衝區型別。

下面我們通過如下程式來進一步了解緩衝區:

我們檢視輸出到螢幕和寫到檔案中的區別:

那麼為什麼輸出到螢幕只有5條輸出命令而輸出到檔案有7條輸出命令呢?

根據輸出結果我們可以看出printf和fwrite重複寫了兩次,沒有重複列印的是write.。

printf和fwrite都是庫函式:結合已有知識,我們了解到當使用庫函式命令時,列印訊息並沒有直接寫到輸出位置上,而是 先把資料寫到輸出緩衝區,在重新整理至輸

出位置。

1、當輸出目標位置為輸出到顯示器時,則重新整理方式是行重新整理;

2、當輸出目標位置為輸出到檔案中時,重新整理方式由行緩衝變為全緩衝,全緩衝是指當把緩衝區寫滿後才能重新整理。(或者強制重新整理)

**中printf和fwrite第一次列印,在fork操作之前,第二次在fork操作之後,原因是因為在fork操作前,printf和fwrite的輸出命令將資料先寫到緩衝區中,此時

只執行了這兩條命令,由於是全緩衝的重新整理方式,所以這兩條命令並不足以將快取寫滿,所以資料暫存在緩衝區中;然後進行fork建立子程序,由於fork建立出的父子

程序**共享,而資料不共享,各自私有乙份,緩衝區中的資料都屬於資料,因為父程序的殘留資料還在緩衝區中,所以fork完畢後,父子程序將快取中的資料各自存

乙份有父程序殘留資料的資料,所以當父子程序各自重新整理時,父子程序會各自執行一次printf和fwrite的輸出命令,所以命令就從原來的兩條變為四條。

1.mode_t f_mode;

檔案模式確定檔案是可讀的或者是可寫的(或者都是), 通過位 fmode_read 和fmode_write. 你可能想在你的 open 或者 ioctl 函式中檢查這個成員的讀寫許可, 但是不需要檢查讀寫許可, 因為核心在呼叫你的方法之前檢查. 當檔案還沒有為那種訪問而開啟時讀或寫的企圖被拒絕, 驅動甚至不知道這個情況.

2.loff_t f_pos;

當前讀寫位置. loff_t 在所有平台都是 64 位( 在 gcc 術語裡是 long long ). 驅動可以讀這個值,如果它需要知道檔案中的當前位置, 但是正常地不應該改變它; 讀和寫應當使用它們作為最後引數而收到的指標來更新乙個位置, 代替直接作用於 filp->f_pos. 這個規則的乙個例外是在 llseek 方法中, 它的目的就是改變檔案位置.

3.unsigned int f_flags;

這些是檔案標誌, 例如 o_rdonly, o_nonblock, 和 o_sync. 驅動應當檢查o_nonblock 標誌來看是否是請求非阻塞操作; 其他標誌很少使用. 特別地, 應當檢查讀/寫許可, 使用 f_mode 而不是f_flags. 所有的標誌在標頭檔案

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呢,就是用來...

Linux fd與FILE結構體

學習檔案描述符fd和file結構體前,我們先了解一下系統i o 1 系統檔案i o 我們學習c語言的時候,通過fopen fclose fread fwrite 等 i o函式來操作檔案,同樣的,我們也可以採用系統介面open close write read等來進行檔案訪問。往檔案裡寫 inclu...