4 原子操作
5 高階函式
實際開始時間是2023年11月25號,以此來記錄我的apue學習之路,可能中間會有許多錯誤。
檔案i/o是指不帶緩衝的i/o,它直接呼叫核心的系統呼叫,這是與第5章標準i/o作對比,標準i/o是帶緩衝的i/o。我是這麼理解這兩者的區別:
(1)檔案i/o:程式(資料)—>記憶體緩衝—>硬碟(檔案系統)。
(2)標準i/o:程式(資料)—>陣列緩衝(buffer)—>記憶體緩衝—>硬碟。
也就是標準i/o完成操作後,實際沒有寫進記憶體,而還是寫進暫存器,或者比記憶體更高階的快取中?不知道正確與否。
unix系統萬物皆為檔案,在程式中每開啟乙個檔案,都會返回乙個檔案描述符(int fd,實際非負整數),供核心引用。而相對於標準i/o,就是開啟檔案指標(file* fp)。
unix系統shell把檔案描述符0、1、2分配給標準輸入、標準輸出、標準錯誤,並用符號常量stdin_filino、stdout_fileno、stderr_fileno來表示。
(1)open和openat函式開啟或建立檔案,返回最小的未使用的檔案描述符,若錯誤則返回-1。
(2)creat函式以只寫建立檔案。
(3)close函式關閉檔案,不過當乙個程序終止,核心會自動關閉。
(4)lseek設定當前檔案偏移量,可以理解開啟檔案後,你的游標在哪。測試lseek是否出錯,不要檢測其是否<0,而要檢測其返回值是否等於-1。
(5)read從當前檔案偏移量處開始讀檔案,並將讀取的檔案放在buf中。
(6)write和read類似,只不過是寫進buf中。
unix可以在不同程序間共享開啟檔案,也就是不同程序可以同時開啟同乙個檔案。
i/o資料機構:
(1)每個程序都有乙個程序表,其裡面的記錄項有乙個一位fd標誌(檔案描述符標誌)和乙個指向檔案表項的指標。
(2)核心為所有開啟檔案維持乙個檔案表,其裡面的檔案項如圖所示。
(3)每個開啟的檔案都有都有乙個v節點結構,包括v節點資訊,也有指向i節點的指標。
注意點:
(1)多個程序開啟同乙個檔案,每個程序都會獲得各自的檔案表,使每個程序都有自己的當前檔案偏移量。
(2)但是對於開啟的檔案永遠只有乙個v節點表項。
if
(lseek
(fd, ol,2)
<0)
perror
("lseek error");
if(write
(fd, buf,
100)
!=100
)perror
("write error"
);
這個對於只有乙個程序時,是完全正確且沒有錯誤的。可是一旦有多程序,就會出現問題。
讓我們來假設有兩個程序a和b,分別對同乙個檔案進行追加寫。其可能的時間線是這樣的:
(1)在程序a,lseek定位到檔案尾(假設為1500)。
(2)此時核心進行程序切換,切換到b程序。程序b執行完全部過程,為檔案寫入了100位元組,此時檔案尾為1600。
(3)核心進行程序切換,程序a繼續執行,因為不同程序開啟同一檔案都有各自的檔案表,而之前a程序lseek將當前檔案偏移量設定為1500,write函式理應也是從1500處寫起,導致程序b寫進的資料被覆蓋。
所以這裡提出原子操作的定義:原子操作指的是多步組成的乙個操作。
lseek和write可以合成乙個原子操作pwrite,先執行lseek,再執行write。要麼執行完所有步驟,要麼不執行。
(1)pread和pwrite,原子操作。
(2)dup和dup2複製現有的檔案描述符到乙個新的檔案描述符。
注意:每個檔案描述符都有它自己一套的檔案描述符標誌。
(3)fsync、fdatasync、sync函式,將核心的緩衝區檔案寫進磁碟,保證磁碟上的檔案系統和緩衝區中的內容一致。
(4)fcntl函式可以改變已經開啟檔案的屬性
APUE學習(一)基礎知識
段一 include apue.h include intmain int argc,char argv make後在.lib生成libapue.a,然後 gcc ls1.c l lib lapue i include 連線庫和標頭檔案,可以模擬ls命令,man 1 ls 檢視命令都是man 1ex...
python 學習日記(一)
這兩天看完了python速成教程,從c 轉到python確實有點不是很適應。主要是兩種語言差別還是挺大的,下面我就先說說,我在轉換過程中出現的一些問題。1 python 的語言風格是指令碼式的,語言側重於解決問題,而不是語言本身,所以可以發現,對於變數 python裡都是物件 的使用上來看,pyth...
Linux C 學習日記 一
這個學期學了tcp ip socket 程式設計。老師順便講了下linux c的相關知識。所以在這把自己學到的東西記下來。下面所說的是關於檔案讀寫的。1 用linux c的標準庫函式實現檔案的複製。先貼上 吧。稍後再做分析。庫函式呼叫 include int main fclose f1 fclos...