13.3 Third stage of interpretation
In the third and final stage of the interpretation of an EDL
script the real experiment is run. This third stage may be repeated
several times if the user restarts an experiment without reloading the
EDL
file.
At the start of the third stage the GPIB bus, the serial ports, the
LAN connections and the RULBUS printer port are initialized (at least
if one of the devices needs them). Next the hook functions in the
modules are called that allow the modules to initialize the devices
and do all checks they find necessary. If this was successful the
graphics for the experiment are initialized, opening up the display
windows. When all this has been done fsc2
is ready to do the
experiment, i.e. to interpret the EXPERIMENT
section.
But there is a twist. Just before starting to interpret the
EXPERIMENT
section fsc2
splits itself into two independent
processes by calling fork(2)
. If you use the ps
command to
list all your running processes suddenly a new instance of fsc2
will be listed(23). The new
processes is doing the interpretation of the EXPERIMENT
section,
i.e. is running the experiment, while one of the other processes is
responsible for the graphics and all interactions with the user.
The main reason for splitting the execution of the experiment into two
separate tasks is the following: the execution of the experiment, as far
as concerned with acquiring data from the devices etc. should be
unimpeded (at least as far as possible) from the task of dealing with
displaying data and user requests to allow maximum execution speed and
to make the timing of the experiment less dependent on user
interruptions. Take for example the case that the user starts to move
one of fsc2
s windows around on the screen. As long as she is
moving the window no other instructions of the program get executed,
which effectively would stop the experiment for this time even though
nothing really relevant happens. By having one task for the actual
execution of the experiment and one for the user interaction this
problem vanishes because the task for the experiment can continue while
only the other task, responsible for the user interaction, is
blocked. This, of course, also applies to all other actions the user may
initiate, e.g. resizing of windows, magnification of data etc.
Another advantage is, of course, that on machines with more than one processor the workload can be distributed onto two processors.
The approach requires some channels of communication between the two
processes. Because the user interaction task has to draw the new data
the other task, executing the experiment, is producing the data will have
to passed on from the experiment task to the user interaction task. And,
the other way round, the user interaction task must be able to send back
informations received from the user (e.g. which file name got selected)
and to stop the experiment when the user hits the Stop
button. Care has been taken that this is done in a way that usually
can't be impeded by user interventions. The only exceptions are cases
where the further execution of the experiment depends on user input,
e.g. if within the experiment a new file has to be opened and the name
must be selected by the user.
The most important part of the communication between parent process (the user interaction task) and the child process (the task running the experiment) is basically a one-way communication - the child process must pass on newly acquired data to the parent process to be drawn. The child processes writes the new data (together with the information where they are to be drawn) into a shared memory segment and stores the key for this memory segment in an unused slot in another buffer (that also resides in shared memory). Then it sends the parent process a signal to inform it that new data are available and continues immediately.
The user interaction process gets interrupted by the signal (even while it is doing some other tasks on behalf of the user), removes and stores the key for the memory segment, and can now deal with the new data whenever it has the time to do so.
Problems can arise only if the child process for running the experiment creates new data at a much higher rate than the parent can accept them, in which case the buffer for memory segment keys would fill up(24). Only if all the slots in the buffer are used up child process will have to suspend the experiment until the parent empties one or more of the slots. But fortunately in practice this rarely happens. And as a further safeguard against this happening the parent is written in a way that it will empty slots in the buffer as fast as possible, if necessary deferring to draw data or to react to user requests.
There is also a second communication channel for cases where the task running the experiment needs some user input. Typical cases are requests for file names, but also requests for information about the state of objects in the toolbox. Here the task running the experiment always has to wait for a reaction by the user interaction task (which in turn may have to wait for user input). This communication channel is realized by a pair of pipes between the processes.
Footnotes
(23)
Please note that already before the experiment
gets started you will find that there are three instances of fsc2
running, during the experiment there are (at least) four.
(24)
The buffer is guarded against overflows by a semaphore that is initialized to the number of slots in the buffer and on which the child process does a down operation before writing data into the buffer while the parent process posts it after removing an item.
This document was generated by Jens Thoms Toerring on September 6, 2017 using texi2html 1.82.