Why is this message not only displayed when writing a file (using the poll C Linux function)?

I read about a survey in C programming and created the application given on the poll (2) manual page .

Here is an example:

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

Note: dev0 and dev1 are normal files. When I run the program, if no events occurred in dev0 and dev1, a message is displayed. But I was expecting some writing to the file to happen, only then it should display a message. I was wrong?

+4
source share
3 answers

A readiness to output survey does not mean that you will be notified when any output occurs: it means that you will be notified when the output buffer space is available so that you can output (but you should still check the return value of your function of output Perhaps the state of the buffer has changed between polling and output; always check the return values).

+3
source

Minimal FIFO named pipe example

You won’t be able to see anything interesting in regular files, since they always give POLLIN immediately: How to select () wait on regular file descriptors (not sockets)?

The easiest way to play with poll is to use named pipes as shown below. This should prepare you for their main application: sockets and device files.

Source below. Using:

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

In another shell:

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

Output:

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

So, note that poll expects reading without a loop.

Cooler example:

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

0 recorded every second, and 1 every two seconds, which shows how poll() works with both inputs simultaneously, without stopping each other.

A source:

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

Compile with:

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

Tested on Ubuntu 14.04.

GitHub upstream .

Rows:

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

otherwise you will get POLLHUP forever, see also: How to use the C poll function to view named pipes in Linux?

For even more fun, create a Linux kernel module that implements poll fops: How do I add a polling function to the kernel module code?

+2
source

I will give you a hint on how to fix this. revents interpreted as multiple bit flags.

 /* 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
source

Source: https://habr.com/ru/post/1434431/


All Articles