unix 環境高階程式設計 閱讀第三章

2021-09-21 05:51:25 字數 3581 閱讀 9113

3.4 函式creat

3.5 函式close

3.6 函式lseek

3.7 函式read

3.8 函式write

3.9 i/o效率

3.10、檔案共享

3.11、原子操作

3.12、函式dup和函式dup2

3.13、函式sync

3.14、函式fcntl

3.15、函式ioctl

3.16、/dev/fd

3.17、小結

begintime:2019-05-02-12點30分

理解了術語不帶緩衝的i/o(unbuffered i/o),指的是每個read和write都呼叫核心中的乙個系統呼叫。這些不帶緩衝的i/o函式不是iso c的組成部分,但是,它們是posix.1和sus的組成部分。

只要涉及在多個程序間共享資源,原子操作的概念就變得非常重要。通過檔案i/o和open函式的引數來討論此概念。

明白對於核心而言,所有開啟的檔案都通過檔案描述符引用。

當開啟乙個現有檔案或建立乙個新檔案時,核心向程序返回乙個檔案描述符。

當讀、寫乙個檔案時,使用open或creat返回的檔案描述符標識該檔案,將其作為引數傳遞給read或write。

按照慣例,unix系統shell把檔案描述符0與程序的標準輸入相關聯,檔案描述符1與標準輸出相關聯,檔案描述符2與標準錯誤相關聯。這是各種shell以及很多應用程式使用的慣例,與unix核心無關。儘管如此,如果不遵循這種慣例,很多unix系統應用程式就不能正常工作。

在符號posix.1的應用程式中,幻數0、1、2雖然已被標準化,但應把它們替換成符號常量stdin_fileno、stdout_fileno和stderr_fileno以提高可讀性。在標頭檔案中定義。

檔案描述符的變化範圍是0~open_max-1,對於free bsd 8.0、linux 3.2.0、mac os 10.6.8、solaris 10以及solaris 10 檔案描述符的變化範圍幾乎是無限的。

我只能說,太詳細了,隨用隨查吧。。。

由open和openat函式返回的檔案描述符一定是最小的未用描述符數值。

這一點被某些應用程式用來在標準輸入、標準輸出或標準錯誤上開啟新檔案。例如,乙個應用程式可以先關閉標準輸出(通常是檔案描述符1),然後開啟另乙個檔案,執行開啟操作就能了解到該檔案一定會在檔案描述符1上開啟。更好的方法是使用dup函式,可以保證在乙個給定的描述符上開啟乙個檔案。

fd引數把open和openat函式區分開,共有3種可能性:

(1)(2)

(3)openat函式是posix.1最新版中新增的一類函式之一,希望解決兩個問題:

第一,讓執行緒可以使用相對路徑名開啟檔案目錄中的檔案,而不再只能開啟當前目錄。在第11章會看到,同一程序中的所有執行緒共享相同的當前工作目錄,因此很難讓同一程序的多個不同執行緒在同一時間工作在不同的目錄中。

第二,可以避免time-of-check-to-time-of-use(tocttou,檢查與使用時差)錯誤。

tocttou錯誤的基本思想是:如果有兩個基於檔案的函式呼叫,其中第二個呼叫依賴於第乙個呼叫的結果,那麼程式是脆弱的。

endtime:13點33分

begintime:2019-05-03-13點18分

如果name_max是14,而存在乙個檔名恰好就是14個字元,那麼以路徑名作為引數的任一函式(open、stat等)都無法確定該檔案的原始名是什麼。其原因是這些函式無法判斷該檔名是否被階段過。

在posix.1中,常量_posix_no_trunc決定是要截斷過長的檔名或路徑名,還是返回乙個出錯。正如我們在第2章中已經見過的,根據檔案系統型別,此值可以變化。可以使用fpathconf或pathconf來查詢目錄具體支援何種行為,到底是截斷過長的檔名還是返回出錯。

若_posix_no_trunc有效,則在整個路徑名超過path_max,或路徑名中的任一檔名超過name_max時,出錯返回,並將errno設定為enametoolong(錯誤名稱過長)。

在open函式提供了o_creat和o_trunc後不再需要單獨地creat函式。當然,想的話,還能使用

