【APUE】文件I/O

1 文件描述符
    所有打開的文件都通過文件描述符引用,文件描述符是一個非負整數,本質是一個數組下標。
    當打開或創建一個文件的時候,內核向進程返回一個文件描述符。
    open,creat返回文件描述符來標識該文件,將其作爲參數傳遞給write和read。
    UNIX系統shell使用文件描述符0與進程的標準輸入相關聯,1和標準輸出相關聯,2和標準錯誤輸出相關聯。:

2 open函數
    打開一個文件

  1. #include <fcntl.h>
  2.         int open(const char * pathname, int oflag, ...);
  3.         //若成功返回文件描述符,不成功返回-1
        pathname是打開或創建文件的名字。
        oflag說明次函數的多個選項:
                O_RDONLY        只讀打開        0
                O_WRONLY        只寫打開        1
                O_RDWR          讀、寫打開      2
        以上這三個參數必須且只能定義一個,下列常量是可選的
                O_APPEND        每次寫入時追加到文件尾部
                O_CREAT         如果文件不存在,則創建。使用第三個參數來限制創建文件的權限。
                O_EXCL          如果指定了O_CREAT,則如果存在該文件,則會出錯。
                O_TRUNC         如果只讀或只寫打開的文件存在,將其長度截短爲0
                O_NOCTTY        如果pathname指定的是終端設備,則不將該設備分配作爲此進程的控制終端。
                O_NONBLOCK      如果pathname指定的是一個FIFO,一個塊特殊文件或一個字符特殊文件,則此選項爲文本的本次打開操作和後續的I/O操作設置非阻塞模式。
        以下參數是Single UNIX Specification
                O_DSYNC         使每次write操作等待物理I/O完成,如果寫操作不影響讀取剛寫入的數據,則不等待文件屬性被更新
                O_RSYNC         使以文件描述符爲參數的read等待,直到任何對文件同一部分進行的未決寫操作都完成。
                O_SYNC          使每次write操作等待物理I/O完成。

3 creat函數
    創建一個文件
  

  1. #include <fnctl.h>
  2.     int creat(const char * pathname, mode_t mode);
  3.     //若成功則返回一個以只寫打開的文件描述符,失敗返回-1
    詞函數等同於
            open(pathname, O_RDONLY | O_TRUNC | O_CREAT, mode);
    這個函數的缺點是返回一個以只寫打開的文件描述符,建議使用open函數來創建文件:
            open(pathname, O_RDWR | O_CREAT | O_TRUNC, mode);

4 close函數

    關閉一個打開的文件

  1. #include <unistd.h>
  2.     int close(int filedes);
  3.     //若成功返回0,錯誤返回-1
    關閉一個文件的同時關閉在該進程中爲文件加上的所有記錄鎖。
    *編程原則:誰打開誰關閉,誰申請誰釋放

5 lseek函數
    每打開一個文件的時候,都有一個與其相關的“當前文件偏移量”,用以度量從文件開始處計算的文件字節數。
    按照系統默認情況,當文件打開時,除非指定O_APPEND選項,文件偏移量從0開始。
    可以調用lseek來顯示的爲打開文件設置其偏移量。
  

  1. #include <unistd.h>
  2.     off_t lseek(int filedes, off_t offset, int whence);
  3.     //若成功返回文件的偏移量,失敗返回-1
    以下是whence屬性
            SEEK_SET        將文件偏移量設置爲距從文件開始處offset個字節
            SEEK_CUR        將文件偏移量設置爲從當前處到offset個字節,offset可以爲正/負
            SEEK_END        將文件偏移量設置爲文件長度加offset
    可以用下面的方式打開文件的偏移量

  1.             off_t currpos;
  2.             currpos = lseek(fd, 0, SEEK_CUR);
6 read函數
    從打開的文件讀取數據

  1. #include <unistd.h>
  2.     ssize_t read(int filedes, void * buf, size_t nbytes);
  3.     //若成功返回讀到的字節數,若以到達文件結尾返回0,若出錯返回-1
    ssize_t    帶符號的整數
    size_t    不帶符號的整數
    以下情況讀到的字節數少於要求的字節數
        1.在讀到要求字節數之前已經讀到文件結尾
        2.當從終端設備文件讀時
        3.從網絡讀時
        4.從管道或者FIFO讀時
        5.從某些面向記錄的設備讀時(磁帶)
        6.信號影響
    讀操作從文件的當前偏移量開始,讀取完畢該偏移量加上讀取的實際字節數

7 write函數
    向打開的文件中寫入數據

  1. #include <unistd.h>
  2.     ssize_t write(int filedes, const void * buf, size_t nbytes);
  3.     //若成功返回寫入的字節數,若失敗返回-1
    對於普通文件,write函數從文件的偏移量開始寫,如果指定了O_APPEND選項,就從文件的結尾處開始寫,在一次成功的寫操作之後,該文件的偏移量加上實際寫入的字節數

