2012-09-16 34 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?