使用非阻塞读进行选择

4

我在网上找不到关于这个问题的答案。

当在Linux上调用选择以读取文件并将套接字设置为非阻塞时,应该期望什么呢?

我认为这并不像select手册中所述那样简单:

在readfds列表中列出的内容将被观察以查看是否有字符可供读取(更准确地说,是查看读取是否会被阻塞;特别是,在文件结束符处也可以随时读取文件描述符)

如果将套接字设置为非阻塞,则它永远不应该被阻塞,select是否应立即返回?这听起来不对...是Hyde文档错了还是忽略了这种情况?

此外,如果select确实会被阻塞,它应该返回什么值?读取套接字不会被阻塞,但套接字没有可供读取的数据..

当我回家后,我会写一些代码示例并编辑这个问题,这可能对任何谷歌这个主题的人都有很大帮助。

3个回答

2
如果你使用select()在一个没有数据等待读取(也没有任何错误)的套接字上进行读取,它会阻塞(直到select()超时)。

这正是我所想的,但我找不到任何支持它的东西。你能找到吗? - user1708860
当然,任何一本关于事件驱动套接字编程的书都会解释这个问题。我推荐已故的Richard Stevens所著的《Unix网络编程》。 - John Zwinck
@ejp,我从select man页面引用的部分表明了相反的情况:“如果读取不会阻塞”,在非阻塞模式下这种情况总是成立的。 - user1708860
@user1708860:man页可能含糊不清或者并没有直接解决你所关心的问题。如果你仍然不相信这就是它的工作原理,请自行尝试一下。 - John Zwinck
1
在Linux上,如果读取操作将返回,则select函数会返回。因此,对于没有可用数据的非阻塞流,select函数将返回。这显然不是POSIX行为,但Linux不符合POSIX标准。 - Jean-Baptiste Yunès

2
这是一个小的C程序,它展示了在非阻塞文件描述符上调用select(2)仍然会阻塞,直到有可读内容:
#include <stddef.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>

int main(int argc, char **argv) {
    int ready;
    struct timeval *pto;
    fd_set readfds, writefds;
    char buf[1024];
    int bytes;
    int fd = 0; // stdin

    pto = NULL;
    FD_ZERO(&readfds);
    FD_ZERO(&writefds);
    FD_SET(fd, &readfds);

    int flags = fcntl(fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, flags | O_NONBLOCK);

    while (1) { 
        ready = select(1, &readfds, &writefds, NULL, pto);

        if (ready == -1) {
            printf("got -1\n");
            return 1;
        }

        printf("ready = %d\n", ready);

        bytes = read(fd, buf, 1024);
        if (bytes == 0) {
            printf("all done\n");
            return 0;
        } else if (bytes > 0) {
            buf[bytes] = '\0';
            printf("read: %s\n", buf);
        } else {
            printf("got an error\n");
        }
    }
}

-1
如果您在不使用非阻塞的情况下使用read(),程序将会阻塞,从而阻塞代码的流程。但是,如果您使用非阻塞模式,select()将立即返回,而不会阻塞代码流程,仅在有数据可读时返回大于零的值。

不,read() 会立即返回。select() 会阻塞,直到有可选项或超时。 - user207421
请不要在评论中提出新问题。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接