第三章 檔案I O

2021-10-03 10:55:28 字數 3331 閱讀 3182

1. 檔案描述符

- unix 系統 shell 把檔案描述符 0 與程序的標準輸入關聯,檔案描述符 1 與標準輸出關聯,檔案描述符 2 與標準錯誤關聯;

- 上述 0、1、2 使用時應該替換為符號常量 stdin_fileno、stdout_fileno 和 stderr_fileno;

- 檔案描述符的變化范文是 0 ~ open_max - 1;

2. open 和 openat

- 原型:

int open(const char *path, int oflag, …);

int openat(int fd, const char *path, int oflag, …);

- path 引數是要開啟或建立檔案的名字;

- oflag引數可用來說明此函式的多個選項(oflag引數之間用 「|」 連線);

- open 和 openat 返回的檔案描述符一定是最小的未用描述符數值;

- fd 引數:

1) path引數指定的是絕對路徑名,fd被忽略,此時倆原型一樣;

2) path引數指定的是相對路徑名,fd引數表示相對路徑名在檔案系統中的開始位址;

3) path引數指定的是相對路徑名,fd引數具有特殊值at fdcwd,此時,路徑名在當前工作目錄中獲取;

3. 函式creat

- 原型:

int creat(const char *path, mode_t mode);//成功返回檔案描述符,失敗返回-1

open(path, o_wronly | o_creat | o_trunc, mode);

4. 函式 close

- 原型:

int close (int fd);

- 當乙個程序終止時,核心自動關閉它所有的開啟檔案。

5. 函式 lseek

- 原型:

off_t lseek(int fd, off_t offset, int whence);//成功返回新的檔案偏移量,失敗返回-1;

- 功能:顯式地為乙個開啟檔案設定偏移量;

- 引數whence:

1) 若whence為seek_set,則偏移量為距檔案開始處offset個位元組;

2) 若whence為seek_cur,則偏移量為其當前值加offset,offset可正可負;

3) 若whence為seek_end,則偏移量為檔案長度加offset,offset可正可負;

- 確定開啟檔案的當前偏移量的方式(也可用來確定所涉及的檔案是否可以設定偏移量):

off_t currpos;

currpos = lseek(fd, 0, seek_cur);

- 通常情況下,對於普通檔案來講,偏移量必須是非負值。但由於有些檔案允許偏移量為負,所以在判斷偏移量是否設定成功時,我們需要判斷的是返回值是否等於-1,而非是否小於零。

- 空洞:當檔案的偏移量大於檔案的當前長度,下一次的寫操作將加長該檔案,並在檔案中構成乙個空洞。我的理解是「先占個地」,也就是用空洞來佔位置,保證下一次寫入是在我們預期的地方。另外,空洞檔案可以用來保證多執行緒的順利進行,因為這個「佔位置」的作用,使同乙個任務可以分段寫入。

6. 函式 read

- 原型:

ssize_t read ( int fd, void *buf, size_t bnytes);//返回值為讀到的位元組數,若到檔案尾,返回零,出錯返回-1;

7. 函式 write

- 原型:

ssize_t write ( int fd, const void *buf, size_t bnytes);//成功返回已寫位元組數,出錯返回-1

8. 核心用三種資料結構表示開啟檔案

1) 每個程序在程序表中有乙個記錄項,記錄項中包含一張開啟檔案描述符表;

2) 核心為所有開啟檔案維持一張檔案表;

3) 每個開啟檔案都有乙個v節點(v-node)結構,v 節點包含了檔案型別和對此檔案進行各種操作函式的指標。(linux中使用的是i節點,概念相同)

9. 原子操作

- 所謂原子操作,指的是乙個操作或者乙個操作集合,該操作要麼執行完,要麼不執行;

- 原子操作能夠有效避免很多操作間的衝突,比如對檔案的修改,如果兩個程序對乙個檔案同時進行操作,或者操作時間差不太多,很有可能出現前乙個程序的操作被強行覆蓋掉,或者偏移量已經被另乙個程序修改之類的錯誤。

- 函式 pread = lseek + read;但 pread 就是原子操作,一旦呼叫,無法中斷,並且 pread 不更新當前檔案偏移量。( pwrite 同理)

10. 函式 dup 和 dup2

- 原型:

int dup ( int fd);

int dup2 ( int fd, int fd2 );

- 作用:複製乙個現有的檔案描述符;

- dup 返回的是當前可用檔案描述符中的最小數值,而 dup2 可以給定新的描述符的值;

- 如果 fd2 已經被占用,則先關閉 fd2(dup2是原子操作,而且可以關別的檔案,感覺有點強勢);

11. 延遲寫

- 延遲寫,就是建立乙個緩衝區,把寫入資料儲存到一定程度,一次性寫入,避免過於頻繁的呼叫i/o(類似於printf的輸出緩衝區);

- sync 函式:將所有修改過的塊緩衝區排入寫佇列,然後返回;

- fsync 函式:只對fd指定的乙個檔案起作用,並且等到磁碟操作結束才返回;

- fdatasync 函式:同 fsync ,但只影響資料,不同步更新檔案屬性。

12. 函式 fcntl

- 功能:

1) 複製乙個已有的描述符;

2) 獲取/設定檔案描述符標誌;

3) 獲取/設定檔案狀態標誌;

4) 獲取/設定非同步i/o所有權;

5) 獲取/設定記錄鎖;

- 注:修改檔案描述符標誌或檔案狀態標誌時,先要獲得現在的標誌值,然後修改,最後設定新的標誌值。否則會關閉以前設定的標誌位。

13. /dev/fd

- 開啟 /dev/fd/n 相當於複製描述符 n。

第三章 檔案I O

include int open const char pathname,int oflag,mode t mode 成功返回檔案描述符,出錯返回 1 oflag 可多選 o rdonly 唯讀 o wronly 只寫 o rdwr 讀 寫 mode o creat 檔案不存在則建立 o excl ...

第三章 檔案I O

include include off t lseek int fileds,off t offset,int whence 成功返回新檔案的位移量,失敗返回 1 返回值可能為負數,所有測試它的返回值時應該確定是否為 1而不是是否為負數。stdin 屬於標準庫處理的輸入流,其宣告為 file 型的,...

APUE 第三章 檔案I O

linux對檔案操作有open read write close lseek,這些api都是不帶緩衝的函式,相對於c庫,這些可移植的api內部實現是有緩衝區的。int open char pathname,int flag,int read int fd,void buf,size t size i...