Consider the following code snippet.
#include <fcntl.h>
#include <stdio.h>
#include <sys/poll.h>
#include <unistd.h>
int main(int argc, char ** argv) {
int fd;
char buf[1024];
int i;
struct pollfd pfds;
fd = open(argv[1], O_RDONLY);
while (1) {
pfds.fd = fd;
pfds.events = POLLIN;
poll(&pfds, 1, -1);
if (pfds.revents & POLLIN) {
i = read(fd, buf, 1024);
write(1, buf, i);
}
}
return 0;
}
This program receives a file name, opens the corresponding file, and "poll"s its file descriptor in order to monitor data in availability. Whenever poll
detects data in availability, those new data are printed.
However, what happens with this program? If the file I want to monitor already contained data when the program is launched, its contents are printed. That's ok. But, later, when I edit the file with a text editor and save it, my program doesn't print the new data.
So, how to monitor a regular file descriptor (not a file using its path) for new data availability? Do I have to use another function other than poll
? Or am I missing any pollfd
flag?
The idea is to use read with -t 0 (to have zero timeout) and -u 5 (read from file descriptor 5) to instantly check for data availability. Of course this is just a toy loop to demonstrate the concept.
When you read the data from a descriptor, the OS read the data from the hard-disk. The information in file descriptor just represents the location of the file on hard-disk etc.. File descriptor to file is not a one to one mapping. I could open () the same file 4 times and get 4 different file descriptors.
If timeout is 0, read returns immediately, without trying to read and data. The exit status is 0 if input is available on the specified file descriptor, non-zero otherwise. The idea is to use read with -t 0 (to have zero timeout) and -u 5 (read from file descriptor 5) to instantly check for data availability.
You can use fstat()to check if a file descriptor is open. Or you can use one of the other functions that take a file descriptor as an argument, looking for EBADF(bad file descriptor) if the descriptor is not open). The advantage of fstat()is that it is a pure interrogation function whereas most others try to change something about the descriptor.
You can't use poll
on regular files to watch for changes. However, there are several other ways. The classic approach is to call fstat
at regular intervals with the open file descriptor, and compare the returned fields with the previous fields (in particular st_size
). A modern approach is to use inotify(7)
for monitoring files. For example recent versions of GNU tail use this approach:
$ strace tail -f /tmp/foobar
...
open("/tmp/foobar", O_RDONLY) ) = 3
...
inotify_init() = 4
inotify_add_watch(4, "/tmp/foobar", IN_MODIFY|IN_ATTRIB|IN_DELETE_SELF|IN_MOVE_SELF) = 1
...
read(4, ...
See the manual page inotify(7) for more information on how that works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With