1. 程式人生 > >fwrite/fread 導致system 記憶體不斷減少

fwrite/fread 導致system 記憶體不斷減少

  在emeded linux系統中通過迴圈讀取一個大檔案,使用fread來讀到一塊固定大小的記憶體,在讀取的過程中系統記憶體不斷減小,可能是fread有快取的原因,但是通過setvbuf(fpTsFileIn,NULL,_IONBF,0);設定快取大小為0,讀取檔案的過程系統記憶體還是會不斷減少。
   
   fwrite寫檔案也存在同樣的問題。
   
   系統記憶體減少到6-7M的時候,繼續讀寫檔案,記憶體就不在減少了,可能真是檔案快取的問題。
   

open系統呼叫,返回的是檔案描述符,即檔案控制代碼,是檔案在檔案描述副表裡的索引。

fopenC語言庫函式,返回的是一個指向檔案結構的指標

fopenANSI C標準中的C語言庫函式,在不同的作業系統中應該呼叫不同的核心APIUNIX環境下,fopen是對open的封裝。

檔案描述符是UNIX/Linux下的一個概念,Linux環境下,一切裝置皆是檔案一切裝置皆是以檔案的形式進行操作,如網路套接字、硬體裝置等。有關檔案描述符和檔案指標的區別可以參見博文:《檔案描述符和檔案指標的區別》

裝置檔案不可以當成流式檔案來處理,因此,只能使用open,而fopen只是用來操縱正規檔案的,並且設定有緩衝,跟open還是有區別的。

openfopen的區別在於:

1.緩衝檔案系統

緩衝檔案系統是藉助於檔案結構體指標FILE *

來對檔案進行管理,通過檔案指標對檔案進行訪問,即可以讀寫字元、字串、格式化資料,也可以讀寫二進位制資料。

緩 衝檔案系統特點:在記憶體中開闢一個“緩衝區”,為程式裡每一個檔案使用,當執行讀檔案操作時,從磁碟檔案將資料先讀入記憶體“緩衝區”,裝滿後再從記憶體“緩 衝區”依次讀入接收的變數。執行寫檔案操作時,也是先將資料寫入記憶體“緩衝區”,待記憶體“緩衝區”裝滿後再寫入檔案。由此可以看出,記憶體“緩衝區”的大 小,影響著實際操作外在的次數,記憶體“緩衝區”越大,則操作外存的次數就越少,執行速度就越快,效率就越高。一般來說,檔案“緩衝區”的大小跟機器是相關 的。

緩衝檔案系統的IO函式主要包括:

fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind

2.非緩衝檔案系統

非緩衝檔案系統依賴於作業系統,通過作業系統的功能對檔案進行讀寫,是系統級的輸入輸出,它不設檔案結構體指標,只能讀寫二進位制檔案(對於UNIX系統核心而言,文字檔案和二進位制程式碼檔案並無區別),但效率高、速度快,由於ANSI標準不再包括非緩衝檔案系統,因此,在讀取正規的檔案時,建議大家最好不要選擇它。

非緩衝檔案系統的IO函式主要包括:open, close, read, write, getc, getchar, putc, putchar等。

舉個例子來說明open系列函式與fopen系列函式的效率問題:如果檔案的大小是8k

你如果用read/write,且只分配了2K的快取,則要將此檔案讀出需要做4次系統呼叫來實際從磁碟上讀出。如果你用fread/fwrite,則系統自動分配快取,則讀出此檔案只要一次系統呼叫從磁碟上讀出。也就是用read/write要讀4次磁碟,而用fread/fwrite則只要讀1次磁碟。效率比read/write要高4倍。如果程式對記憶體有限制,則用read/write比較好。都用fread fwrite,它自動分配快取,速度會很快,比自己來做要簡單。如果要處理一些特殊的檔案,用read write,如套介面,管道之類的裝置檔案。

系統呼叫write的效率取決於你buffer的大小和你要寫入的總數量,如果buffer太小,你進入核心空間的次數大增,效率就低下。而fwrite會替你做快取,減少了實際出現的系統呼叫,所以效率比較高。

如果只調用一次(這種可能性比較小),這倆差不多,嚴格來說write要快一點點,因為實際上fwrite封裝了write,最後還是用write做真正的寫入檔案系統工作,但是這其中的差別無所謂。

