The named pipe option can be used to display data in real-time. That is, with the named pipe option you can use xmgr to display data immediately as you generate them by your number-crunching program. In contrast with the simple pipe option, xmgr's graphic user interface remains responsive to your actions while displaying the data.
A simple pipe is used, for example, by the command
grep searchfor file | more
The "|
" symbol is the pipe, i.e. the output of grep
is mounted to one end of the pipe, and the input of more
is
mounted to the other end of the pipe. Everything that grep
writes
to its standard output goes through the pipe, and more
sees this
on its standard input. Another name for a pipe is FIFO (First In First Out).
That means that things arrive at the end of the pipe in the same order as you
put them in (in contrast with a stack, where you'll see first what you put in
last).
A named pipe is essentially the same, except that (you guessed it) the pipe gets a file name. Before we can use a named pipe, we have to create it. That can be done using
mkfifo /tmp/mynamedpipe
from the shell prompt, or using the C function
#include <sys/stat.h> . . mkfifo ("/tmp/mypipename", 0600);
where 0600
sets the access permissions for the named pipe.
After having created the named pipe, one program can open that file name for writing (as you would open any ordinary file), and another program can open the file for reading. Here is a simple example:
mkfifo /tmp/testpipe echo "This is a test" > /tmp/testpipe & cat /tmp/testpipe rm /tmp/testpipe
You can use the the C functions "open
" or "fopen
" to
mount a process to the pipe.
The named pipe behaves very much like an ordinary file, except that
SIGPIPE
. If
we did not install a signal handler for SIGPIPE
, the talking end
exits.If xmgr is used with the named pipe option, it starts a timer that ticks in intervals of 1000 milliseconds. You can change that interval using the "-timer" command line option. When the first tick occurs, xmgr opens and reads the named pipe and executes the corresponding commands. At the second tick, xmgr closes the pipe. At the third tick, xmgr reopens the pipe, and so forth. In other words, every two seconds we give xmgr a one-second break to respond to commands from the graphic user interface if the commands at the named pipe arrive faster than xmgr can execute them.
There are at least two different ways how to implement the talking end (your number-cruncher).
xmgr
-npipe /tmp/mypipe
")man fork
").
As described above, xmgr will close the named pipe every two seconds.
Therefore, your talking end will receive the signal SIGPIPE
every
two seconds as long as the named pipe is open for writing. The default action
of a program is to exit on SIGPIPE
. Hence, you need to tell your
program to ignore SIGPIPE
's:
#include <signal.h> . . /* Don't exit on SIGPIPE */ signal (SIGPIPE, SIG_IGN);
If you try to write to the pipe while xmgr has closed its listening end, the
thus written commands are lost - xmgr will never see them. Therefore, after
each write
to the pipe you should test whether the write was
successful. If it was not, the write operation needs to be repeated later.
One way to handle this problem is to append new commands to a global buffer instead of sending them directly. Each time we append some new commands to that buffer, we subsequently try to write the buffer to the pipe. If the write operation succeeds, we clear the buffer. If it fails, we try to resend the contents of the buffer next time we append a new command.
There is still a problem we need to take care of: it might happen that we always try to write to the pipe when xmgr is not listening. For example, if we send new data to xmgr approximately every two seconds, there is a good chance that we find xmgr not listening for quite a long time. This can lead to an overflow of the buffer. Therefore, each time we append some new commands to the buffer we should check whether the buffer filling exceeds some threshold. If it does, we should wait for xmgr's next sensitive time window and send the entire buffer before continuing our calculations.
Isn't there a simpler solution?
Yes, there is. You can use the
acegr_np
library that comes with xmgr
and implements the solutions suggested in the above.