Document revision date: 19 July 1999
[Compaq] [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]
[OpenVMS documentation]

OpenVMS Programming Concepts Manual


Previous Contents Index

1.4.1 Using LIB$SPAWN to Create a Spawned Subprocess

The LIB$SPAWN routine enables you to create a subprocess and to set some context options for the new subprocess. LIB$SPAWN creates a subprocess with the same priority as the parent process (generally priority 4). The format for LIB$SPAWN is:

LIB$SPAWN ([command_string],[input_file],
,[output_file],[flags],[process-name],[process_id],[completion_status]
,[completion_efn],[completion_astadr],[completion_astarg],[prompt],[cli])

For complete information on using each argument, refer to the LIB$SPAWN routine in OpenVMS RTL Library (LIB$) Manual.

Specifying a Command String

Use the command_string argument to specify a single DCL command to execute once the subprocess is initiated. You can also use this argument to execute a command procedure that, in turn, executes several DCL commands (@command_procedure_name).

Redefining SYS$INPUT and SYS$OUTPUT

Use the input_file and output_file arguments to specify alternate input and output devices for SYS$INPUT and SYS$OUTPUT. Using alternate values for SYS$INPUT and SYS$OUTPUT can be particularly useful when you are synchronizing processes that are executing concurrently.

Passing Parent Process Context Information to the Subprocess

Use the flags argument to specify which characteristics of the parent process are to be passed on to the subprocess. With this argument, you can reduce the time required to create a subprocess by passing only a part of the parent's context. You can also specify whether the parent process should continue to execute (execute concurrently) or wait until the subprocess has completed execution (execute in line).

After the Subprocess Completes Execution

Use the completion_status, completion_efn, and completion_astadr arguments to specify the action to be taken when the subprocess completes execution (send a completion status, set a local event flag, or invoke an AST procedure). For more information about event flags and ASTs, refer to Chapter 5.

The LIB$SPAWN routine and SPAWN command do not return a completion status code of 0 from a subprocess command procedure.

Specifying an Alternate Prompt String

Use the prompt argument to specify a prompt string for the subprocess.

Specifying an Alternate Command Language Interpreter

Use the cli argument to specify a command language interpreter for the subprocess.

Examples of Creating Subprocesses

The following example creates a subprocess that executes the commands in the COMMANDS.COM command procedure, which must be a command procedure on the current default device in the current default directory. The created subprocess inherits symbols, logical names (including SYS$INPUT and SYS$OUTPUT), keypad definitions, and other context information from the parent. The subprocess executes while the parent process hibernates.


! Declare status and library routine 
INTEGER STATUS, LIB$SPAWN 
 
STATUS = LIB$SPAWN ('@COMMANDS') 

The following Fortran program segment creates a subprocess that does not inherit the parent's symbols, logical names, or keypad definitions. The subprocess reads and executes the commands in the COMMANDS.COM command procedure. (The CLI$symbols are defined in the $CLIDEF module of the system object or in shareable image library. See Chapter 19 for more information.)


! Mask for LIB$SPAWN 
INTEGER MASK 
EXTERNAL CLI$M_NOCLISYM, 
2        CLI$M_NOLOGNAM, 
2        CLI$M_NOKEYPAD 
! Declare status and library routine 
INTEGER STATUS, LIB$SPAWN 
 
! Set mask and call LIB$SPAWN 
MASK = %LOC(CLI$M_NOCLISYM) .OR. 
2      %LOC(CLI$M_NOLOGNAM) .OR. 
2      %LOC(CLI$M_NOKEYPAD) 
 
STATUS = LIB$SPAWN ('@COMMANDS.COM', 
2                   ,, 
2                   MASK) 

The following Fortran program segment creates a subprocess to execute the image $DISK1:[USER.MATH]CALC.EXE. CALC reads data from DATA84.IN and writes the results to DATA84.RPT. The subprocess executes concurrently. (CLI$M_NOWAIT is defined in the $CLIDEF module of the system object or shareable image library; see Chapter 19.)


