天天看點

APUE程式設計:28---進階I/O之(自定義讀寫函數:readn()、writen())

  • 這兩個函數是自己實作的,不是系統自帶的

一、引入

管道,FIFO以及某些裝置(特别是終端和網絡)具有以下兩種性質:

  • 一次read操作所傳回的資料可能少于所要求的資料,即使還沒達到檔案尾端。這不是 一個錯誤,應當繼續讀該裝置
  • 一次write操作的傳回值也可能少于指定輸出的位元組數。這可能是由若幹因素造成的, 例如,核心輸出緩沖區變滿。這也不是錯誤,應當繼續寫餘下的資料至該裝置。(通常, 隻有對非阻塞描述符,或捕捉到一個信号時,才發生這種write傳回)

在讀、寫磁盤檔案時沒有這兩種性質,除非檔案系統用完了空間,或者接近了配額限制,不能将要求寫的資料全部寫出

二、函數引入

APUE程式設計:28---進階I/O之(自定義讀寫函數:readn()、writen())
#include "apue.h"
ssize_t readn(int fd, void *buf, size_t nbytes);
ssize_t writen(int fd, void *buf, size_t nbytes);           
傳回值
  • 兩個函數傳回:已讀、寫位元組數,若出錯則為-1

三、函數的實作

#include<unistd.h>
ssize_t readn(int fd, void *ptr, size_t n)
{
    size_t nleft;
    ssize_t nread;

    nleft = n;
    while (nleft > 0) {
        if ((nread = read(fd, ptr, nleft)) < 0) {
            if (nleft == n)
                return(-1); /* error, return -1 */
            else
                break; /* error, return amount read so far */
        } else if (nread == 0) {
            break; /* EOF */
        }
        nleft -= nread;
        ptr += nread;
    }

    return(n - nleft); /* return >= 0 */
}           
#include<unistd.h>
ssize_t writen(int fd, const void *ptr, size_t n)
{
    size_t nleft;
    ssize_t nwritten;

    nleft = n;
    while (nleft > 0) {
        if ((nwritten = write(fd, ptr, nleft)) < 0) {
            if (nleft == n)
                return(-1); /* error, return -1 */
            else
                break; /* error, return amount written so far */
        } else if (nwritten == 0) {
            break;
        }
        nleft -= nwritten;
        ptr += nwritten;
    }

    return(n - nleft); /* return >= 0 */
}