總結open與fopen的區別

2020-08-08 13:24:02

原文:https://www.zybuluo.com/yiltoncent/note/87461
對於這兩個名字很類似的函數,對於很多初學者來說,不容易搞清楚它們有什麼不同,只知道按照函數用法使用。如果能很好的區分兩者,相信大家對於C語言和UNIX系統(包括LINUX)有更深入的瞭解。

在網上查詢了一些資料,但是感覺不夠全面,一些答案只是從某個角度闡述,所以讓人覺得,這個也對,那個也對。但到底誰的表述更正確呢?其實都是對的,只是解釋的視角不同罷了。下面 下麪結合個人的理解做一些梳理。

1. 來源

從來源的角度看,兩者能很好的區分開,這也是兩者最顯而易見的區別:

open是UNIX系統呼叫函數(包括LINUX等),返回的是檔案描述符(File Descriptor),它是檔案在檔案描述符表裏的索引。
fopen是ANSIC標準中的C語言庫函數,在不同的系統中應該呼叫不同的內核api。返回的是一個指向檔案結構的指針。
PS:從來源來看,兩者是有千絲萬縷的聯繫的,畢竟C語言的庫函數還是需要呼叫系統API實現的。

2. 移植性

這一點從上面的來源就可以推斷出來,fopen是C標準函數,因此擁有良好的移植性;而open是UNIX系統呼叫,移植性有限。如windows下相似的功能使用API函數CreateFile

3. 適用範圍

open返迴檔案描述符,而檔案描述符是UNIX系統下的一個重要概念,UNIX下的一切裝置都是以檔案的形式操作。如網路通訊端、硬體裝置等。當然包括操作普通正規檔案(Regular File)。
fopen是用來操縱普通正規檔案(Regular File)的。

4. 檔案IO層次

如果從檔案IO的角度來看,前者屬於低階IO函數,後者屬於高階IO函數。低階和高階的簡單區分標準是:誰離系統內核更近。低階檔案IO執行在內核態,高階檔案IO執行在使用者態。

5. 緩衝

緩衝檔案系統
緩衝檔案系統的特點是:在記憶體開闢一個「緩衝區」,爲程式中的每一個檔案使用;當執行讀檔案的操作時,從磁碟檔案將數據先讀入記憶體「緩衝區」,裝滿後再從記憶體「緩衝區」依此讀出需要的數據。執行寫檔案的操作時,先將數據寫入記憶體「緩衝區」,待記憶體「緩衝區」裝滿後再寫入檔案。由此可以看出,記憶體「緩衝區」的大小,影響着實際操作外存的次數,記憶體「緩衝區」越大,則操作外存的次數就少,執行速度就快、效率高。一般來說,檔案「緩衝區」的大小隨機器 而定。fopen, fclose, fread, fwrite, fgetc, fgets, fputc, fputs, freopen, fseek, ftell, rewind等。
非緩衝檔案系統
緩衝檔案系統是藉助檔案結構體指針來對檔案進行管理,通過檔案指針來對檔案進行存取,既可以讀寫字元、字串、格式化數據,也可以讀寫二進制數據。非緩衝檔案系統依賴於操作系統,通過操作系統的功能對檔案進行讀寫,是系統級的輸入輸出,它不設檔案結構體指針,只能讀寫二進制檔案,但效率高、速度快,由於ANSI標準不再包括非緩衝檔案系統,因此建議大家最好不要選擇它。open, close, read, write, getc, getchar, putc, putchar等。
一句話總結一下,就是open無緩衝,fopen有緩衝。前者與read, write等配合使用, 後者與fread,fwrite等配合使用。

使用fopen函數,由於在使用者態下就有了緩衝,因此進行檔案讀寫操作的時候就減少了使用者態和內核態的切換(切換到內核態呼叫還是需要呼叫系統呼叫API:read,write);而使用open函數,在檔案讀寫時則每次都需要進行內核態和使用者態的切換;表現爲,如果順序存取檔案,fopen系列的函數要比直接呼叫open系列的函數快;如果隨機存取檔案則相反。

這樣一總結梳理,相信大家對於兩個函數及系列函數有了一個更全面清晰的認識,也應該知道在什麼場合下使用什麼樣的函數更合適,效率更高。