文件 I/O操作open、lseek、read、write、close詳解

一,文件描述符、套接字和管道

        對於內核而言,所有打開的打開的文件都通過文件描述符引用。文件描述符是一個非負整數。

        內核爲每個進程維護一個結構體struct task_struct,可稱爲進程控制塊(PCB: Process Control Block)或進程描述符,含有一個稱爲打開文件描述符表的子結構體。普通的文件、套接字和管道都被放入其中,這說明這三者都被抽象爲文件,共同佔用進程佔用的打開文件描述符。

        其中UNIX系統shell使用:

        文件描述符0與進程的標準輸入相關聯;

        文件描述符1標準輸出相關聯;

        文件描述符2標準出錯輸出相關聯。


二,文件I/O函數

    1,open 函數可以打開或創建一個文件。

#include <fcntl.h>

int open(const char *pathname, int oflag, ... /* mode_t mode */ );

返回值:成功則返回文件描述符,出錯則返回-1。

參數:

    pathname:是要打開或創建文件的名字。

    oflag:說明此函數的多個選項。可將它的選項進行“或”運算構成oflag。

            O_RDONLY            只讀打開。

            O_WRONLY            只寫打開。

            O_RDWR                讀、寫打開。

            這三個選項只能制定且必須一個。下列常量可選:

            O_APPEND            每次都從文件尾端寫。

            O_CREAT               若文件不存在,則創建它。使用次選項必須帶第三個參數。

            O_EXECL                如果指定了O_EXECL,而文件存在,則會出錯。可以用它測試一個文件是否存在,如果不存在,則創建它。

            O_TRUNC                如果此文件存在,而且爲只寫或只讀打開,則將其長度截短爲0。

    2,create函數創建一個文件

#include <fcntl.h>

int create(const char *pathname, mode_t mode);

    返回值:成功則返回打開的文件描述符,出錯則返回-1。

    由於它只能以只寫的方式打開所創建的文件,所以等效於:

open(pathname, 0_WRONLY | O_CREAT | O_TRUNC, mode);

    3,close函數關閉一個打開的文件

#include <unistd.h>

int close(int filedes)

    返回值:成功則返回打開的文件描述符,出錯則返回-1。

    如果一個進程沒有調用close顯示關閉,當進程終止時,內核會自動關閉它所有打開的文件。

    4,lseek函數 爲一個打開的文件設置偏移量

     每個打開的文件都有一個與其關聯的“當前文件偏移量”,它是一個非負整數,用以度量從文件開始處計算的字節數。默認情況下,打開一個文件,該偏移量被設置爲0,除非制定了O_APPEND選項。

#include <unistd.h>

off_t lseek(int filedes, off_t offset, int whence)

    返回值:成功則返回新的文件的偏移量,出錯則返回-1。

    參數:設置的偏移量offset與whence有關。

        whence     文件的偏移量設置爲offset值
SEEK_SET文件開始處offset個字節必須爲正數
SEEK_CUR文件偏移量當前值加offset可正可負
SEEK_END文件長度加offset可正可負

    如何確定當前打開文件的偏移量:

int curpose;
curpose = lseek(filedes, 0, SEEK_CUR);

    也可以用來判斷所涉及的文件是否可以設置偏移量。因爲文件描述符引用的是一個管道、FIFO或網絡套接字,則lseek返回-1,並將error設置爲ESPIPE。

    注意:lseek(file, 163840, SEEK_SET);如果文件偏移量大於文件的當前長度,對該文件的下一次寫將加長該文件,並在文件中構成一個空洞,這些空洞不在磁盤上佔用存儲區,位於文件中但沒有寫過的字節都被讀爲0(即空洞都被讀爲0)。

    5,read函數 從打開的文件讀數據

#include <unistd.h>

ssize_t read(int filedes, void *buf, size_t nbytes);

    返回值:

  • 若成功返回讀到的字節數;
  • 若已到文件結尾返回0;
  • 若出錯返回-1。        

    實際讀到的字節數有可能少於要求讀的字節數 nbytes:

  • 讀取普通文件時,在讀到要求字節數時已到達文件末尾。例如,若在到達文件末尾之前還有30個字節,而要求讀100個字節,則read返回30,下一次再調用read時,它將返回0(文件尾端)。
  • 當從終端設備讀時,通常一次最多讀一行。
  • 當從網絡讀時,網絡中的緩衝機構可能造成返回值小於所要求讀的字節數。
  • 當從管道或FIFO讀時,如管道包含的字節少於所需的數量,那麼read將只返回實際可用的字節數。
  • 當某一信號造成中斷,而已經讀了部分數據量時。

    6,write函數 向打開的文件寫入數據

#include <unistd.h>

ssize_t write(int filedes, const void *buf, size_t nbytes);

    返回值:

  • 若成功返回已寫入的字節數;
  • 如出錯返回-1。

    返回值通常與參數nbytes的值相同,否則表示出錯(比如緩衝區已滿)。

               

       

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