process |
Use the os_process
class to create, suspend, resume, interrupt, and terminate a process. When an os_process
object is created, the current process spawns a child and stores the child's PID
in the os_process object.
The current process and its child
execute concurrently. To force the current process to wait until one of its
child processes terminates, use one of the wait()
family of functions described in process_status
.
This section illustrates
approaches to constructing a child process and provides examples of several uses
for the os_process class.
Examples in this section illustrate two approaches to constructing a child process: the traditional approach and the constructor-based approach.
Platform<ToolKit> for
UNIX supports the traditional method of creating a child process. If you send fork()
to the current process, it returns the parent
process PID to the child and returns the child process PID to the parent. The
following example illustrates this technique.
#include <iostream>
#include <ospace/unix.h>
int
main()
{
os_unix_toolkit initialize;
cout << "Parent process is " << os_this_process::pid() << endl;
// Fork the old-fashioned way.
os_process process = os_this_process::fork();
if (process == os_this_process::parent())
{
cout << "Child with pid " << os_this_process::pid () << endl;;
}
else
{
cout << "Parent with pid " << os_this_process::pid() << endl;
}
return 0;
}
Parent process is 281
Child with pid 282
Parent with pid 281
For clarity, we recommend
using the following constructor-based approach for creating processes
whenever possible. In the following example, the constructor for os_process
automatically invokes a fork() on the current
process, storing the child PID in the new os_process
object.
If you want to control a
process and you know its PID, you can refer to the process by constructing a
process object with that PID. The os_process
class also defines an operator pid_t() , so you
can pass a process into any routine expecting a pid_t
.
The following example also
illustrates how to pass a process into any
routine expecting a pid_t , and determines
whether or not a process exists by sending it the message valid()
.
#include <iostream>
#include <ospace/unix.h>
int
main()
{
os_unix_toolkit initialize;
os_process child1; // Construct a process with an undefined PID.
cout << "child1,child1.valid() = ";
cout << child1 << ", " << child1.valid() << endl;
os_process child2( "/bin/sh", "sleep 10" ); // Execute a program.
cout << "child2,child2.valid() = ";
cout << child2 << ", " << child2.valid() << endl;
int pid = child2.pid(); // Get the program's pid.
cout << "pid of child2 = " << pid << endl;
os_process process( pid ); // Associate object with existing PID.
process.suspend(); // Suspend the process.
kill( child2, SIGKILL ); // Now kill it; illustrate operator pid_t().
os_this_process::wait_for_child( child2 );
cout << "child2,child2.valid() = ";
cout << child2 << ", " << child2.valid() << endl;
return 0;
}
child1,child1.valid() = os_process( -1 ), 0
child2,child2.valid() = os_process( 295 ), 1
pid of child2 = 295
child2,child2.valid() = os_process( 295 ), 0
There are several ways to construct a process object.
The next four examples illustrate the construction of a process object that executes one of the following.
Use the shell name and the name of the command to construct a process object. The following example spawns a child process to execute Bourne shell commands.
#include <iostream>
#include <ospace/unix.h>
int
main()
{
os_unix_toolkit initialize;
os_process child( "/bin/sh", "a=4; echo $a" );
os_this_process::wait_for_child( child );
return 0;
}
4
Use the program name and an
optional null-terminated argument list to execute a named program with
arguments. The following example spawns a child to execute a date
-u command using a null-terminated
argument list.
#include <iostream>
#include <ospace/unix.h>
int
main()
{
os_unix_toolkit initialize;
// Spawn child using null terminated argument list.
os_process child( "date", "-u", 0 );
os_this_process::wait_for_child( child );
return 0;
}
Wed Sep 27 19:07:44 GMT 1995
Use the program name and an optional null-terminated argument array to execute a named program with arguments. The following example is identical to the previous example with one exception: this example uses a null-terminated argument array instead of a null-terminated argument list.
#include <iostream>
#include <ospace/unix.h>
int
main()
{
os_unix_toolkit initialize;
char* argv[ 3 ];
argv[ 0 ] = "date"; // Name of program.
argv[ 1 ] = "-u"; // Argument causes GMT to be displayed.
argv[ 2 ] = 0; // Null terminate the argument vector.
// Supply name of program + argument vector.
os_process child( "date", argv );
os_this_process::wait_for_child( child );
return 0;
}
Wed Sep 27 19:08:08 GMT 1995
Use a pointer to the function and an optional null-terminated argument list or null-terminated array of arguments to construct the process. The following examples creates a child process to execute a function with two arguments.
#include <iostream>
#include <ospace/unix.h>
int
function( int argc, const char* argv[] )
{
for (int i = 0; i < argc; i++) // Display input arguments.
cout << argv[ i ] << endl;
return 0;
}
int
main()
{
os_unix_toolkit initialize;
os_process child( function, "hi", "there", 0 );
os_this_process::wait_for_child( child );
return 0;
}
hi
there
The following example
illustrates output indirection. The child process
executes the date utility and sends its
standard output and errors to the file process5.out.
#include <iostream>
#include <ospace/file.h>
#include <ospace/unix.h>
int
main()
{
os_file_toolkit init_file;
os_unix_toolkit init_unix;
os_file file( "process5.out", O_CREAT | O_WRONLY );
os_process child( os_nil_env, os_nil_desc, file, file, "date" );
return 0;
}
Following is the content of the output file process5.out.
Wed Sep 27 14:08:46 CDT 1995
A process can spawn multiple
child processes to perform a variety of tasks. This section provides two
powerful examples of os_process .
The following example uses an
unnamed pipe to send a sequence of numbers to the sort
utility and uses another unnamed pipe to read back
the results. You can use this technique to create programmatic interfaces to
many utilities. For information about unnamed pipes, see Pipes
for the UNIX Environment
#include <iostream>
#include <ospace/unix.h>
int
main()
{
os_unix_toolkit initialize;
os_unnamed_pipe send;
os_unnamed_pipe receive;
// Spawn child to sort four numbers.
os_process child
(
os_nil_env,
send.read_end(),
receive.write_end(),
receive.write_end(),
"sort", "-n", 0
);
send.write( "5\n10\n4\n7\n", 9 ); // Send four numbers to be sorted.
send.close(); // End-of-input.
char buffer[ 10 ];
int bytes;
// Receive and display results.
while ( (bytes = receive.read( buffer, 10 )) > 0)
{
buffer[ bytes ] = 0;
cout << buffer << endl;
}
return 0;
}
4
5
7
10
In the following example, the first child process inherits its environment from its parent, whereas the second child receives a different environment.
#include <iostream>
#include <ospace/unix.h>
int
child_function()
{
os_environment env = os_this_process::environment();
os_environment::const_iterator i;
cout << "Environment: " << endl;
for ( i = env.begin(); i != env.end(); i++ )
cout << " " << (*i).first << " = " << (*i).second << endl;
return 0;
}
int
main()
{
os_unix_toolkit initialize;
cout << "Child1's output:" << endl;
os_process child1
(
os_nil_env, // Inherit parent's environment.
os_nil_desc,
os_nil_desc,
os_nil_desc,
child_function
);
os_this_process::wait_for_child( child1 );
os_environment child_env;
child_env[ "CAT" ] = "Smokey";
cout << "Child2's output:" << endl;
os_process child2
(
&child_env, // Pass new environment to child.
os_nil_desc,
os_nil_desc,
os_nil_desc,
child_function
);
os_this_process::wait_for_child( child2 );
return 0;
}
Child1's output:
Environment:
HOSTTYPE = sparc
HISTFILE = /nestegg0/users/fred/.history
...
PATH = /usr/ucb:/usr/bin:/usr/etc
...
Child2's output:
Environment:
CAT = Smokey
Copyright©1994-2026 Recursion
Software LLC
All Rights Reserved - For use by licensed users only.