在"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 */
}发布于 2013-11-20 10:39:26
通常,当代码可以(或打算)并行地执行其他操作而不是等待输入(例如检查另一个文件或套接字)时,就会使用非阻塞IO。否则,就像Jlghtuse提到的那样,一个简单的阻塞IO将执行与轮询文件读取相同的功能。但是,我不确定非阻塞IO是否保证返回请求的确切字节数。作为一个安全的赌注,它可能需要一个时间循环无论如何。我认为一个可用的代码块看起来可能是:
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;
}
}发布于 2013-11-20 08:17:15
不,这个示例不需要包装在循环中。它使用goto语句(有关其使用的良好示例,请参见this answer )。
这个例子显示了非阻塞读取,这就是为什么这段代码不同于第一个代码的原因。参见第二个代码块之后的注意事项:
处理EAGAIN的案例,就像我们做的EINTR案例一样(用一个goto启动)将是毫无意义的。我们最好不要使用非阻塞I/O,非阻塞I/O的目的是捕获EAGAIN并做其他有用的工作。
https://stackoverflow.com/questions/20090235
复制相似问题