APUE 學習記錄 20200628

3.7 函數read

調用read函數從打開文件中讀數據。shell

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t nbytes); // 返回值:讀到的字節數,若已到文件尾,返回0;若出錯,返回-1

如read成功,則返回讀到的字節數。如已到達文件的尾端,則返回0.
有多種狀況可以使實際讀到的字節數少於要求讀的字節數:網絡

  • 讀普通文件時,在讀要求字節數以前已到達了文件尾端。
  • 當從終端設備讀時,一般一次最多讀一行。
  • 當從網絡讀時,網絡中的緩衝機制可能形成但繪製小於所要求讀的字節數。
  • 當從管道或FIFO讀時,如若管道包含的字節少於所需的數量,那麼read將只返回實際可用的字節數。
  • 當從某些面向記錄的設備(如磁帶)讀時,一次最多返回一個記錄。
  • 當一信號形成中斷,而已經讀了部分數據量時。

讀操做從文件的當前偏移量處開始,在成功返回以前,該偏移量將增長實際讀到的字節數。函數

POSIX.1從幾個方面對read函數的原型作了更改。經典的原型定義是:性能

int read(int fd, char *buf, unsigned nbytes);
  • 首先,爲了與ISO C一致,第二個參數由char *改成void *。在ISO C中,類型void *用於即是通用指針。
  • 其次,返回值必須是一個帶符號整型(ssize_t),以保證可以返回正整數字節數、0或-1。
  • 最後,第三個參數在歷史上是一個無符號整型,這容許一個16位的實現一次讀或寫的數據能夠多達65534個字節。

3.8 函數write

調用write函數向打開文件中寫數據。spa

#include <unistd.h>
ssize_t write(int fd, void * buf, size_t nbytes); // 返回值:若成功,返回已寫的字節數;若出錯,返回-1

其返回值一般與參數nbytes值相同,不然表示出錯。write出錯的一個常見緣由是磁盤已寫滿,或者超過了一個給定進程的文件長度限制。指針

對於普通文件,寫操做從文件的當前偏移量處開始。若是在打開文件時,制定了O_APPEND選項,則在每次寫操做以前,將文件偏移量設置在文件的當前結尾處。在一次成功寫以後,該文件偏移量增長實際寫的字節數。code

3.9 I/O的效率

Page 58 示例:只使用read和write函數複製一個文件。進程

#include "apue.h"

#define BUFFSIZE 4096

int main(void)
{
    int n;
    char buf[BUFFSIZE];

    while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
        if(write(STDOUT_FILENO, buf, n) != n)
            err_sys("write error");

    if(n < 0)
        err_sys("read error");

    exit(0);
}

關於該程序應注意如下幾點:原型

  • 它從編撰輸入讀,寫至標準輸出,這就假定在執行本程序以前,這些標準輸入、輸出已由shell安排好。
  • 考慮到進程終止時,UNIX系統內核會關閉進程的全部打開的文件描述符,因此此程序並不關閉輸入和輸出文件。
  • 對UNIX系統而言,文本文件和二進制代碼文件並沒有區別,因此本程序對這兩種文件都有效。

咱們尚未回答的一個問題是如何選取BUFFSIZE值。使用本程序在ext4文件系統上(磁盤塊長度爲4096字節),讀516581760字節的結果以下:
image.pngit

CPU時間最小值出如今4096及之後的位置,繼續增長緩衝區長度對此時間機會沒有影響。大多數文件系統爲改善性能都採用某種預讀技術,當檢測到正進行順序讀取時,系統就試圖讀入比應用所要求的更多數據,並假象應用很快就會讀這些數據。

相關文章
相關標籤/搜索