APUE學習筆記 第三章 檔案I O

2021-08-19 04:45:44 字數 4901 閱讀 8321

apue學習筆記 第三章 檔案i/o

1、函式open和openat

呼叫open或openat函式可以開啟或建立乙個檔案

#includeint open(const char *path,into flag,…/*mode_t made*/);

int openat(int fd,const char* path,into flag,…/*mode_t mode*/);

兩個函式返回值:若成功,返回檔案描述符(一定是最小的未用描述符數值);若出錯,返回-1;

path引數是要開啟或建立檔案的名字;oflag引數可用來說明此函式的多個選項,用下列乙個或多個常量進行「或」運算構成oflag引數

o_rdonly 以唯讀方式開啟檔案

o_wronly 以只寫方式開啟檔案

o_rdwr 以可讀寫方式開啟檔案.

上述三種旗標是互斥的, 也就是不可同時使用, 但可與下列的旗標利用or(|)運算子組合.大多數實現將o_rdonly定義為0,o_wronly定義為1,o_rdwr定義為2;

o_exec 只執行開啟

o_search 只搜尋開啟

o_creat 若欲開啟的檔案不存在則自動建立該檔案.

o_excl 如果o_creat 也被設定, 此指令會去檢查檔案是否存在. 檔案若不存在則建立該檔案, 否則將導致開啟檔案錯誤.

此外, 若o_creat 與o_excl 同時設定, 並且欲開啟的檔案為符號連線, 則會開啟檔案失敗.

o_noctty 如果欲開啟的檔案為終端機裝置時, 則不會將該終端機當成程序控制終端機.

o_trunc 若檔案存在並且以可寫的方式開啟時, 此旗標會令檔案長度清為0, 而原來存於該檔案的資料也會消失.

o_nonblock 以不可阻斷的方式開啟檔案, 也就是無論有無資料讀取或等待, 都會立即返回程序之中.

o_ndelay 同o_nonblock.

o_sync 以同步的方式開啟檔案.

o_nofollow 如果引數pathname 所指的檔案為一符號連線, 則會令開啟檔案失敗.

o_directory 如果引數pathname 所指的檔案並非為一目錄, 則會令開啟檔案失敗。

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

a、path引數指定的是絕對路徑名,此情況下,fd引數被忽略,openat函式就相當於open函式;

b、path引數指定的是相對路徑名,fd引數指定了相對路徑名在檔案系統中的開始位址;

c、 path引數指定了相對路徑名,fd引數具有特殊值at_fdcwd。在此情況下,路徑名在當前工作目錄中獲取,openat函式在操作上與open函式類似。

示例:

open('test', o_rdonly);                     // 唯讀方式開啟

open('test', o_rdwr); // 讀寫的方式開啟

open('test', o_wronly | o_creat, 0666); // 建立檔案,只寫,許可權是 0666

open('test', o_wronly | o_trunc); // 只寫開啟,同時把檔案長度截斷成 0.

2、函式creat

呼叫creat函式建立乙個新檔案

#includeint creat(const char* path,mode_t mode);

返回值:若成功,返回為只寫開啟的檔案描述符;若出錯,返回-1.

此函式等效於open(path,o_wronly | o_creat |o_trunc,mode);

creat函式的不足之處是它以只寫方式開啟所建立的檔案。

示例:creat("foo",0666);

3、函式close

可呼叫close函式關閉乙個開啟的檔案

#includeint close(int fd);

返回值:若成功,返回0;若失敗,返回-1;

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

4、函式lseek

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

#includeoff_t lseek(int fd,off_t offset,int whence);

//返回值:若成功,返回新的檔案偏移量;若出錯,返回為-1;

對引數offest的解釋與引數whence的指有關

a、若whence是seek_set,則將該檔案的偏移量設定為距檔案開始處offset個位元組;

b、若whence是seek_cur,則將該檔案的偏移量設定為當前值加offset,offset可正可負;

c、 若whence是seek_end,則將該檔案的偏移量設定為檔案長度加offset,offset可正可負。(可能產生空洞)

如果檔案描述符指向的是乙個管道、fifo或網路套接字,則lseek返回-,並將errno設定為espipe。