關閉乙個檔案時還會釋放該程序加在該檔案上的所有記錄鎖(14.3節再學)。

當乙個程序關閉時,核心自動關閉它所有的開啟檔案。很多程式都利用了這一功能而不顯示地呼叫close關閉開啟檔案。

可以呼叫lseek顯式地為乙個開啟檔案設定偏移量。

成功返回新的檔案偏移量;出錯,返回-1

這種方法也可用來確定所涉及的檔案是否可以設定偏移量。如果檔案描述符指向的是乙個管道、fifo或網路套接字,則lseek返回-1,並將errno 設定為espipe。

比較lseek的返回值時應當謹慎(因為在某些裝置中偏移量的值可以為負),不要測試它是否小於0,而要測試它是否等於-1。

lseek使用的偏移量是off_t型別

od命令詳解:

函式型別 ssize_t

如read成功,則返回讀到的位元組數。如已到達檔案的尾端,則返回0。

iso c標準中,型別void * 用於表示通用指標

其返回值通常與引數nbytes的值相同,否則表示出錯。write出錯的乙個常見原因是磁碟已寫滿,或者超過了乙個給定程序的檔案長度限制

如何選取合適的buffsize值

當buffsize的值為》=4096時,繼續增加緩衝區長度對系統cpu時間幾乎沒有影響。

大多數檔案系統為改善效能都採用某種預讀(read ahead)技術。當檢測到正進行順序讀取時,系統就試圖讀入比應用所要求的更多資料,並假想應用很快就會讀這些資料。

影響時鐘時間。

endtime:2019-05-03-15點38分

begintime:2019-05-04

對檔案系統相關部分的i-node(i節點)

對與檔案系統無關部分的v-node(v節點)有了清晰的認識

核心定義了三種資料結構表示開啟檔案:

(1)程序在程序表中有乙個記錄項

(2)核心為所有開啟檔案維護一張檔案表

(3)每個開啟檔案(或裝置)都有乙個v-node結構

以前在學習資料庫原理時學習過關係型資料庫的acid特性。

複製乙個現有的檔案的描述符。

新描述符的執行時關閉(close-on-exec)標誌總是由dup函式清除

延遲寫(delayed write)

在學習作業系統概念時有了解過。

endtime:2019-05-04-晚

begintime:2019-05-05

改變已經開啟的檔案的屬性

write函式只是將資料排入佇列,而實際的寫磁碟操作可能在以後的某個時刻進行

i/o操作的雜物箱。不能使用本章其他函式表示的i/o操作通常都能用ioctl函式表示。

其目錄項是名為0,1,2等的檔案。開啟檔案/dev/fd/n等效於複製描述符n(假定描述符n是開啟的)

主要由shell使用,它允許使用路徑名作為呼叫引數的程式,能用處理其他路徑名的相同方式處理標準輸入和輸出。

學習了和i/o相關的函式,對unix的檔案系統有了較為清晰的認識,v-node、i-node。在linux種實現為通用i-node與i-node。

UNIX環境高階程式設計習題 第三章

3.1 當讀 寫磁碟檔案時,本章中描述的函式確實是不帶緩衝機制的嗎?請說明原因 1 本章中描述的read和write函式都是系統呼叫,這兩個函式都是在核心中進行的,所以是不帶緩衝的i o函式。而帶有緩衝機制的函式是以記憶體空間作為緩衝區,避免不當操作降低多寫效能。3.2 編寫乙個與3.12節中dup...

unix 網路程式設計 第三章

包裹函式 就是對有錯誤返回值的函式的封裝。在unix網路程式設計中用大寫表示。err sys 必須要errno 的值才能輸出錯誤?執行緒函式遇到錯誤的時候 不設定errno的值,而是把error的值作為函式的返回值。必須檢查某個確定的錯誤,並處理它,而不是終止程序執行。unix errno 值 每當...

UNIX環境高階程式設計學習筆記 第三章 檔案I O

include int creat const char path,mode t mode 成功返回只寫開啟的檔案描述符,錯誤放回 1 等效 open path,o wronly o creat o trunc,mode o trunc 如果檔案存在,只寫或讀 寫成功開啟,則其長度截斷為0 crea...