如何使用轮询C函数在Linux中观看命名pipe道?

我正试图编写一个程序,我应该使用poll函数来观察一些命名pipe道的末端。 我有一个for循环来检查每一个pipe道,每当民意调查返回> 0,我知道当一个pipe道从另一端的程序closures时,我会得到POLLHUP或POLLIN | POLLHUP在pollfd结构的revents字段中。

我的问题是:当一个pipe道确实closures并返回POLLHUP给我时,下一个循环会发生什么? 是否会在下一个循环和后续循环中一次又一次地返回POLLHUP,或者在第一个POLLHUP之后,poll函数是否会忽略它?

它将继续设置POLLHUP的崇拜。
另外,请参阅http://linux.die.net/man/3/poll以供参考。

最小的例子

来源如下。 用法:

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如何等待读取而不循环。

更酷的例子:

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

0每1秒写一次,每2秒写1次,这表明poll()如何同时处理两个输入,而不会相互拖延。

资源:

 #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=%dn=%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测试。

GitHub上游 。

回答原来的问题:

当一个管道确实关闭并返回POLLHUP给我,下一个循环会发生什么? 是否会在下一个循环和后续循环中一次又一次地返回POLLHUP,或者在第一个POLLHUP之后,poll函数是否会忽略它?

删除行:

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

你会看到它永远在POLLHUP循环。

删除:

 close(pfds[i].fd); 

并且你得到POLLNVAL ,因为它试图使用一个封闭的fd: Linux socket处理revents POLLERR POLLHUP POLLNVAL