在“Linux系统编程”一书的第34页上,给出了以下使用while循环正确处理部分读取以阻止读取的示例
ssize_t ret;
while (len != 0 && (ret = read(fd, buf, len)) != 0) {
if (ret == -1) {
if (errno == EINTR)
continue;
perror("read");
break;
}
len -= ret;
buf += ret;
}
在下一页中,它给出了非阻塞读取的以下示例。此示例是否需要包含在while循环中以处理部分读取的可能性?
char buf[BUFSIZ];
ssize_t nr;
start:
nr = read(fd, buf, BUFSIZ);
if (nr == -1) {
if (errno == EINTR)
goto start; /* oh shush */
if (erron == EAGAIN)
/* resubmit later */
else
/* error */
}
答案 0 :(得分:1)
通常,当代码可以(或打算)并行执行其他操作而不是等待输入(例如检查另一个文件或套接字)时,使用非阻塞IO。否则,一个简单的阻塞IO将执行与在文件上轮询读取相同的技巧,如Jlghtuse所述。但是,我不确定是否保证非阻塞IO返回所请求的确切字节数。作为一个安全的赌注,它可能会使用while循环。我认为一个可用的代码块可能看起来像:
char buf[BUFSIZ];
ssize_t nr;
char *bufp = buf;
ssize_t rdbyts = 0;
while(rdbyts < BUFSIZ) {
nr = read(fd, bufp, (BUFSIZ - rdbyts));
if (nr == -1) {
if (errno == EINTR)
continue; /* oh shush */
else if (errno == EAGAIN)
/* resubmit later - might be do
* something else and come back
* or just sleep. */
do_some_work_or_sleep();
continue;
else
/* error */
break;
} else if (nr < (BUFSIZ - rdbytes)) {
bufp += nr;
rdbyts += nr;
}
}
答案 1 :(得分:0)
不,这个例子不需要循环包装。它使用goto
语句(请参阅this answer以获取其使用的好例子。)
此示例显示非阻塞读取,这就是此代码与第一个不同的原因。请参阅第二个代码块之后的注释:
处理EAGAIN案例就像我们做了EINTR案例一样(带有goto 开始)没什么意义。我们不妨没用过非 阻止I / O.非阻塞I / O的目的是捕获EAGAIN和 做其他有用的工作。