mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-18 10:06:54 +01:00
f61c34b9c7
git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@432 f6dd340e-d3f9-0310-b409-bdd246841980
74 lines
4.6 KiB
Text
74 lines
4.6 KiB
Text
Redirection at the system level requires the use of emi(file descriptors),
|
|
created by the ti(pipe) system call. When two processes want to communicate
|
|
using such file descriptors, the following happens:
|
|
itemization(
|
|
it() The process constructs two em(associated file descriptors) using the
|
|
tt(pipe) system call. One of the file descriptors is used for writing, the
|
|
other file descriptor is used for reading.
|
|
it() Forking takes place (i.e., the system tt(fork) function is called),
|
|
duplicating the file descriptors. Now we have four file descriptors as
|
|
the child process and the parent process both have their own copies of the two
|
|
file descriptors created by tt(pipe).
|
|
it() One process (say, the parent process) uses the filedescriptors
|
|
for em(reading). It should close its filedescriptor intended for em(writing).
|
|
it() The other process (say, the child process) uses the filedescriptors
|
|
for em(writing). It should therefore close its filedescriptor intended for
|
|
em(reading).
|
|
it() All information written by the child process to the file
|
|
descriptor intended for writing, can now be read by the parent process from
|
|
the corresponding file descriptor intended for reading, thus establishing a
|
|
communication channel between the child- and the parent process.
|
|
)
|
|
Though basically simple, errors may easily creep in. Functions of file
|
|
descriptors available to the two processes (child- or parent-) may easily get
|
|
mixed up. To prevent bookkeeping errors, the bookkeeping may be properly set
|
|
up once, to be hidden therafter inside a class like the tt(Pipe) class
|
|
developed here. Let's have a look at its characteristics (before using
|
|
functions like tt(pipe) and tt(dup) the compiler must have read the
|
|
tthi(unistd.h) header file):
|
|
itemization(
|
|
it() The tt(pipe) system call expects a pointer to two tt(int) values,
|
|
which will represent, subsequent to the tt(pipe) call, the file descriptor
|
|
used for reading and the file descriptor used for writing, respectively. To
|
|
avoid confusion, the class tt(Pipe) defines an tt(enum) having values
|
|
associating the indices of the array of 2-tt(int)s with symbolic
|
|
constants. The two file descriptors themselves are stored in a data member
|
|
tt(d_fd). Here is the initial section of the class's interface:
|
|
verbinsert(HEAD)(concrete/examples/pipe.h)
|
|
it() The class only needs a default constructor. This constructor
|
|
calls tt(pipe) to create a set of associated file descriptors used for
|
|
accessing both ends of a pipe:
|
|
verbinsert(CONS)(concrete/examples/pipe.cc)
|
|
it() The members tt(readOnly) and tt(readFrom) are used to configure the
|
|
pipe's reading end. The latter function is used when using redirection. It is
|
|
provided with an alternate file descriptor to be used for reading from the
|
|
pipe. Usually this alternate file descriptor is ti(STDIN_FILENO), allowing
|
|
tt(cin) to extract information from the pipe. The former function is merely
|
|
used to configure the reading end of the pipe. It closes the matching writing
|
|
end and returns a file descriptor that can be used to read from the pipe:
|
|
verbinsert(READ)(concrete/examples/pipe.cc)
|
|
it() tt(writeOnly) and two tt(writtenBy) members are available to
|
|
configure the writing end of a pipe. The former function is only used to
|
|
configure the writing end of the pipe. It closes the reading end, and
|
|
returns a file descriptor that can be used for writing to the pipe:
|
|
verbinsert(WRITE)(concrete/examples/pipe.cc)
|
|
For the latter member two overloaded versions are available:
|
|
itemization(
|
|
itt(writtenBy(int fileDescriptor)) is used to configure em(single)
|
|
redirection, so that a specific file descriptor (usually ti(STDOUT_FILENO)
|
|
or ti(STDERR_FILENO)) can be used to write to the pipe;
|
|
itt((writtenBy(int *fileDescriptor, size_t n = 2))) may be used
|
|
to configure em(multiple) redirection, providing an array argument containing
|
|
file descriptors. Information written to any of these file descriptors is
|
|
actually written to the pipe.
|
|
)
|
|
it() The class has one private data member, tt(redirect), used to set up
|
|
redirection through the ti(dup2) system call. This function expects two file
|
|
descriptors. The first file descriptor represents a file descriptor that can
|
|
be used to access the device's information; the second file descriptor is an
|
|
alternate file descriptor that may also be used to access the device's
|
|
information. Here is tt(redirect)'s implementation:
|
|
verbinsert(REDIRECT)(concrete/examples/pipe.cc)
|
|
)
|
|
Now that redirection can be configured easily using one or more tt(Pipe)
|
|
objects, we'll use tt(Fork) and tt(Pipe) in various example programs.
|