Unix中的文件IO函數主要包括如下幾個:open()、read()、write()、lseek()、close()等。這類I/O函數也被稱爲不帶緩衝的I/O,標準I/O是帶緩衝的I/O(固然,標準I/O也能夠設置爲不帶緩衝)。函數
對於內核而言,全部打開的文件都經過文件描述符引用,好比read、write等操做都是經過文件描述符來實現的。文件描述符其實就是一個非負整數。當打開或者建立一個文件時,內核會向進程傳遞一個非負整數做爲文件描述符,該文件描述符就能夠做爲參數傳遞給read、write等函數,進行文件操做。學習
UNIX系統中,一般是把0做爲標準輸入的描述符、1做爲標準輸出的描述符、2做爲標準錯誤的描述符。code
// <unistd.h> #define STDIN_FILENO 0 #define STDOUT_FILENO 1 #define STDERR_FILENO 2
#include <fcntl.h> int open(const char *path, int oflag, ...); int openat(int fd, const cahr *path, int oflag, ...);
使用open() 或者 openat() 函數打開或者建立文件。在函數open()中,path參數是文件的絕對路徑或相對於當前文件的相對路徑,oflag表示打開的方式。而在函數openat()中,path表示絕對路徑(此時fd被忽略)或者是相對於fd的相對路徑(fd 表示某已打開目錄的文件描述符),openat()函數能夠實現以相對路徑來打開某些不便直接用相對路徑表示的文件。進程
open和openat函數返回的文件描述符必定是最小的未使用描述符,好比一個應用程序能夠先關閉標準輸出(文件描述符是1),而後打開另外一文件,這樣該文件會返回1做爲其文件描述符。it
int fd1 = open("test/test.c", O_RDONLY); //只讀方式打開文件test.c,此處爲相對路徑。 int fd2 = open("test", O_RDONLY | O_DIRECTORY); //打開當前目錄下的文件夾test int fd3 = openat(fd2, "test.c", O_RDONLY); //打開相對於test文件夾下的test.c
文件打開標誌有五個必選標誌(必須指定一個且只能指定一個),與其餘可選標誌。io
// 如下五個必須選一個且只能選一個 O_RDONLY // 只讀打開 O_WRONLY // 只寫打開 O_RDWR // 讀寫打開 O_EXEC // 只執行打開 O_SEARCH // 只搜索打開(應用於目錄) // 如下爲可選標誌, O_APPEND // 每次寫都追加到文件的結尾,文件以該標誌打開時,若是使用lseek對文件重定位,如果讀操做,重定位能夠生效,如果寫操做,重定位不生效,依然寫在文件結尾。 O_CREAT // 如果文件愛你不存在則建立它,使用該標誌時須要同時說明open第三個參數mode,即建立文件的權限。 O_TRUNC // 若是此文件存在且以只讀或讀寫打開,則將文件長度截爲0. O_DIRECTORY // 打開目錄,若path不是目錄則出錯。
該函數只能以只寫方式打開,咱們能夠直接使用open來實現建立新的文件,因此該函數就不用了。test
#include <fcntl.h> int close(int fd);
關閉一個文件時,還會釋放加在該文件上的全部記錄鎖。搜索
當一個進程結束時,內核會自動關閉它全部的打開文件,不少程序都用了這一點而不顯示的調用close關閉打開文件。權限
每一個打開的文件都有一個與其相關的文件偏移量,表示從文件開始處到當前的字節數,一般是一個非負值。學習筆記
#include <unistd.h> off_t lseek(int fd, off_t offset, int whence); // whence 可能取值以下 // SEEK_SET, 將文件的偏移量設置爲距文件開始處offset個字節 // SEEK_CUR, 將文件的偏移量設置爲距當前位置offset個字節(offset可正可負) // SEEK_END, 將文件的偏移量設置爲距結尾處offset個字節(offset可正可負)
一般,讀寫操做都是從當前文件偏移量處開始,並使偏移量增長所讀寫的字節數。根據系統默認狀況,除非設置了O_APPEND,不然打開文件時,其偏移量被設置爲0。
lseek若成功,則返回新的文件偏移量。文件的偏移量能夠大於文件的長度,在這種狀況下,對文件的下一次寫操做將會增加改文件,並在文件中構成一個空洞。
文件空洞並不在磁盤佔用存儲區,讀出的數據爲0.