系統調用read,write和標準庫fread,fwrite的區別

read,write屬於Linux系統調用,fread,fwrite屬於C語言標準庫

使用系統調用會影響系統的性能。與函數調用相比,系統調用的開銷要大些,因爲在執行系統調用時,Linux必須從運行用戶代碼切換到執行內核代碼,然後再返回用戶代碼。減少這種開銷的一個好方法是,在程序中儘量減少系統調用的次數,並且讓每次系統調用完成儘可能多的工作。例如,每次讀寫大量的數據而不是每次僅讀寫一個字符。
硬件會限制對底層系統調用一次所能讀寫的數據塊大小。例如,磁帶機通常一次能寫的數據塊長度是10k。所以,如果你試圖寫的數據量不是10k的整數倍,磁帶機還是會以10k爲單位卷繞磁帶,從而在磁帶上留下了空隙。

當對文件區域加鎖之後(使用fcntl系統調用),你必須使用底層的read和write調用來訪問文件中的數據,而不要使用更高級的fread和fwrite調用,這是因爲fread和fwrite會對讀寫的數據進行緩存,所以執行一次fread調用來讀取文件中的頭100個字節可能(事實上,是幾乎肯定如此)會讀取超過100個字節的數據,並將多餘的數據在函數庫中進行緩存。如果程序再次使用fread來讀取下100個字節的數據,它實際上將讀取已緩衝在函數庫中的數據,而不會引發一個底層的read調用來從文件中取出更多的數據。 爲了說明這爲什麼是一個問題,讓我們來考慮這樣一個例子:兩個程序都打算更新同一個文件。假設這個文件由200個全爲零的字節組成。第一個程序先開始運行,並獲得該文件頭100個字節的寫鎖。它然後使用fread來讀取這100個字節。但是正如我們在前面章節中所看到的,fread會一次讀取多達BUFSIZE個字節的數據,因此,它實際上把整個文件都讀到了內存中,但僅把頭100個字節傳遞給程序。 接着,第二個程序開始運行。它獲得了文件後100個字節的寫鎖。這個操作將會成功,因爲第一個程序只鎖定了文件的前100個字節。第二個程序將100~199字節的數據都寫成2,關閉文件並解鎖,最後退出程序。這時,第一個程序鎖定了文件的後100個字節,然後調用fread來讀取數據。儘管真正存在於文件中的數據是100個字節的2,但是因爲先前數據已經被緩存,所以程序實際上讀到的數據將是100個字節的零。但如果你使用read和write,這個問題就不會發生。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章