为什么此消息不仅在写入文件时显示(使用poll C Linux函数)?

问题描述 投票:4回答:3

我在C编程中阅读有关民意调查的内容,并在poll(2) man page上构建了一个应用程序。

这是一个例子:

#include<stdio.h>
#include <stropts.h>
#include <poll.h>
#include <fcntl.h>

int main() {

    struct pollfd fds[2];
    int timeout_msecs = -1;
    int ret;
    int i;

    /* Open STREAMS device. */
    fds[0].fd = open("/home/jeshwanth/mywork/poll/dev0", O_RDONLY);
    fds[1].fd = open("/home/jeshwanth/mywork/poll/dev1", O_RDONLY);
    fds[0].events = POLLOUT | POLLWRBAND;
    fds[1].events = POLLOUT | POLLWRBAND;

    while (1) {
        ret = poll(fds, 2, timeout_msecs);

        if (ret > 0) {
            /* An event on one of the fds has occurred. */
            for (i = 0; i < 2; i++) {
                if (fds[i].revents != 0) {
                    /* Priority data may be written on device number i. */
                    printf(
                            "Priority Data may be written on device number %d POLLWRBAND\n",
                            i);

                }
                if (fds[i].revents = !0) {
                    /* Data may be written on device number i. */
                    printf("Data may be written on device number %d POLLOUT\n",
                            i);
                }
                if (fds[i].revents = !0) {
                    /* A hangup has occurred on device number i. */
                    printf("A hangup has occurred on device number %d\n", i);

                }
            }
        }
    }
    return 0;
}

注意:dev0和dev1是普通文件。当我运行程序时,如果dev0和dev1中没有发生任何事件,则会显示该消息。但是我期待当一些写入文件时,只有它才会显示消息。我错了吗?

c linux polling
3个回答
3
投票

轮询输出就绪并不意味着当出现输出时会收到通知:这意味着当有输出缓冲区空间可以输出时会收到通知(但是你仍然应该检查输出函数的返回值) 。轮询和输出之间的缓冲区状态可能已经改变;总是检查返回值)。


2
投票

最小FIFO命名管道示例

你将无法看到任何有趣的常规文件,因为那些总是立即给POLLINHow can select() wait on regular file descriptors (non-sockets)?

使用poll最简单的方法是使用命名管道,如下所示。这应该为您的主要应用程序做好准备:套接字和设备文件。

来源如下。用法:

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

在另一个shell上:

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每两秒写一次,这表明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=%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中测试过。

GitHub upstream

线条:

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

是必需的,否则你永远得到POLLHUP,参见:How to use the poll C function to watch named pipes in Linux?

为了更有趣,创建一个实现poll fops的Linux内核模块:How to add poll function to the kernel module code?


0
投票

我会告诉你如何纠正它。 revents被解释为几个位标志。

/* check for priority write readiness */
if (fds[i].revents & POLLWRBAND) {
  printf("Priority Data may be written on device number %d POLLWRBAND\n", i);
}

/* check for write readiness */
if (fds[i].revents & POLLOUT) {
  printf("Data may be written on device number %d POLLOUT\n", i);
}

/* check for hang-up */
if (fds[i].revents & POLLHUP) {
  printf("A hangup has occurred on device number %d\n", i);
}
© www.soinside.com 2019 - 2024. All rights reserved.