如何在Linux中使用poll C函数监视命名管道? [英] How to use the poll C function to watch named pipes in Linux?

查看:367
本文介绍了如何在Linux中使用poll C函数监视命名管道?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个程序,在该程序中我应注意一些命名管道的末端 使用民意调查功能. 我有一个for循环,可在poll返回> 0时检查每个管道,并且我知道当管道从另一端的过程关闭时,我将得到POLLHUP或POLLIN | pollfd结构的revents字段中的POLLHUP.

I am trying to write a program where i am supposed to watch the ends of some named pipes using poll function. I have a for loop to check every pipe whenever poll returns >0 and i know that when a pipe gets closed from the procedure at the other end, i will get POLLHUP or POLLIN | POLLHUP in the revents field of the pollfd struct.

我的问题是:当确实关闭了一个管道并向我返回POLLHUP时,下一个循环会发生什么?是在下一个以及随后的任何循环中一次又一次地返回POLLHUP还是在第一个POLLHUP之后轮询函数将其忽略?

My question is: when one pipe does indeed get closed and returns POLLHUP to me, what will happen on the next loop? Is it going to return POLLHUP again and again in the next and any subsequent loop or is poll function going to ignore it after the first POLLHUP?

推荐答案

最小示例

以下来源.用法:

sudo mknod poll0.tmp p
sudo mknod poll1.tmp p
sudo chmod 666 poll*.tmp
./poll.out

在另一个外壳上:

printf a > poll0.tmp
printf b > poll1.tmp

输出:

loop
POLLIN i=0 n=1 buf=a
loop
POLLHUP i=0
loop
POLLIN i=1 n=1 buf=b
POLLHUP i=1
loop

因此请注意poll如何等待读取而不会循环.

So notice how poll waits for the reads without looping.

更酷的示例:

(while true; do date; sleep 1; done) > poll0.tmp &
(while true; do date; sleep 2; done) > poll1.tmp &

0每秒钟写入一次,而1每两秒钟写入一次,这说明poll()如何同时处理两个输入而不会彼此停顿.

0 gets written every one second, and 1 every two seconds, which shows how poll() is dealing with both inputs concurrently, without stalling each other.

来源:

#define _XOPEN_SOURCE 700
#include <fcntl.h> /* creat, O_CREAT */
#include <poll.h> /* poll */
#include <stdio.h> /* printf, puts, snprintf */
#include <stdlib.h> /* EXIT_FAILURE, EXIT_SUCCESS */
#include <unistd.h> /* read */

int main(void) {
    enum { N = 2 };
    char buf[1024], path[1024];
    int fd, i, n;
    short revents;
    struct pollfd pfds[N];

    for (i = 0; i < N; ++i) {
        snprintf(path, sizeof(path), "poll%d.tmp", i);
        /* O_NONBLOCK is required or else the open blocks
         * until the other side of the pipe opens. */
        fd = open(path, O_RDONLY | O_NONBLOCK);
        if (fd == -1) {
            perror("open");
            exit(EXIT_FAILURE);
        }
        pfds[i].fd = fd;
        /* Only events in this mask will be listened to.
         * However, there are also some events that are unmaskable,
         * notably POLLHUP when pipe closes! */
        pfds[i].events = POLLIN;
    }
    while (1) {
        puts("loop");
        i = poll(pfds, N, -1);
        if (i == -1) {
            perror("poll");
            exit(EXIT_FAILURE);
        }
        for (i = 0; i < N; ++i) {
            revents = pfds[i].revents;
            if (revents & POLLIN) {
                n = read(pfds[i].fd, buf, sizeof(buf));
                printf("POLLIN i=%d n=%d buf=%.*s\n", i, n, n, buf);
            }
            if (revents & POLLHUP) {
                printf("POLLHUP i=%d\n", i);

                /* This happens when the other side closed.
                 * This event is only cleared when we close the reader. */

                /* poll won't set POLLHUP anymore once all fds are closed.
                 * Any futher polls on this will give the POLLNVAL event instead. */
                close(pfds[i].fd);

                /* negative fds are ignored. So if we negate an FD,
                 * we can both turn if off for a while, and turn it on
                 * later on by re-nagating it. */
                pfds[i].fd *= -1;
            }
        }
    }
}

编译为:

gcc -o poll.out -std=c99 poll.c

在Ubuntu 14.04中进行了测试.

Tested in Ubuntu 14.04.

GitHub上游.

要回答原始问题:

当一个管道确实关闭并向我返回POLLHUP时,下一个循环会发生什么?是在下一个以及随后的任何循环中一次又一次地返回POLLHUP还是在第一个POLLHUP之后轮询函数将其忽略?

when one pipe does indeed get closed and returns POLLHUP to me, what will happen on the next loop? Is it going to return POLLHUP again and again in the next and any subsequent loop or is poll function going to ignore it after the first POLLHUP?

删除行:

close(pfds[i].fd);
pfds[i].fd *= -1;

,您将看到它在POLLHUP上永远循环.

and you will see that it loops forever over POLLHUP.

仅删除:

close(pfds[i].fd);

,您将得到POLLNVAL,因为它尝试使用封闭的fd:

and you get POLLNVAL instead, as it tries to use a closed fd: Linux socket handling revents POLLERR POLLHUP POLLNVAL

这篇关于如何在Linux中使用poll C函数监视命名管道?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