openfopen最主要的區別在於fopen在使用者態下就有了快取,在進行readwrite時,減少了使用者態和核心態的切換,而open則每次都需要進行核心態和使用者態的切換,其表現為:如果順序訪問檔案,fopen系統的函式要比直接呼叫open系統函式快,如果隨機訪問檔案,open系列函式要比fopen系列函式快。

因此,open系列函式與fopen系列的區別可以簡單概括為:

open系列函式

fopen系列函式

一般用於開啟裝置檔案(少數情況)

一般用於開啟普通檔案(大多數情況)

利用檔案描述符操縱檔案

利用檔案指標操作檔案

open返回一個檔案描述符

fopen返回一個檔案指標

POSIX系統呼叫

ANSI C庫函式

低層次IO

高層次IO,對open的擴充套件和封裝

只能在POSIX作業系統上移植

可移植到任何作業系統

非緩衝IO

緩衝IO

只能讀取二進位制或普通文字

可以讀取一個結構

可以指定要建立檔案的訪問許可權

不能指定要建立檔案的訪問許可權

fread返回的是一個FILE結構指標而read返回的是一個int的檔案號前者fopen/fread的實現是靠呼叫底層的open/read來實現的.fopen/fread是C標準的庫函式,操作的物件是: file streamopen/read是和作業系統有關的系統呼叫。操作的物件是: “file descriptor”f是ANSI的C標準庫。後面的是UNIX下的系統呼叫。帶f的帶有緩衝,是後面的衍生,直接和硬體打交道,必須是後面的!

UNIX環境下的C對二進位制流檔案的讀寫有兩套班子:1) fopen,fread,fwrite ; 2) open, read, write這裡簡單的介紹一下他們的區別。1. fopen系列是標準的C庫函式;open系列是POSIX定義的,是UNIX系統裡的system call。也就是說,fopen系列更具有可移植性;而open系列只能用在POSIX的作業系統上2.使用fopen系列函式時要定義一個指代檔案的物件,被稱為“檔案控制代碼”(file handler),是一個結構體;而open系列使用的是一個被稱為“檔案描述符”(file descriptor)的int型整數。3. fopen系列是級別較高的I/O,讀寫時使用緩衝;而open系列相對低層,更接近作業系統,讀寫時沒有緩衝。由於能更多地與作業系統打交道,open系列可以訪問更改一些fopen系列無法訪問的資訊,如檢視檔案的讀寫許可權。這些額外的功能通常因系統而異。4.使用fopen系列函式需要"#include ";使用open系列函式需要"#include ",連結時要之用libc(-lc)小結:總的來說,為了使程式獲得更好的可移植性,未到非得使用一些fopen系列無法實現的功能的情況下,fopen系列是首選。

read/write和fread/fwrite區別

1,fread是帶緩衝的,read不帶緩衝.

eg:

如果檔案的大小是8k。你如果用read/write,且只分配了2k的快取,則要將此檔案讀出需要做4次系統呼叫來實際從磁碟上讀出。如果你用fread/fwrite,則系統自動分配快取,則讀出此檔案只要一次系統呼叫從磁碟上讀出。也就是用read/write要讀4次磁碟,而用fread/fwrite則只要讀1次磁碟。效率比read/write要高4倍。

如果程式對記憶體有限制,則用read/write比較好2,fopen是標準c裡定義的,open是POSIX中定義的.3,fread可以讀一個結構. read在linux/unix中讀二進位制與普通檔案沒有區別.4,fopen不能指定要建立檔案的許可權.open可以指定許可權.5,fopen返回指標,open返回檔案描述符(整數).6,linux/unix中任何裝置都是檔案,都可以用open,read.都用fread和fwrite,它自動分配快取,速度會很快,比自己來做要簡單。如果要處理一些特殊的描述符,用read和write,如套介面,管道之類的系統呼叫write的效率取決於你buf的大小和你要寫入的總數量,如果buf太小,你進入核心空間的次數大增,效率就低下。而fwrite會替你做快取,減少了實際出現的系統呼叫,所以效率比較高。如果只調用一次(可能嗎?),這倆差不多,嚴格來說write要快一點點(因為實際上fwrite最後還是用了write做真正的寫入檔案系統工作),但是這其中的差別無所謂。