UNIX系統 檔案操作介面
一、檔案描述符
對於核心而言所有開啟的檔案都是通過檔案描述符引用。檔案描述符是一個非負整數。當開啟一個現有檔案或者建立一個新檔案時,核心向程序返回一個檔案描述符。當讀或者寫一個檔案時使用open或creat返回檔案描述符標識該檔案,將作為引數傳遞給read或write
UNIX系統shell把檔案描述符0與程序的標準輸入關聯,檔案描述符1與標準輸出關聯,檔案描述符2與標準錯誤關聯。這是各種shell以及很多程式使用的慣例,與UNIX核心無關。
在符合POSIX.1的應用程式中。幻數0、1、2以及被標準化。但是建議使用符號常量:STDIN_FILENO、STDOUT_FILENO 、STDERR_FILENO以提高可讀性。這些常量定義在標頭檔案<unistd.h>中。
檔案描述符的變化範圍是0~OPEN_MAX-1。早期可以同時使用的檔案描述符是20個(既可以同時開啟20個檔案),現在多是64。可以使用函式sysconf來檢視OPEN_MAX的值。
long sysconf(int _SC_OPEN_MAX)
二、檔案操作
1、檔案建立與開啟
(1)open
1)函式原型
#include <fcntl.h>
int open(const char*path,int oflag,.../*mode_t mode*/);
2)引數說明
path是要開啟或建立檔案的名字。
最後一個引數寫為...表明餘下的引數的數量及型別是可變的。僅當建立新檔案時才使用最後這個引數mode.用於指定檔案的訪問許可權位。
oflag引數可以用來說明此函式的多個選項。用下列一個或多個常量進行“或”運算構成oflag引數
O_RDONLY 只讀模式
O_WRONLY 只寫模式
O_RDWR 讀寫模式
O_EXEC 只執行開啟
O_SEARCH 只搜尋開啟(應用與目錄)
開啟/建立檔案時,至少得使用上述五個常量中的一個。以下常量是選用的:
O_APPEND 每次寫操作都寫入檔案的末尾
O_CREAT 如果指定檔案不存在,則建立這個檔案。使用此選項時要同時說明open函式的第三個參mode,用mode指定該新檔案的許可權位。
O_EXCL 如果要建立的檔案已存在,則返回 -1,並且修改 errno 的值
O_TRUNC 如果檔案存在,並且以只寫/讀寫方式開啟,則清空檔案全部內容
O_NOCTTY 如果路徑名指向終端裝置,不要把這個裝置用作控制終端。
O_NONBLOCK 如果路徑名指向 FIFO/塊檔案/字元檔案,則把檔案的開啟和後繼 I/O設定為非阻塞模式(nonblocking mode)
以下三個常量同樣是選用的,它們用於同步輸入輸出
O_DSYNC 等待物理 I/O 結束後再 write。在不影響讀取新寫入的資料的前提下,不等待檔案屬性更新。
O_RSYNC read 等待所有寫入同一區域的寫操作完成後再進行
O_SYNC 等待物理 I/O 結束後再 write,包括更新檔案屬性的 I/O
3)返回值
open 函式返回的檔案描述符一定是最小的未用的描述符值。
(2)openat
int openat(int fd, const char* path,int oflag,.../*mode_t mode*/);
與open 不同的是openat函式可以使用相對路徑名開啟目錄中的檔案,而不再只打開當前工作目錄。
path引數是絕對路徑名時,fd引數被忽略,openat函式就相當於open函式;path引數是相對路徑名時,fd引數指出了相對路徑名在檔案系統中的開始地址。fd引數是通過開啟相對路徑名所在的目錄來獲取;若fd引數的值為AT_FDCWD則,路徑名會在當前工作目錄中獲取。
(3)creat
#include<fcntl.h>
int create(const char* path,mode_tmode);
等價於
open(path,O_WRONLY | O_CREAT | O_TRUNC, mode);
create 的不足之處是它一隻寫的方式開啟所建立的檔案。
2、檔案關閉
#include<unistd.h>
int close(int fd);
關閉一個檔案時還會釋放該程序加在該檔案上的所有記錄鎖。
當一個程序結束時,核心會自動關閉它所有開啟的檔案。
3、讀檔案
(1)read
1)函式原型
#include<unistd.h>
ssize_t read(int fd,void *buf,size_t nbytes)
2)返回值
read 成功時,返回讀到的位元組數。如已到達檔案的尾端,則返回0;若出錯,返回-1。
3)說明
多種情況會使實際讀到的位元組數少於要求讀的位元組數。例如:在讀到要求的位元組數之前已經到達了檔案的尾端;從終端裝置讀時,通常一次最多讀一會等
4、寫檔案
(1)write
#include <unistd.h>
ssize_t write(int fd,const void* buf,size_t nbytes);
write函式向開啟的檔案寫資料。若成功返回已寫的位元組數,若出錯返回-1.
5、其它
(1)使用int dup(int fd)或int dup2(int fd,int fd2)函式進行檔案描述符複製
(2) 使用int fsync(int fd)或void sync(void);將緩衝區資料寫至磁碟
(3)使用fcntl函式gaibian已經開啟的檔案屬性
(4)使用off_t lseek(int fd,off_t offset,int whence);函式顯示設定一個已經開啟檔案的偏移量
三、與標準C函式庫的區別
標準C庫是對系統檔案I/O介面的封裝。標準I/O庫處理了很多細節,如緩衝區分配、以優化的塊長度執行I/O等。
1、不帶緩衝
不帶緩衝指:每個read和write都呼叫核心中的一個系統呼叫
2、檔案描述符與流
對於核心所有的檔案操作都是圍繞檔案描述符來進行的;但是標準C I/O庫是圍繞流(FILE*)進行的。