示例:lseek(fd, 6, seek_set);

lseek(fd,0,seek_end);

5、函式read

呼叫read函式從開啟的檔案中讀資料。

#includessize_t read(int fd,void *buf,size_t nbytes);

//返回值:若成功,返回讀到的位元組數,若已到達檔案尾,返回0;若出錯,返回-1.

//示例:read(srcfd, buffer, buffersize);

6、函式write

呼叫write函式向開啟檔案寫資料。

#includessize_t write(int fd,const void* buf,size_t nbytes);

//返回值:若成功,返回已寫的位元組數;若出錯,返回-1.

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

示例:write(dstfd, buffer, len);

7、原子操作

原子操作指的是不可再分的指令操作,即在執行原子操作時不可能被打斷,要麼原子操作沒有執行,要麼已經執行完畢。

原子操作的實現必須需要硬體的支援,作業系統僅僅是在硬體指令的基礎之上進行一次封裝。對於沒有實現原子操作的硬體,則需要作業系統從軟體演算法層面進行支援。

8、函式pread和pwrite

#includessize_t pread(int fd,void *buf,size_t nbytes,off_t offset);

//返回值:讀到的位元組數,若已到檔案尾,返回0;若出錯,返回-1;

ssize_t pwrite(int fd,const void* buf,size_t nbytes,off_t offset);

//返回值:若成功,返回已寫的位元組數,若出錯,返回-1;

呼叫pread相當於呼叫lseek後呼叫read;呼叫pwrite相當於呼叫lseek後呼叫write。

9、函式dup和dup2

下面兩個函式都可以用來複製乙個現有的檔案描述符。

#includeint dup(int fd);

int dup2(int fd,int fd2); //用fd2指定新的檔案描述符

//兩函式的返回值:若成功,返回新的檔案描述符;若出錯,返回-1.

這些函式返回的新檔案描述符與引數fd共享同乙個檔案表項。

示例:newfd = dup(fd); 

10、函式sync、fsync和fdatesync

通常,當核心需要重用緩衝區來存放其他資料塊資料時,它會把所有延遲寫資料塊寫入磁碟。

#includeint fsync(int fd);

int fdatesync(int fd);

返回值:若成功,返回0;若出錯,返回-1;

void sync(void);

sync只將所有修改過的快緩衝區排入寫佇列,然後就返回,不等待實際寫磁碟操作結束;

fsync函式只對檔案描述符fd指定的乙個檔案起作用,並等待寫磁碟操作結束才返回;

fdatesync函式類似於fsync,但它只影響檔案的資料部分,除資料外,fsync還會同時更新檔案的屬性。

11、函式fcntl

函式fcntl可以改變已經開啟檔案的屬性。

#include#includeint fcntl(int fd, int cmd);  

int fcntl(int fd, int cmd, long arg);

int fcntl(int fd, int cmd ,struct flock* lock);

返回值:若成功,則依賴於cmd;若出錯,返回-1.

fantl函式有以下5種功能:

a、複製乙個已有的描述符(cmd=f_dupfd或f_dupfd_cloexec);

b、獲取/設定檔案描述符標誌(cmd=f_getfd或f_setfd);

c、 獲取/設定檔案狀態標識(cmd=f_getfl或f_setfl);

d、獲取/設定非同步i/o所有權(cmd=f_getown或f_setown);

e、獲取/設定記錄鎖(cmd=f_getlk、f_setlk或f_setlkw)。

apue學習筆記(第三章 檔案I O)

本章開始討論unix系統,先說明可用的檔案i o函式 開啟檔案 讀寫檔案等 unix系統中的大多數檔案i o只需用到5個函式 open read write lseek以及close open函式 返回乙個最小的未用描述符 include int open const char pathname,i...

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...

《APUE》第三章筆記(1)

以下內容是我看 apue 第二版第三章的筆記,有錯還希望指出來,謝謝。unbuffered i o,跟buffered i o相對,buffered i o就是 iso c標準下的標準輸入輸出函式,而unbuffered i o就是posix下的函式。檔案描述符,個人理解就相當於linux下的uid...