2012-09-16 32 views
4

我正在阅读有关C编程的投票,并在poll(2)手册页中构建了一个应用程序。
这里是例子:
轮询C Linux函数如何工作?

#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; 
} 

注:装置0和DEV1是正常的文件。当我运行程序时,如果在dev0和dev1中没有发生事件,则显示消息。但是我期待有人写入文件时,只有它应该显示消息。我错了吗?

+4

没有那些'printf'应为每个封闭那些来执行'if'分支具备的条件'0'。 – oldrinb

+0

@oldrinb谢谢,我在发布之前测试它,所以我误以为=,现在它是!=。忘了那些printf的,怎么ret> 0?如果文件没有变化? –

+0

你的代码仍然是错误的,但现在它会打印后面的2条消息,因为它们的封闭'if'分支都具有'!0'的条件。 – oldrinb

回答

3

轮询它输出的准备并不意味着你会得到通知时,一些输出时:这意味着,当有可用的输出缓冲空间,所以你可以输出(但你还是应该检查你就会收到通知输出函数的返回值,轮询和输出之间的缓冲区状态可能已经改变;始终检查返回值)。

+0

感谢@ninjalj,实际上我想做的事情是我应该在写入文件的时候收到通知,那么如何实现? –

+2

您不能使用传统的* nix APIs获得通知,在Linux上,你可以使用inotify,为了更便携,你可以使用FAM或gamin – ninjalj

+0

谢谢@ninjalj,FAM看起来有趣:)。 –

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); 
} 
+0

我再次确认,文件I我打开的文件是普通文件,不是设备文件或其他类型的文件,可以吗? –

1

最小FIFO命名管道例如

您将无法看到任何与常规文件有趣,因为那些总是给POLLIN立刻道:How 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?