! Mask for LIB$SPAWN 
EXTERNAL CLI$M_NOWAIT 
! Declare status and library routine 
INTEGER STATUS, LIB$SPAWN 
 
STATUS = LIB$SPAWN ('RUN $DISK1:[USER.MATH]CALC', ! Image 
2                   'DATA84.IN',                  ! Input 
2                   'DATA84.RPT',                 ! Output 
2                   %LOC(CLI$M_NOWAIT))           ! Concurrent 

1.4.2 Using PPL$SPAWN to Create a Spawned Subprocess

The PPL$SPAWN routine works similarly to LIB$SPAWN in that it creates one or more subprocesses with the same context as the parent process on the same node (or system) as the parent process. You can specify the name of an image to be executed in the subprocess. However, you should limit use of PPL$SPAWN to creating subprocesses specifically for parallel processing.

Before using PPL$SPAWN, you must set up special PPL$ data structures with the PPL$INITIALIZE routine; otherwise, unpredictable results may occur. Also, after you create a process with PPL$CREATE_PROCESS and the process has completed its activity, you must explicitly delete it with PPL$STOP.

For more information about using these PPL$ routines, see the OpenVMS RTL Parallel Processing (PPL$) Manual.

1.4.3 Using SYS$CREPRC to Create a Subprocess

The Create Process (SYS$CREPRC) system service creates both subprocesses and detached processes. This section discusses creating a subprocess; Section 1.5 describes creating a detached process. When you call the SYS$CREPRC system service to create a process, you define the context by specifying arguments to the service. The number of subprocesses a process can create is controlled by its PQL$_PRCLM subprocess quota, an individual quota description under the quota argument. The DETACH privilege controls your ability to create a detached process with a user identification code (UIC) that is different from the UIC of the creating process.

With SYS$CREPRC, you must usually specify the priority because the default priority is zero. Though SYS$CREPRC does not set many context values for the subprocess by default, it does allow you to set many more context values than LIB$SPAWN. For example, you cannot specify separate privileges for a subprocess with LIB$SPAWN directly, but you can with SYS$CREPRC.

By default, SYS$CREPRC creates a subprocess rather than a detached process. The format for SYS$CREPRC is as follows:

SYS$CREPRC ([pidadr] ,[image] ,[input] ,[output] ,[error] ,[prvadr] ,[quota]
,[prcnam] ,[baspri] ,[uic] ,[mbxunt] ,[stsflg] ,[itemlst] ,[node])

Ordinarily, when you create a subprocess, you need only assign it an image to execute and, optionally, the SYS$INPUT, SYS$OUTPUT, and SYS$ERROR devices. The system provides default values for the process's privileges, resource quotas, execution modes, and priority. In some cases, however, you may want to define these values specifically. The arguments to the SYS$CREPRC system service that control these characteristics follow. For details, see the descriptions of arguments to the SYS$CREPRC system service in the OpenVMS System Services Reference Manual.

The default values passed into the subprocess might not be complete enough for your use. The following sections describe how to modify these default values with SYS$CREPRC.

Redefining SYS$INPUT, SYS$OUTPUT, and SYS$ERROR

Use the input, output, and error arguments to specify alternate input, output, and error devices for SYS$INPUT, SYS$OUTPUT, and SYS$ERROR. Using alternate values for SYS$INPUT, SYS$OUTPUT, and SYS$ERROR can be particularly useful when you are synchronizing processes that are executing concurrently. By providing alternate or equivalent names for the logical names SYS$INPUT, SYS$OUTPUT, and SYS$ERROR, you can place these logical name/equivalence name pairs in the process logical name table for the created process.

The following C program segment is an example of defining input, output, and error devices for a subprocess:


#include <stdio.h> 
#include <ssdef.h> 
#include <descrip.h> 
 
