-
對于內核而言,所有打開的文件都通過文件描述符引用,文件描述符是一個非負整數
文件描述符 標準 符號常量 文件描述符0 標準輸入 STDIN_FILENO 文件描述符1 標準輸出 STDOUT_FILENO 文件描述符2 標準錯誤 STDERR_FILENO -
函數open和openat---打開文件
int open(const char *path, int oflag, .../*mode_t mode*/) int openat(int fd,const char *path, int oflag, .../*mode_t mode*/) 兩函數的返回值:若成功,返回文件描述符,若出錯,返回-1
- path---要打開或創建文件的名字
- oflag---用來說明此函數的多個選項
- fd---把open和openat函數區分開,有下列三種情況
- path參數指定的是絕對路徑名,在這種情況下,fd參數被忽略,openat函數相當于open
- path參數指定的是相對路徑名,fd參數指出了相對路徑名在文件系統中的開始地址。fd參數是通過打開相對路徑名所在的目錄來獲取
- path參數指定的是相對路徑名,fd參數具有特殊值AT_FDCWD。在這種情況下,路徑名在當前工作目錄中獲取,openat函數在操作上和open函數相似
-
函數creat---創建文件
int creat(const char *path, mode_t mode) 返回值:若成功,返回為只寫打開的文件描述符。若出錯,返回-1
-
函數close---關閉文件
int close(int fd) 返回值:若成功,返回0。若出錯,返回-1
- 關閉一個文件時會釋放該進程加在改文件上的所有記錄鎖
-
函數lseek---顯示地為一個打開文件設置偏移量
off_t lseek(int fd, off_t offset, int whence) 返回值:若成功,返回新的文件偏移量。若出錯,返回-1
對參數offset的解釋和參數whence的值有關
- 若whence = SEEK_SET,則將該文件的偏移量設置為距文件開始處offset個字節
- 若whence = SEEK_CUR,則將該文件的偏移量設置為其當前值加offset,offset可正可負
- 若whence = SEEK_END,則將該文件的偏移量設置為文件長度加offset,offset可正可負
-
函數read---讀數據
ssize_t read(int fd, void *buf,size_t nbytes) 返回值:讀到的字節數,若已到文件尾,返回0。若出錯,返回-1
- 有多種情況可使實際讀到的字節數少于要求讀的字節數
-
函數write---寫數據
ssize_t write(int fd, const void *buf,size_t nbytes) 返回值:若成功,返回已寫的字節數。若出錯,返回-1
單個進程打開文件時內核數據結構圖
image
- 兩個獨立進程各自打開了同一個文件,有如下關系圖
image
多個進程讀取同一文件都能正常工作。每個進程都有它自己的文件表項,其中也有它自己的當前文件偏移量。但是,當多個進程寫同一個文件時,則可能產生預想不到的結果
原子操作指的是由多步組成的一個操作,如果原子操作被執行,要么執行完所有步驟,要么一步也不執行,不可能執行所有步驟中的一個子集
-
函數dup和dup2---復制一個現有的文件描述符
int dup(int fd) int dup2(int fd,int fd2); 返回值:若成功,返回新的文件描述符。若出錯,返回-1
- fd---將要復制的文件描述符
- fd2---指定新描述符的值(將要返回的)
- dup返回的新文件描述符一定是當前可用文件描述符中的最小數值
- dup2是一個原子操作,
close(fd2); fcntl(fd,F_DUPFD,fd2);
-
函數fcntl---改變打開已經打開的文件的屬性
int fcntl(int fd, int cmd, .../* int arg */) 返回值:若成功,則依賴于cmd。若出錯,返回-1
- fcntl有以下5中功能
- 復制一個已有的描述符(cmd = F_DUPFD 或 F_DUPFD_CLOEXEC)
- 獲取/設置文件描述符標志(cmd = F_GETFD 或 F_SETFD)
- 獲取/設置文件狀態標志(cmd = F_GETFL 或 F_SETFL)
- 獲取/設置異步I/O所有權(cmd = F_GETOWN 或 F_SETOWN)
- 獲取/設置記錄鎖(cmd = F_GETLK、F_SETLK 或 F_SETLKW)
- 在修改文件描述符標志或文件狀態標志時必須謹慎,先要獲得現在的標志值,然后按照期望修改,最后設置新標志值。不能只執行F_SETFD或F_SETFL命令,這樣會關閉以前設置的標志位
- fcntl有以下5中功能