1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
When the tt(Monitor) object starts a child process, it creates an object
of the class tt(Child). The tt(Child) class is derived from the class
tt(Fork), allowing it to operate as a emi(daemon) (as discussed in the
previous section). Since tt(Child) is a daemon class, we know that its parent
process must be defined as an empty function. Its tt(childProcess) member
has a non-empty implementation. Here are the characteristics of the class
tt(Child):
itemization(
it() The tt(Child) class has two tt(Pipe) data members, to handle
communications between its own child- and parent processes. As these pipes are
used by the tt(Child)'s child process, their names refer to the child
process. The child process reads from tt(d_in), and writes to tt(d_out). Here
is the interface of the class tt(Child):
verbinclude(//CLASS examples/monitor/child.h)
it() The tt(Child)'s constructor simply stores its argument, a
child-process order number, in its own tt(d_nr) data member:
verbinclude(//CONS examples/monitor/child.h)
it() The tt(Child)'s child process obtains commands from its standard
input stream and writes its output to its standard output stream. Since the
actual communication channels are pipes, redirections must be used. The
tt(childRedirections) member looks like this:
verbinclude(//CHILD examples/monitor/child.cc)
it() Although the parent process performs no actions, it must configure
some redirections. Realizing that the names of the pipes indicate their
functions in the child process. So the parent em(writes) to tt(d_in) and
em(reads) from tt(d_out). Here is tt(parentRedirections):
verbinclude(//PARENT examples/monitor/child.cc)
it() The tt(Child) object exists until it is destroyed by the
tt(Monitor)'s tt(stopChild) member. By allowing its creator, the tt(Monitor)
object, to access the parent-side ends of the pipes, the tt(Monitor) object
can communicate with the tt(Child)'s child process via those pipe-ends. The
members tt(readFd) and tt(writeFd) allow the tt(Monitor) object to access
these pipe-ends:
verbinclude(//PIPES examples/monitor/child.h)
it() The tt(Child) object's child process performs two tasks:
itemization(
it() It must reply to information appearing at its standard input
stream;
it() If no information has appeared within a certain time frame (the
implementations uses an interval of five seconds), then a message is written
to its standard output stream.
)
To implement this behavior, tt(childProcess) defines a local
tt(Selector) object, adding tt(STDIN_FILENO) to its set of monitored input
file descriptors.
Then, in an endless loop, tt(childProcess) waits for tt(selector.wait())
to return. When the alarm goes off it sends a message to its standard output
(hence, into the writing pipe). Otherwise, it echoes the messages appearing
at its standard input to its standard output. Here is the tt(childProcess)
member:
verbinclude(//PROCESS examples/monitor/child.cc)
it() Two accessors are defined allowing the tt(Monitor) object to obtain
the tt(Child)'s process ID and its order number:
verbinclude(//PIDNR examples/monitor/child.h)
it() A tt(Child) process terminates when the user enters a tt(stop)
command. When an existing child process number was entered, the corresponding
tt(Child) object is removed from tt(Monitor)'s tt(d_child) map. As a result,
its destructor is called. tt(Child)'s destructor calls tt(kill) to terminate
its child, and then waits for the child to terminate. Once its child has
terminated, the destructor has completed its work and returns, thus completing
the erasure from tt(d_child). The current implementation fails if the child
process doesn't react to the tt(SIGTERM) signal. In this demonstration program
this does not happen. In `real life' more elaborate killing-procedures may be
required (e.g., using tt(SIGKILL) in addition to tt(SIGTERM)). As discussed in
section ref(CONSEXCEPTIONS) it em(is) important to ensure the proper
destruction. Here is the tt(Child)'s destructor:
verbinclude(//CHILDDES examples/monitor/child.cc)
)
|