8 文件共享
    內核使用三種數據結構來表示打開的文件,它們之間的關係決定了在文件共享方面一個進程對另一個進程可能產生的影響。
    1.每個進程在進程表中都有一個記錄項,記錄項中包含一張打開文件描述符表,可將其視爲一個矢量,每一個文件描述符佔用一項,與每個文件描述符相關聯的是:
        a.文件描述符標誌
        b.指向一個文件表項的指針
    2.內核爲每個打開文件維持一個文件表,每個文件表含:
        a.文件狀態標誌
        b.當前文件偏移量
        c.指向該文件v節點表項的指針
    3.每打開一個文件都有一個v節點結構。包含了文件類型和對此文件進行各種操作的函數的指針。

    如果有兩個獨立的進程各自打開了同一個文件,打開文件的每一個進程都將得到一個文件表項,但是對於一個給定的文件只有一個v節點表項。
    這種安排使得每個進程都有它自己的對該文件的當前偏移量。
    但是對於多個進程對同一文件進行寫操作的時候就會產生不可預期的錯誤,所以要介紹原子操作。

9 原子操作
    爲了避免多進程操作同一文件會產生覆蓋的影響,有如下函數,該函數首先操作lseek,然後在進行讀寫操作

  1. #include <unistd.h>
  2.     ssize_t pread(int filedes, void * buf, size_t nbytes, off_t offset);
  3.     ssize_t pwrite(int filedes, const void * buf, size_t nbytes, off_t offset);
  4.     //其返回值和read,write類似
10 dup和dup2
    複製一個現存的文件描述符
    #include <unistd.h>
    int dup(int filedes);
    int dup(int filedes, int filedes2);
    //若正確,返回新的文件描述符,錯誤返回-1
    由dup返回的文件描述符一定是當前可用的最小的文件描述讀
    dup2函數則用filedes2來指定新文件描述符,如果filedes2已經存在,則先將其關閉。若filedes2等於filedes則返回filedes2,而不關閉

11 sync, fsync, fdatasync函數
    保證了磁盤上實際文件系統與緩衝區高速緩存中內容的一致性
  

  1. #include <unistd.h>
  2.     int fsync(int filedes);
  3.     int fdatasync(int filedes);
  4.     //若成功返回0,失敗返回-1
  5.     void sync(void);
    sync將所有修改過的塊緩衝區排入寫隊列,然後就返回,不等待實際寫磁盤操作結束。
    通常系統的守護進程update會定期調用sync,命令sync也是調用sync函數
    fsync對文件描述符filedes指定的單一文件起作用,並且等待實際寫磁盤操作結束。同時也會同步更新文件的屬性。
    fdtatsync和fsync類似,不過它值針對與數據部分。

12 fcntl函數
    可以改變以打開文件的屬性
   

  1. #include <fcntl.h>
  2.     int fcntl(int filedes, int cmd, ...);
  3.     //若成功則返回值依賴於cmd,失敗返回-1
    fcntl的五種功能cmd
    1.F_DUPFD            複製一個現有的文件描述符,與dup,dup2函數類似,返回一個文件描述符
    2.F_GETFD或F_SETFD        獲得/設置文件描述符標記,返回文件描述符標記
    3.F_GETFL或F_SETFL        獲得/設置文件狀態標誌,返回文件狀態標誌
        O_RDONLY    只讀打開
        O_WRONLY    只寫打開
        O_RDWR        讀寫打開
        O_APPEND    追加
        O_NONBLOCK    非阻塞模式
        O_SYNC        等待寫完成(數據和屬性)
        O_DSYNC        等待寫完成(數據)
        O_RSYNC        同步讀寫
        O_FSYNC        等待寫完成
        O_ASYNC        異步I/O

        前三個訪問標誌是互斥的,因此首先必須使用屏蔽字O_ACCMODE取得訪問模式位,在比較

    4.F_GETOWN或F_SETOWN        獲得/設置異步I/O所有權,返回一個正的進程ID或一個負的進程組ID
    5.F_GETLF、F_SETLK或F_SETLKW    獲得/設置記錄鎖

13 ioctl函數

    I/O操作的雜物箱
 

  1. #include <unistd.h> // System V
  2.     #include <sys/ioctl.h> // BSD and linux
  3.     #include <stropts.h> // XSI STREAMS
  4.     int ioctl(int filedes, int request, ...);
  5.     //若出錯返回-1,成功返回其他值


    在此原型中,我們表示的只是ioctl函數本身所要求的頭文件。通常還需要另外的設備專用頭文件<termios.h>

14 /dev/fd

    在較新的系統都提供名爲/dev/fd的目錄。打開/dev/fd/n等效於複製描述符n

閱讀(241) | 評論(4) | 轉發(0) |
給主人留下些什麼吧!~~
16_avatar_small.jpg

lixiang22022012-05-19 21:11:24

星期五啦: 什麼叫前三個訪問標誌是互斥的。。。.....
就是說 O_RDONLY  O_WRONLY   O_RDWR   這三個選項在一個文件中只能有一個值
00_avatar_small.jpg

星期五啦2012-05-17 21:04:52

什麼叫前三個訪問標誌是互斥的。。。

12_avatar_small.jpg

小蝌蚪1232012-05-16 21:13:05

寫的很好啊,淺顯易懂~博主辛苦啦~5.gif

91_avatar_small.jpg

夏冰軟件2012-05-16 16:46:06

寫的不錯,支持一下

評論熱議
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章