main() { 
 
 unsigned int status; 
 
 $DESCRIPTOR(input,"SUB_MAIL_BOX");   /* Descriptor for input stream */ 
 $DESCRIPTOR(output,"COMPUTE_OUT");   /* Descriptor for output and error*/ 
                                      /* streams */ 
 $DESCRIPTOR(image,"COMPUTE.EXE");    /* Descriptor for image name */ 
 
 /* Create the subprocess */ 
 status = SYS$CREPRC( 0,              /* process id */ 
                      &image,         /* image */ 
                      &input,  (1)   /* input SYS$INPUT device */ 
                      &output, (2)   /* output SYS$OUTPUT device*/ 
                      &output, (3)   /* error SYS$ERROR device*/ 
                      0,0,0,0,0,0,0); 
 
} 

  1. The input argument equates the equivalence name SUB_MAIL_BOX to the logical name SYS$INPUT. This logical name may represent a mailbox that the calling process previously created with the Create Mailbox and Assign Channel (SYS$CREMBX) system service. Any input the subprocess reads from the logical device SYS$INPUT is read from the mailbox.
  2. The output argument equates the equivalence name COMPUTE_OUT to the logical name SYS$OUTPUT. All messages the program writes to the logical device SYS$OUTPUT are written to this file.
  3. The error argument equates the equivalence name COMPUTE_OUT to the logical name SYS$ERROR. All system-generated error messages are written into this file. Because this is the same file as that used for program output, the file effectively contains a complete record of all output produced during the execution of the program image.

The SYS$CREPRC system service does not provide default equivalence names for the logical names SYS$INPUT, SYS$OUTPUT, and SYS$ERROR. If none are specified, any entries in the group or system logical name tables, if any, may provide equivalences. If, while the subprocess executes, it reads or writes to one of these logical devices and no equivalence name exists, an error condition results.

In a program that creates a subprocess, you can cause the subprocess to share the input, output, or error device of the creating process. You must first follow these steps:

  1. Use the Get Device/Volume Information (SYS$GETDVI) system service to obtain the device name for the logical name SYS$INPUT, SYS$OUTPUT, or SYS$ERROR.
  2. Specify the address of the descriptor returned by the SYS$GETDVI service when you specify the input, output, or error argument to the SYS$CREPRC system service.

This procedure is illustrated in the following example:


#include <stdio.h> 
#include <ssdef.h> 
#include <prcdef.h> 
#include <dvidef.h> 
#include <descrip.h> 
 
/* Item list to return device name */ 
 
struct { 
        unsigned short buflen, item_code; 
        void *bufaddr; 
        void *retlenaddr; 
        unsigned int terminator; 
}itm_lst; 
 
 
main() { 
 
        char term[64]; 
        unsigned int baspri=4, status, *termlen; 
 
/* Descriptors for SYS$GETDVI */ 
        $DESCRIPTOR(lognam,"SYS$INPUT"); 
 
/* Descriptors for SYS$CREPRC */ 
        $DESCRIPTOR(image,"SYS$SYSTEM:LOGINOUT.EXE"); 
        $DESCRIPTOR(termdesc, term); 
 
/* Assign values to the item list */ 
 
itm_lst.buflen = 64; 
itm_lst.item_code = DVI$_DEVNAM; 
itm_lst.bufaddr = term; 
itm_lst.retlenaddr = &termlen; 
itm_lst.terminator = 0; 
 
/* Determine the terminal name */ 
 
status = SYS$GETDVI(0,                  /* efn (event flag) */ 
                    0,                  /* channel */ 
                    &lognam,            /* devnam */ 
                    &itm_lst,           /* item list */ 
                    0,0,0,0); 
 
if((status & 1) != 1) 
                    LIB$SIGNAL( status ); 
 
/* Create the subprocess */ 
 
status = SYS$CREPRC( 0, &image,         /* image to be run */ 
                     &termdesc,         /* input (SYS$INPUT device) */ 
                     &termdesc,         /* output (SYS$OUTPUT device) */ 
                     &termdesc,         /* error (SYS$ERROR device) */ 
                     0,0,0, 
                     &baspri,           /* base priority */ 
                     0,0,0); 
     if((status & 1) != 1) 
                     LIB$SIGNAL( status ); 
 
} 

In this example, the subprocess executes, and the logical names SYS$INPUT, SYS$OUTPUT, and SYS$ERROR are equated to the device name of the creating process's logical input device. The subprocess can then do one of the following:

