Polling a file without using huge amount of system resources

I

Ishmael

I would like to check a file continuously to see if something has been
written to it. If so, immediately run a script. I can do this
successfully by repeatedly polling the file, as shown below, but this
uses up lots of system resources. I can, of course, add a 'sleep' to
the while loop, which reduces the drag on the system, but it also
slows down the response time.

Can someone recommend a replacement for this code using some more
elegant means? Ideally, I would like to set some sort of interrupt as
soon as the \n character is written to the file. That way, I can
avoid doing any polling myself and let the system handle it. Maybe
select(2) or FIFOs would work, but I've read the documentation and
can't figure out if this is really what I want. Thanks for your help!

# ---- My naive way ----
# Listener

open(FID, ">myfile") || die("Can't open: $!");
while (1) {
if (my $line = <FID>) {
print "$line\n";
last;
}
}


# Writer
open(FID, ">myfile") || die("Can't open: $!");
print FID "test\n";
 
I

Ishmael

Thanks for the response, that's quite helpful! As it turns out, FIFOs
do the trick for what I wanted. But now I'm curious - when I open,
for example, an xterm window, it will wait patiently until I type
something, and it knows (instantly!) when I press 'Enter'. That means
that somewhere, it is polling rapidly for keypress events, yet it uses
essentially no system resources. Do you know if that is implemented
using the functions you describe (like inotify?)? Or is there some
other secret mechanism?
 
T

Ted Zlatanov

I> But now I'm curious - when I open, for example, an xterm window, it
I> will wait patiently until I type something, and it knows (instantly!)
I> when I press 'Enter'. That means that somewhere, it is polling
I> rapidly for keypress events, yet it uses essentially no system
I> resources.

Actually X applications set up an event loop, where they respond to
messages from X. So for an xterm in particular, when you just start it,
the key press is delivered by a X event and then fed to whatever process
the xterm is running (e.g. a shell).

I> Do you know if that is implemented using the functions you describe
I> (like inotify?)? Or is there some other secret mechanism?

Look at IO::Select for a simple way to poll multiple filehandles (either
IO::Handle objects or file descriptors). The examples show how to use
it to check if input is waiting on STDIN, with \*STDIN.

Writing software in a time-sharing environment boils down to either
receiving events or yielding (via sleep/usleep) when there is nothing to
do. Usually, events are not available in the Unix environment unless
you implement a X event loop or something similar. So waiting for input
and yielding are the most common choice, and the one that works in
general terms with file or interactive input.

The interactivity of the application in a time-sharing environment
actually *increases* when it idles instead of consuming key presses
immediately. The reason is that the OS, meanwhile, can get a chance to
do other tasks instead of interfering with the application while the key
presses are handled. Just don't use sleep(1), that's too long, use
usleep(50) which is usually good enough for interactive use.

Anyhow, if you want good responsiveness in Perl programs, use
Term::ReadKey for single-key presses (it will tell you if a key press is
waiting) and Term::ReadLine::Gnu for line-based editing. Don't try to
be too clever with handling input, because you never know if you're
running in a local xterm or in a remote shell over a 9600 baud modem.

I'm sure much more can be said on this topic...

Ted
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,154
Members
46,702
Latest member
LukasConde

Latest Threads

Top