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.

Constructing a Child Process

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.

Example <ospace/unix/examples/process8.cpp>
#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() .

Example <ospace/unix/examples/process9.cpp>
#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

Constructing Process Objects

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.

Example <ospace/unix/examples/process1.cpp>
#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.

Example <ospace/unix/examples/process2.cpp>
#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.

Example <ospace/unix/examples/process3.cpp>
#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.

Example <ospace/unix/examples/process4.cpp>
#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.

Example <ospace/unix/examples/process5.cpp>
#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

Redirecting Standard I/O to Child Processes

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

Example <ospace/unix/examples/process6.cpp>
#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

Changing the Environment in Child Processes

In the following example, the first child process inherits its environment from its parent, whereas the second child receives a different environment.

Example <ospace/unix/examples/process7.cpp>
#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.