12

我需要用纯 C 编写的程序在标准输入关闭时停止执行。

在程序主循环中完成了无限期的工作,我无法在那里使用阻塞检查(如getc())(没有数据应该到达标准输入 - 它只是在未知时间内保持打开状态)。

我打算使用描述的功能来实现托管在 inetd、xinetd 或其类似物的网络守护进程——它应该在连接保持打开状态时在标准输出上发出数据,并在连接关闭时正确完成工作。现在我的程序被托管服务杀死,因为它在连接终止后不会停止。

我想知道fctntl()O_NONBLOCK标志应用于标准输入描述符是否允许我read()在非阻塞模式下使用函数?我应该select()以某种方式使用吗?

PS 数据不是假设的,但可能会到达标准输入。一种非阻塞读出的方式将是该问题的答案。

4

5 回答 5

8

select()完全符合您的要求:表示文件描述符(文件、套接字等)上的操作(在本例中为读取)不会阻塞。

#include <stdio.h>
#include <sys/select.h>

int is_ready(int fd) {
    fd_set fdset;
    struct timeval timeout;
    int ret;
    FD_ZERO(&fdset);
    FD_SET(fd, &fdset);
    timeout.tv_sec = 0;
    timeout.tv_usec = 1;
    //int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
     struct timeval *timeout);
    return select(fd+1, &fdset, NULL, NULL, &timeout) == 1 ? 1 : 0;
}

您现在可以在使用前检查文件描述符,例如为了清空文件描述符:

void empty_fd(int fd) {
    char buffer[1024];
    while (is_ready(fd)) {
        read(fd, buffer, sizeof(buffer));
    }
}

在您的情况下,使用fileno(stdin)获取标准输入的文件描述符:

if (is_ready(fileno(stdin))) {
    /* read stuff from stdin will not block */
}
于 2009-10-20T13:12:01.833 回答
2

我想知道带有 O_NONBLOCK 标志的 fctntl() 是否允许我在非阻塞模式下使用 read() 函数?

使用 O_NONBLOCK 运行标准输入比选择具有优势。选择说有一些数据,但没有多少。有时您希望获取所有可用数据,但不阻塞,无论队列中有多少。为每个角色运行 select 似乎很忙…… O_NONBLOCK 对我不起作用。它是一个内部标志,不会在大多数 tty 驱动程序中公开。

查看 ioctl(..., FIONBIO)。它似乎完成了工作。

于 2012-07-05T12:30:07.833 回答
1

我不确定您是否可以在标准输入上设置 O_NONBLOCK,但select()或者poll()肯定会完成工作。

于 2009-10-20T12:43:12.493 回答
0

有什么问题feof(stdin)

于 2009-10-20T12:34:41.837 回答
0

是的,您可以使用select(超时时间为零)。但是,您不需要将文件描述符设置为非阻塞 - 如果select告诉您文件描述符是可读的,那么read它肯定不会阻塞。

因此,偶尔使用 轮询文件描述符 0 select,如果它是可读的,则使用read它。如果read返回 0,则表示它已关闭。

于 2009-10-20T12:48:04.700 回答