天天看點

《Linux系統程式設計(第2版)》——2.8 定位讀寫

本節書摘來自異步社群《linux系統程式設計(第2版)》一書中的第2章,第2.8節,作者:【美】robert love著,更多章節内容可以通路雲栖社群“異步社群”公衆号檢視

linux提供了兩種read()和write()系統調用的變體來替代lseek(),每次讀寫操作時,都把檔案位置作為參數,在完成時,不會更新檔案位置。

read()的變體是pread():

《Linux系統程式設計(第2版)》——2.8 定位讀寫

該調用會從檔案描述符fd的pos位置開始讀取,共讀取count個位元組到buf中。

write()的變體是pwrite():

《Linux系統程式設計(第2版)》——2.8 定位讀寫

該調用從檔案描述符fd的pos位置開始,從buf中寫count位元組到檔案中。

這兩個調用和read()、write()調用的最主要差別在于它們完全忽略了目前檔案位置;相反,pread()和pwrite()調用用的是參數pos值。此外,當調用完成時,它們不會更新檔案位置指針。換句話說,任何read()和write()交替調用可能會破壞定位讀寫的結果。

定位讀寫隻适用于可查找的檔案描述符,包括普通檔案。pread()和pwrite()調用的語義相當于在read()或write()調用之前執行lseek()調用,但仍然存在以下三點差別。

1.pread()和pwrite()調用更易于使用,尤其是對于一些複雜的操作,比如在檔案中反向或随機查找定位。

2.pread()和pwrite()調用在結束時不會修改檔案位置指針。

3.最重要的一點,pread()和pwrite()調用避免了在使用lseek()時會出現的競争。

由于線程共享檔案表,而目前檔案位置儲存在共享檔案表中,可能會發生這樣的情況:程序中的一個線程調用lseek()後,在執行讀寫操作之前,另一個線程更新了檔案位置。也就是說,當程序中存在多個線程操作同一個檔案描述符時,lseek()有潛在競争可能。這些競争場景可以通過pread()和pwrite()調用來避免。

錯誤碼

pread()和pwrite()調用執行成功時,分别傳回讀或寫的位元組數。如果pread()傳回0,表示eof;如果pwrite()傳回0,表示什麼都沒寫。出錯時,兩個調用都傳回-1,并相應設定errno值。對于pread(),可能出現任何有效的read()或lseek() 的errno值。對于pwrite(),也可能出現任何有效的write ()或lseek()的errno值

繼續閱讀