# 10.5.1 RIO 的无缓冲的输入输出函数
通过调用 rio_readn 和 rio_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 个字节到描述符 fd。rio_readn 函数在遇到 EOF 时只能返回一个不足值。rio_writen 函数决不会返回不足值。对同一个描述符,可以任意交错地调用 rio_readn 和 rio_writen。
图 10-4 显示了 rio_readn 和 rio_writen 的代码。注意,如果 rio_readn 和 rio_writen 函数被一个从应用信号处理程序的返回中断,那么每个函数都会手动地重启 read 或 write。为了尽可能有较好的可移植性,我们允许被中断的系统调用,且在必要时重启它们。
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_readn 和 rio_writen 函数