In the following example, the program assigns a channel to the device specified by the logical name SYS$OUTPUT:


 
        unsigned int status; 
        unsigned short chan; 
        $DESCRIPTOR(devnam,"SYS$OUTPUT"); 
   .
   .
   .
        status = SYS$ASSIGN( &devnam,           /* Device name */ 
                             &chan,             /* Channel */ 
                             0, 0, 0); 

For more information about channel assignment for I/O operations, see Chapter 11.

Setting Privileges

Set different privileges by defining the privilege list for the subprocess using the prvadr argument. This is particularly useful when you want to dedicate a subprocess to execute privileged or sensitive code. If you do not specify this argument, the privileges of the calling process are used. If you specify the prvadr argument, only the privileges specified in the bit mask are used; the privileges of the calling process are not used. For example, a creating process has the user privileges GROUP and TMPMBX. It creates a process, specifying the user privilege TMPMBX. The created process receives only the user privilege TMPMBX; it does not have the user privilege GROUP.

If you need to create a process that has a privilege that is not one of your current process's privileges, you must have the user privilege SETPRV.

Symbols associated with privileges are defined by the $PRVDEF macro. Each symbol begins with PRV$V_ and identifies the bit number that must be set to specify a given privilege. The following example shows the data definition for a bit mask specifying the GRPNAM and GROUP privileges:


struct { 
    unsigned int privs = PRV$M_GRPNAM || PRV$M_GROUP; 
    unsigned int terminator; 
}prvmsk; 

Setting Process Quotas

Set different process quotas by defining the quota list of system resources for the subprocess using the quota argument. This option can be useful when managing a subprocess to limit use of system resources (such as AST usage, I/O, CPU time, lock requests, and working set size and expansion). If you do not specify this argument, the system defines default quotas for the subprocess.

Setting the Subprocess Priority

Set the subprocess priority by setting the base execution priority with the baspri argument. If you do not set the subprocess priority, the priority defaults to 2 for VAX MACRO and VAX BLISS--32 and to 0 for all other languages. If you want a subprocess to have a higher priority than its creator, you must have the user privilege ALTPRI to raise the priority level.

Specifying Additional Processing Options

Enable and disable parent and subprocess wait mode, control process swapping, control process accounting, control process dump information, control authorization checks, and control working set adjustments using the stsflg argument. This argument defines the status flag, a set of bits that control some execution characteristics of the created process, including resource wait mode and process swap mode.

Defining an Image for a Subprocess to Execute

When you call the SYS$CREPRC system service, use the image argument to provide the process with the name of an image to execute. For example, the following lines of C create a subprocess to execute the image named CARRIE.EXE:


        $DESCRIPTOR(image,"CARRIE"); 
   .
   .
   .
        status = SYS$CREPRC(0, &image, ...); 

In this example, only a file name is specified; the service uses current disk and directory defaults, performs logical name translation, uses the default file type .EXE, and locates the most recent version of the image file. When the subprocess completes execution of the image, the subprocess is deleted. Process deletion is described in Chapter 3.

1.4.3.1 Disk and Directory Defaults for Created Processes

When you use the SYS$CREPRC system service to create a process to execute an image, the system locates the image file in the default device and directory of the created process. Any created process inherits the current default device and directory of its creator.

If a created process runs an image that is not in its default directory, you must identify the directory and, if necessary, the device in the file specification of the image to be run.

There is no way to define a default device or directory for the created process that is different from that of the creating process in a call to SYS$CREPRC. The created process can, however, define an equivalence for the logical device SYS$DISK by calling the Create Logical Name ($CRELNM) system service.

If the process is a subprocess, you, in the creating process, can define an equivalence name in the group logical name table, job logical name table, or any logical name table shared by the creating process and the subprocess. The created process then uses this logical name translation as its default directory. The created process can also set its own default directory by calling the OpenVMS RMS default directory system service, SYS$SETDDIR.

A process can create a process with a default directory that is different from its own by completing the following steps in the creating process:

  1. Make a call to SYS$SETDDIR to change its own default directory.
  2. Make a call to SYS$CREPRC to create the new process.
  3. Make a call to SYS$SETDDIR to change its own default directory back to the default directory it had before the first call to SYS$SETDDIR.

