代码之家  ›  专栏  ›  技术社区  ›  PoVa

手动输入时,轮询在stdin上工作,但在输入通过管道传输且未重定向时不工作

  •  2
  • PoVa  · 技术社区  · 8 年前

    考虑这个C程序:

    #include <poll.h>
    #include <stdio.h>
    #include <unistd.h>
    
    #define TIMEOUT 500 // 0.5 s
    #define BUF_SIZE 512
    
    int fd_can_read(int fd, int timeout) {
        struct pollfd pfd;
    
        pfd.fd = fd;
        pfd.events = POLLIN;
    
        if (poll(&pfd, 1, timeout)) {
            if (pfd.revents & POLLIN) {
                return 1;
            }
        }
    
        return 0;
    }
    
    int main(int argv, char **argc) {
        int fd;
        size_t bytes_read;
        char buffer[BUF_SIZE];
    
        fd = STDIN_FILENO;
    
        while (1) {
            if (fd_can_read(fd, TIMEOUT)) {
                printf("Can read\n");
                bytes_read = read(fd, buffer, sizeof(buffer));
    
                printf("Bytes read: %zu\n", bytes_read);
            }
            else {
                printf("Can't read\n");
            }
        }
    }
    

    它尝试轮询给定的文件描述符(在本例中是stdin的fd),并在可以读取时尝试从中读取。下面是一个名为“input”的示例输入文件:

    stuff to be read
    

    假设我运行程序,输入一些信息,然后关闭它:

    ./a.out
    test
    Can read
    Bytes read: 5
    Can't read
    Can't read
    ...
    

    因此,让我们尝试通过管道/重定向文件内容来读取文件中的输入 stdin 我的计划:

    cat input | ./a.out # Or ./a.out < input
    Bytes read: 0
    Can read
    Bytes read: 0
    Can read
    ...
    

    现在,轮询立即返回(不等待超时),并给出了我意想不到的结果。我确实知道 poll()

    1 回复  |  直到 8 年前
        1
  •  8
  •   Some programmer dude    8 年前

    问题是 poll (就像 select )只告诉你打电话给例如。 read 不会阻塞。它不会告诉你是否真的有什么可以读的。

    如果你阅读 the read manual page 当它回来的时候你会看到的 0 这意味着 文件结束 (或插座连接关闭)。

    什么 投票 告诉你的是 阅读 可以在没有阻塞的情况下调用,然后呢 阅读 通过返回告诉您 0 就是没什么可看的了。

    按文件结束快捷键(默认情况下),您将获得类似的“假阳性” Ctrl-D 对于非管道或重定向输入示例。