1 文件I/O
1.1 函數(shù)open和openat
#include <fcntl.h>
int open(const char *path, int oflag,.../* mode_t mode */);
int openat(int fd,const char *path, int oflag,.../* mode_t mode*/);
//成功返回文件描述符衡怀,出錯返回-1
fd
參數(shù)把open和openat區(qū)分開- 1
path
參數(shù)指定的是絕對路徑名炒事,fd
參數(shù)被忽略专缠,兩函數(shù)沒有區(qū)別 - 2
path
參數(shù)指定的是相對路徑名,fd
參數(shù)指出了相對路徑名在文件系統(tǒng)中的開始地址。fd
是通過打開相對路徑名所在的目錄來獲取的 - 2
path
參數(shù)指定的是相對路徑名,fd
參數(shù)具有特殊值A(chǔ)T_FDCWD囤官,在這種情況下路徑名在當(dāng)前工作目錄中獲取
- 1
oflag
選項可用選項
宏 | 作用 | 備注 |
---|---|---|
O_RDONLY | 只讀打開 | |
O_WRONLY | 只寫打開 | |
O_RDWR | 讀寫打開 | 大多數(shù)實現(xiàn)將前三種定義成0,1蛤虐,2 |
O_EXEC | 只執(zhí)行打開 | |
O_APPEND | 追加模式 | 在每次寫入操作執(zhí)行之前党饮,自動將文件指針定位到文件末尾 |
O_CLOEXEC | 把FD_CLOEXEC常量設(shè)置為文件描述符標志 | |
O_CREAT | 若文件不存在則創(chuàng)建 | 需要給定第三個參數(shù),設(shè)置文件權(quán)限驳庭,最終權(quán)限受umask影響 |
O_DIRECTORY | 如果path不是目錄則出錯 | |
O_EXCL | 如果同時指定了O_CREAT刑顺,而文件已存在,則出錯 | |
O_NOCTTY | 如果path引用的是終端設(shè)備饲常,則不將該終端分配作為此進程的控制終端 | |
O_NOFOLLOW | 如果path是一個符號鏈接蹲堂,則出錯 | |
O_NONBLOCK | 如果path引用的是個FIFO,一個塊或字符文件特殊文件不皆,設(shè)置I/O操作為非阻塞 | |
O_SYNC | 使每次write等待物理I/O操作完成贯城,包括write操作引起的文件屬性更新所需的I/O | |
O_TRUNC | 如果此文件存在熊楼,且以寫屬性打開霹娄,將其長度截斷為0 | 對FIFO和終端文件不管用 |
O_TTY_INIT | d打開一個未打開的終端設(shè)備,設(shè)置非標準termios參數(shù)鲫骗,使其符合singel unix specification | |
1.2 函數(shù)creat
#include <fcntl.h>
int creat(const char *path, mode_t mode);
//成功返回只寫打開的文件描述符犬耻,出錯返回-1
//等效于open(path, O_WRONLY|O_CREAT|O_TRUNC, mode);
//不怎么用了,用open都可以實現(xiàn)执泰,且更靈活
1.3 函數(shù)lseek
- 每打開一個文件都有一個與其關(guān)聯(lián)的“當(dāng)前文件偏移量”(current file offset)
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
//成功返回新的文件偏移量枕磁,出錯返回-1
- 對管道,F(xiàn)IFO或網(wǎng)絡(luò)套接字使用术吝,返回-1计济,設(shè)置
errno
為ESPIPE
-
whence
參數(shù)取值 /wens/ 根源 - SEEK_SET ,將該文件偏移量設(shè)置為距文件開始處
offset
個字節(jié) - SEEK_CUR 排苍,將該文件偏移量設(shè)置為當(dāng)前值+
offset
沦寂,offset
可正可負 - SEEK_END ,將該文件偏移量設(shè)置為文件長度+
offset
淘衙,offset
可正可負
- SEEK_SET ,將該文件偏移量設(shè)置為距文件開始處
1.4 函數(shù)read
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t nbytes);
//返回實際讀到的字節(jié)數(shù)传藏,出錯返回-1
當(dāng)文件指針已位于文件結(jié)尾,返回0
返回-1時會設(shè)置errno
錯誤值 | 含義 |
---|---|
EAGAIN | 使用O_NONBLOCK標志 指定了非阻塞輸入輸出,但當(dāng)前沒有數(shù)據(jù)可讀毯侦。 |
EBADF | fd不是一個合法的文件描述符哭靖,或者不是為了讀操作而打開。 |
EINTR | 在讀取到數(shù)據(jù)以前調(diào)用被信號中斷侈离。 |
EINVAL | fd所指向的對象不合適讀试幽,或者是文件打開時指定了O_DIRECT標志。 |
EISDIR | fd指向一個目錄卦碾。 |
1.5 函數(shù)write
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t nbytes);
//返回寫入字節(jié)數(shù)抡草,出錯返回-1
- 錯誤值
錯誤值 | 含義 |
---|---|
EBADF | fd不是一個合法的文件描述符,或者不是為寫 操作而打開蔗坯。 |
EINTR | 系統(tǒng)調(diào)用在寫入任何數(shù)據(jù)之前調(diào)用被信號所中斷康震。 |
EINVAL | fd所有指向的對象不合適寫,或者是文件打開時指定了O_DIRECT標志宾濒。 |
ENOSPC | fd指向的文件所在的設(shè)備無可用空間腿短。 |
EPIPE | fd連接到一個管道,或者套接字的讀方向一端已經(jīng)關(guān)閉绘梦。 |
1.6 函數(shù)dup和dup2
- 兩函數(shù)都復(fù)制一個現(xiàn)有的文件描述符
#include <unistd.h>
int dup(int fd);
int dup2(int fd, ing fd2);
//成功返回新的文件描述符橘忱,出錯返回-1
- dup返回到新描述符一定是當(dāng)前可用的描述符中最小值
- dup2可以用fd2指定新描述符的值,如果fd2已打開卸奉,則先將其關(guān)閉钝诚。
- 若fd=fd2,返回fd2但不執(zhí)行關(guān)閉動作。否則fd2的FD_CLOEXEC標志就被清除榄棵,這樣fd2在進程調(diào)用exec時是打開狀態(tài)
1.7 函數(shù)close
- 可調(diào)用close函數(shù)關(guān)閉一個打開文件
#include <unistd.h>
int close(int fd); //成功返回0凝颇,否則返回-1
當(dāng)關(guān)閉一個文件還會釋放該進程加在該文件上的所有記錄鎖。
當(dāng)進程終止時疹鳄,內(nèi)核自動關(guān)閉它打開的所有文件拧略,很多程序利用這一點不顯式調(diào)用。
1.8 函數(shù) sync fsync fdatasync
- 將緩沖區(qū)內(nèi)容同步到磁盤
#include <unistd.h>
int fsync(int fd);
int fdatasync(int fd);
//成功返回0瘪弓,否則返回-1
void sync(void);
sync 只是將所有修改過的塊緩沖區(qū)寫入隊列垫蛆,就返回,不等待實際磁盤操作
fsync只對文件描述符指定的一個文件起作用腺怯,并等待磁盤操作結(jié)束才返回
fdatasync類似發(fā)fsync袱饭,但它只影響文件的數(shù)據(jù)部分,fsync同時更新屬性部分
1.9 函數(shù) fcntl
- fcntl 函數(shù)可以改變已經(jīng)打開文件的屬性
#include <fcntl.h>
int fcntl(int fd, int cmd, .../*int arg*/);
//返回值:成功則依賴于cmd呛占,出錯返回-1
- cmd
參數(shù) | 功能 |
---|---|
F_DUPFD | 復(fù)制文件描述符fd虑乖,新文件描述符作為返回值,它是尚未打開的各描述符中大于等于第三個參數(shù)值中最小的值栓票。新描述符有他自己的一套標志决左,其中FD_CLOEXEC被清除愕够, |
F_DUPFD_CLOEXEC | 同上,但D_CLOEXEC被設(shè)置 |
F_GETFD | 對應(yīng)于fd的文件描述符標志作為函數(shù)返回值佛猛。 |
F_SETFD | 對于fd設(shè)置文件描述符標志惑芭,新標志按第三個參數(shù)傳遞(如FD_CLOSEXEC) |
F_GETFL | 對應(yīng)于fd的文件狀態(tài)標志作為函數(shù)返回值,open函數(shù)下面有列出 |
F_SETFL | 設(shè)置狀態(tài)標志继找,可更改的有:O_APPEND,O_NONBLOCK,O_SYNC等 |
F_GETOWN | 獲取當(dāng)前SIGIO和SIGURG信號(兩種異步io信號)的進程id或進程組id |
F_SETOWN | s設(shè)置接收當(dāng)前SIGIO和SIGURG信號的進程id或組id遂跟,正的arg指定進程id,負的arg指定組id |
1.10 函數(shù) ioctl
- 不能用其他函數(shù)表示的i/o操作通常都可以用這個
- 每個設(shè)備驅(qū)動文件可以定義他自己專用的一組ioctl命令婴渡,系統(tǒng)則為不同驅(qū)動提供通用ioctl命令
#include <sys/ioctl.h>
int ioctl(int fd, int request, ...); //出錯返回-1幻锁,成功返回其他值
1.11 /dev/fd
- 較新的系統(tǒng)都有名為
/dev/fd
的目錄,目錄下是名為0边臼,1哄尔,2的文件 - 打開
/dev/fd/n
等效于復(fù)制描述符n,如fd = open("/dev/fd/0",mode)
等效fd = dup(0)