Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to monitor a file descriptor for new data availability?

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?

like image 800
LuisABOL Avatar asked Jun 16 '13 14:06

LuisABOL


People also ask

How to check for data availability from file descriptor 5?

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.

How does the OS read the data from a file descriptor?

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.

How to check for data availability when read timeout is 0?

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.

How to check if a file descriptor is open or not?

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.


1 Answers

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.

like image 166
nosid Avatar answered Oct 10 '22 08:10

nosid