The creating process now has its original default directory. The new process has the different default directory that the creating process had when it created the new process. For details on how to call SYS$SETDDIR, see the OpenVMS System Services Reference Manual.

1.4.4 Debugging Within a Subprocess

You can allow a program to be debugged within a subprocess. To allow debug operations, equate the subprocess logical names DBG$INPUT and DBG$OUTPUT to the terminal. When the subprocess executes the program, which has been compiled and linked with the debugger, the debugger reads input from DBG$INPUT and writes output to DBG$OUTPUT.

If you are executing the subprocess concurrently, you should restrict debugging to the program in the subprocess. The debugger prompt DBG> should enable you to differentiate between input required by the parent process and input required by the subprocess. However, each time the debugger displays information, you must press the Return key to display the DBG> prompt. (By pressing the Return key, you actually write to the parent process, which has regained control of the terminal following the subprocess's writing to the terminal. Writing to the parent process allows the subprocess to regain control of the terminal.)

1.5 Creating a Detached Process

The creation of a detached process is primarily a task the operating system performs when you log in. In general, an application creates a detached process only when a program must continue executing after the parent process exits. To do this, you should use the SYS$CREPRC system service. You can also use detached processes to write to another process's terminal by using the SYS$BREAKTHRU system service.

The DETACH privilege controls the ability to create a detached process with a UIC that is different from the UIC of the creating process. You can use the uic argument to the SYS$CREPRC system service to define whether a process is a subprocess or a detached process. The uic argument provides the created process with a user identification code (UIC). If you omit the uic argument, the SYS$CREPRC system service creates a subprocess that executes under the UIC of the creating process.

You can also create a detached process with the same UIC as the creating process by specifying the detach flag in the stsflg argument. You do not need the DETACH privilege to create a detached process with the same UIC as the creating process.

Examples of Creating a Detached Process

The following Fortran program segment creates a process that executes the image SYS$USER:[ACCOUNT]INCTAXES.EXE. INCTAXES reads input from the file TAXES.DAT and writes output to the file TAXES.RPT. (TAXES.DAT and TAXES.RPT are in the default directory on the default disk.) The last argument specifies that the created process is a detached process (the UIC defaults to that of the parent process). (The symbol PRC$M_DETACH is defined in the $PRCDEF module of the system macro library.)


EXTERNAL  PRC$M_DETACH 
 
! Declare status and system routines 
INTEGER STATUS,SYS$CREPRC 
   .
   .
   .
STATUS = SYS$CREPRC (, 
2                    'SYS$USER:[ACCOUNT]INCTAXES', ! Image 
2                    'TAXES.DAT',                  ! SYS$INPUT 
2                    'TAXES.RPT',                  ! SYS$OUTPUT 
2                    ,,,, 
2                    %VAL(4),                      ! Priority 
2                    ,, 
2                    %VAL(%LOC(PRC$M_DETACH)))     ! Detached 

The following program segment creates a detached process to execute the DCL commands in the command file SYS$USER:[TEST]COMMANDS.COM. The system image SYS$SYSTEM:LOGINOUT.EXE is executed to include DCL in the created process. The DCL commands to be executed are specified in a command procedure that is passed to SYS$CREPRC as the input file. Output is written to the file SYS$USER:[TEST]OUTPUT.DAT.


   .
   .
   .
STATUS = SYS$CREPRC (, 
2                    'SYS$SYSTEM:LOGINOUT',        ! Image 
2                    'SYS$USER:[TEST]COMMANDS.COM',! SYS$INPUT 
2                    'SYS$USER:[TEST]OUTPUT.DAT',  ! SYS$OUTPUT 
2                    ,,,, 
2                    %VAL(4),                      ! Priority 
2                    ,, 
2                    %VAL(%LOC(PRC$M_DETACH)))     ! Detached 


Previous Next Contents Index

  [Go to the documentation home page] [How to order documentation] [Help on this site] [How to contact us]  
  privacy and legal statement  
5841PRO_001.HTML