10.5.1 RIO 的无缓冲的输入输出函数

10.5.1 RIO 的无缓冲的输入输出函数

通过调用 rio_readnrio_writen 函数,应用程序可以在内存和文件之间直接传送数据。

#include "csapp.h"

ssize_t rio_readn(int fd, void *usrbuf, size_t n);
ssize_t rio_writen(int fd, void *usrbuf, size_t n);

返回: 若成功则为传送的字节数,若 EOF 则为 0(只对 rio_readn 而言),若出错则为 -1。

rio_readn 函数从描述符 fd 的当前文件位置最多传送 n 个字节到内存位置 usrbuf。类似地,rio_writen 函数从位置 usrbuf 传送 n 个字节到描述符 fdrio_readn 函数在遇到 EOF 时只能返回一个不足值。rio_writen 函数决不会返回不足值。对同一个描述符,可以任意交错地调用 rio_readnrio_writen

图 10-4 显示了 rio_readnrio_writen 的代码。注意,如果 rio_readnrio_writen 函数被一个从应用信号处理程序的返回中断,那么每个函数都会手动地重启 readwrite。为了尽可能有较好的可移植性,我们允许被中断的系统调用,且在必要时重启它们。

code/src/csapp.c

ssize_t rio_readn(int fd, void *usrbuf, size_t n)
{
    size_t nleft = n;
    ssize_t nread;
    char *bufp = usrbuf;

    while (nleft > 0) {
        if ((nread = read(fd, bufp, nleft)) < 0) {
            if (errno == EINTR) /* Interrupted by sig handler return */
                nread = 0;      /* and call read() again */
            else
                return -1;      /* errno set by read() */
        }
        else if (nread == 0)
            break;              /* EOF */
        nleft -= nread;
        bufp += nread;
    }
    return (n - nleft);         /* Return >= 0 */
}

code/src/csapp.c

ssize_t rio_writen(int fd, void *usrbuf, size_t n)
{
    size_t nleft = n;
    ssize_t nwritten;
    char *bufp = usrbuf;

    while (nleft > 0) {
        if ((nwritten = write(fd, bufp, nleft)) <= 0) {
            if (errno == EINTR) /* Interrupted by sig handler return */
                nwritten = 0;   /* and call write() again */
            else
                return -1;      /* errno set by write() */
        }
        nleft -= nwritten;
        bufp += nwritten;
    }
    return n;
}

图 10-4 rio_readnrio_writen 函数