首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >非阻塞模式下读取的部分读取

非阻塞模式下读取的部分读取
EN

Stack Overflow用户
提问于 2013-11-20 07:51:12
回答 2查看 994关注 0票数 0

在"Linux系统编程“一书的第34页上,给出了正确处理部分读取的示例,并给出了用于阻塞读取的while循环。

代码语言:javascript
复制
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循环中以处理部分读取的可能性?

代码语言:javascript
复制
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 */
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-11-20 10:39:26

通常,当代码可以(或打算)并行地执行其他操作而不是等待输入(例如检查另一个文件或套接字)时,就会使用非阻塞IO。否则,就像Jlghtuse提到的那样,一个简单的阻塞IO将执行与轮询文件读取相同的功能。但是,我不确定非阻塞IO是否保证返回请求的确切字节数。作为一个安全的赌注,它可能需要一个时间循环无论如何。我认为一个可用的代码块看起来可能是:

代码语言:javascript
复制
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;
    }
}
票数 0
EN

Stack Overflow用户

发布于 2013-11-20 08:17:15

不,这个示例不需要包装在循环中。它使用goto语句(有关其使用的良好示例,请参见this answer )。

这个例子显示了非阻塞读取,这就是为什么这段代码不同于第一个代码的原因。参见第二个代码块之后的注意事项:

处理EAGAIN的案例,就像我们做的EINTR案例一样(用一个goto启动)将是毫无意义的。我们最好不要使用非阻塞I/O,非阻塞I/O的目的是捕获EAGAIN并做其他有用的工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20090235

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档