1. 程式人生 > >UNIX系統 檔案操作介面

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*)進行的。