open/close
檔案描述符
一個程序啟動之後,預設打開三個檔案描述符:
#define STDIN_FILENO 0
#define STDOUT_FILENO 1
#define STDERR_FILENO 2
新打開檔案傳回檔案描述符表中未使用的最小檔案描述符, 調用open函數可以打開或建立一個檔案, 得到一個檔案描述符.
open函數
函數描述: 打開或者建立一個檔案
函數原型:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
函數參數:
pathname:參數是要打開或建立的檔案名,和fopen一樣, pathname既可以是相對路徑也可以是絕對路徑。
flags :參數有一系列常數值可供選擇, 可以同時選擇多個常數用按位或運算符連接配接起來, 是以這些常數的宏定義都以O_開頭,表示or。
**必選項:**以下三個常數中必須指定一個, 且僅允許指定一個。
O_RDONLY 隻讀打開
O_WRONLY 隻寫打開
O_RDWR 可讀可寫打開
以下可選項可以同時指定0個或多個, 和必選項按位或起來作為flags參數。可選項有很多, 這裡隻介紹幾個常用選項:
O_APPEND 表示追加。如果檔案已有内容, 這次打開檔案所寫的資料附加到檔案的末尾而不覆寫原來的内容。
O_CREAT 若此檔案不存在則建立它。使用此選項時需要提供第三個參數mode, 表示該檔案的通路權限。
檔案最終權限:mode & ~umask
O_EXCL 如果同時指定了O_CREAT,并且檔案已存在,則出錯傳回。
O_TRUNC 如果檔案已存在, 将其長度截斷為為0位元組。
O_NONBLOCK 對于裝置檔案, 以O_NONBLOCK方式打開可以做非阻塞I/O(NonblockI/O),非阻塞I/O。
函數傳回值:
成功: 傳回一個最小且未被占用的檔案描述符
失敗: 傳回-1, 并設定errno值.
close函數
函數描述: 關閉檔案
函數原型: `
函數參數: fd檔案描述符
函數傳回值:
成功傳回0
失敗傳回-1, 并設定errno值.
需要說明的是,當一個程序終止時, 核心對該程序所有尚未關閉的檔案描述符調用close關閉,是以即使使用者程式不調用close, 在終止時核心也會自動關閉它打開的所有檔案。但是對于一個長年累月運作的程式(比如網絡伺服器), 打開的檔案描述符一定要記得關閉, 否則随着打開的檔案越來越多, 會占用大量檔案描述符和系統資源。
read/write
read函數
函數描述: 從打開的裝置或檔案中讀取資料
函數原型:
*ssize_t read(int fd, void buf, size_t count);
函數參數:
fd: 檔案描述符
buf: 讀上來的資料儲存在緩沖區buf中
count: buf緩沖區存放的最大位元組數
函數傳回值:
>0:讀取到的位元組數
=0:檔案讀取完畢
-1: 出錯,并設定errno
write
函數描述: 向打開的裝置或檔案中寫資料
函數原型:
函數參數:
fd:檔案描述符
buf:緩沖區,要寫入檔案或裝置的資料
count:buf中資料的長度
函數傳回值:
成功:傳回寫入的位元組數
錯誤:傳回-1并設定errno
lseek
所有打開的檔案都有一個目前檔案偏移量(current file offset),以下簡稱為cfo. cfo通常是一個非負整數, 用于表明檔案開始處到檔案目前位置的位元組數. 讀寫操作通常開始于 cfo, 并且使 cfo 增大, 增量為讀寫的位元組數. 檔案被打開時, cfo 會被初始化為 0, 除非使用了 O_APPEND.
使用 lseek 函數可以改變檔案的 cfo.
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
函數描述: 移動檔案指針
函數原型:
函數參數:
fd:檔案描述符
參數 offset 的含義取決于參數 whence:
如果 whence 是 SEEK_SET,檔案偏移量将設定為 offset。
如果 whence 是 SEEK_CUR,檔案偏移量将被設定為 cfo 加上 offset,offset 可以為正也可以為負。
如果 whence 是 SEEK_END,檔案偏移量将被設定為檔案長度加上 offset,offset 可以為正也可以為負。
函數傳回值: 若lseek成功執行, 則傳回新的偏移量。
lseek函數常用操作
檔案指針移動到頭部
擷取檔案指針目前位置
擷取檔案長度
lseek實作檔案拓展
off_t currpos;
// 從檔案尾部開始向後拓展1000個位元組
// 額外執行一次寫操作,否則檔案無法完成拓展