[an error occurred while processing this directive]

HP OpenVMS Systems Documentation

Content starts here

HP OpenVMS Programming Concepts Manual


Previous Contents Index

4.1.1 Determining Privileges for Process Creation and Control

There are three levels of process control privilege:

  • Processes with the same UIC can always issue process control services for one another.
  • You need the GROUP privilege to issue process control services for other processes executing in the same group.
  • You need the WORLD privilege to issue process control services for any process in the system.

You need additional privileges to perform some specific functions; for example, raising the base priority of a process requires ALTPRI privilege.

4.1.2 Determining Process Identification

There are two types of process identification:

  • Process identification (PID) number
    The system assigns this unique 32-bit number to a process when it is created. If you provide the pidadr argument to the SYS$CREPRC system service, the system returns the process identification number at the location specified. You can then use the process identification number in subsequent process control services.

  • Process name
    There are two types of process names:
    • Process name
      A process name is a 1- to 15-character name string. Each process name must be unique within its group (processes in different groups can have the same name). You can assign a name to a process by specifying the prcnam argument when you create it. You can then use this name to refer to the process in other system service calls. Note that you cannot use a process name to specify a process outside the caller's group; you must use a process identification (PID) number.
    • Full process name
      The full process name is unique for each process in the cluster. Full process name strings can be up to 23 characters long and are configured in the following way:
      1--6 characters for the node name
      2 characters for the colons (::) that follow the node name
      1--15 characters for the local process name

For example, you could call the SYS$CREPRC system service, as follows:


unsigned int orionid=0, status;
$DESCRIPTOR(orion,"ORION");
   .
   .
   .
status = SYS$CREPRC(&orionid,           /* pidadr (process id returned) */
                    &orion,             /* prcnam  - process name */
                ...);

The service returns the process identification in the longword at ORIONID. You can now use either the process name (ORION) or the PID (ORIONID) to refer to this process in other system service calls.

A process can set or change its own name with the Set Process Name ($SETPRN) system service. For example, a process can set its name to CYGNUS, as follows:


/* Descriptor for process name */
        $DESCRIPTOR(cygnus,"CYGNUS");

        status = SYS$SETPRN( &cygnus );   /* prcnam -  process name */

Most of the process control services accept the prcnam or the pidadr argument or both. However, you should identify a process by its process identification number for the following reasons:

  • The service executes faster because it does not have to search a table of process names.
  • For a process not in your group, you must use the process identification number (see Section 4.1.3).

If you specify the PID address, the service uses the PID address. If you specify the process name without a PID address, the sevice uses the process name. If you specify both---the process name and PID address---it uses the PID address unless the contents of the PID is 0. In that case, the service uses the process name. If you specify a PID address of 0 without a process name, then the service is performed for the calling process.

If you specify neither the process name argument nor the process identification number argument, the service is performed for the calling process. If the PID address is specified, the service returns the PID of the target process in it. Table 4-2 summarizes the possible combinations of these arguments and explains how the services interpret them.

Table 4-2 Process Identification
Process
Name
Specified?
PID
Address
Specified?
Contents of
PID
Resultant
Action
by Services
No No -- The process identification of the calling process is used, but is not returned.
No Yes 0 The process identification of the calling process is used and returned.
No Yes PID The process identification is used and returned.
Yes No -- The process name is used. The process identification is not returned.
Yes Yes 0 The process name is used and the process identification is returned.
Yes Yes PID The process identification is used and returned; the process name is ignored.

4.1.3 Qualifying Process Naming Within Groups

Process names are always qualified by their group number. The system maintains a table of all process names and the UIC associated with each. When you use the prcnam argument in a process control service, the table is searched for an entry that contains the specified process name and the group number of the calling process.

To use process control services on processes within its group, a calling process must have the GROUP user privilege; this privilege is not required when you specify a process with the same UIC as the caller.

The search for a process name fails if the specified process name does not have the same group number as the caller. The search fails even if the calling process has the WORLD user privilege. To execute a process control service for a process that is not in the caller's group, the requesting process must use a process identification and must have the WORLD user privilege.

4.2 Obtaining Process Information

The operating system's process information procedures enable you to gather information about processes and kernel threads. You can obtain information about either one process or a group of processes on either the local system or on remote nodes in an OpenVMS Cluster system. You can also obtain process lock information. DCL commands such as SHOW SYSTEM and SHOW PROCESS use the process information procedures to display information about processes. You can also use the process information procedures within your programs.

The following are process information procedures:

  • Get Job/Process Information (SYS$GETJPI(W))
  • Get Job/Process Information (LIB$GETJPI)
  • Process Scan (SYS$PROCESS_SCAN)
  • Get Lock Information (SYS$GETLKI)

The SYS$GETJPI(W) and SYS$PROCESS_SCAN system services can also be used to get kernel threads information. SYS$GETJPI(W) can request threads information from a particular process ID or process name. SYS$PROCESS_SCAN can request information about all threads in a process, or all threads for each multithreaded process on the system.

For more information about SYS$GETJPI, SYS$PROCESS_SCAN, and SYS$GETLKI, see the HP OpenVMS System Services Reference Manual.

The differences among these procedures are as follows:

  • SYS$GETJPI operates asynchronously.
  • SYS$GETJPIW and LIB$GETJPI operate synchronously.
  • SYS$GETJPI and SYS$GETJPIW can obtain one or more pieces of information about a process or kernel thread in a single call.
  • LIB$GETJPI can obtain only one piece of information about a process or kernel thread in a single call.
  • SYS$GETJPI and SYS$GETJPIW can specify an AST to execute at the completion of the routine.
  • SYS$GETJPI and SYS$GETJPIW can use an I/O status block (IOSB) to test for completion of the routine.
  • LIB$GETJPI can return some items either as strings or as numbers. It is often the easiest to call from a high-level language because the caller is not required to construct an item list.
  • SYS$GETLKI returns information about the lock database.

4.2.1 Using the PID to Obtain Information

The process information procedures return information about processes by using the process identification (PID) or the process name. The PID is a 32-bit number that is unique for each process in the cluster. Specify the PID by using the pidadr argument. You must specify all the significant digits of a PID; you can omit leading zeros.

With kernel threads, the PID continues to identify a process, but it can also identify a kernel thread within that process. In a multithreaded process each kernel thread has its own PID that is based on the initial threads PID.

4.2.2 Using the Process Name to Obtain Information

To obtain information about a process using the process name, specify the prcnam argument. Although a PID is unique for each process in the cluster, a process name is unique (within a UIC group) only for each process on a node. To locate information about processes on the local node, specify a process name string of 1 to 15 characters. To locate information about a process on a particular node, specify the full process name, which can be up to 23 characters long. The full process name is configured in the following way:

  • 1 to 6 characters for the node name
  • 2 characters for the colons (::) that follow the node name
  • 1 to 15 characters for the local process name

Note that a local process name can look like a remote process name. Therefore, if you specify ATHENS::SMITH, the system checks for a process named ATHENS::SMITH on the local node before checking node ATHENS for a process named SMITH.

Chapter 17 and the HP OpenVMS System Services Reference Manual describe these routines completely, listing all items of information that you can request. LIB$GETJPI, SYS$GETJPI, and SYS$GETJPIW share the same item codes with the following exception: LIB$K_ items can be accessed only by LIB$GETJPI.

In the following example, the string argument rather than the numeric argument is specified, causing LIB$GETJPI to return the UIC of the current process as a string:


! Define request codes
INCLUDE '($JPIDEF)'

! Variables for LIB$GETJPI
CHARACTER*9 UIC
INTEGER LEN

STATUS = LIB$GETJPI (JPI$_UIC,
2                    ,,,
2                    UIC,
2                    LEN)

To specify a list of items for SYS$GETJPI or SYS$GETJPI(W) (even if that list contains only one item), use a record structure. Example 4-1 uses SYS$GETJPI(W) to request the process name and user name associated with the process whose process identification number is in SUBPROCESS_PID.

Example 4-1 Obtaining Different Types of Process Information

   .
   .
   .
! PID of subprocess
INTEGER SUBPROCESS_PID

! Include the request codes
INCLUDE '($JPIDEF)'
! Define itmlst structure
STRUCTURE /ITMLST/
 UNION
  MAP
   INTEGER*2 BUFLEN
   INTEGER*2 CODE
   INTEGER*4 BUFADR
   INTEGER*4 RETLENADR
  END MAP
  MAP
   INTEGER*4 END_LIST
  END MAP
 END UNION
END STRUCTURE
! Declare GETJPI itmlst
RECORD /ITMLST/ JPI_LIST(3)
! Declare buffers for information
CHARACTER*15    PROCESS_NAME
CHARACTER*12    USER_NAME
INTEGER*4       PNAME_LEN,
2               UNAME_LEN
! Declare I/O status structure
STRUCTURE /IOSB/
 INTEGER*2 STATUS,
2          COUNT
 INTEGER*4 %FILL
END STRUCTURE
! Declare I/O status variable
RECORD /IOSB/ JPISTAT
! Declare status and routine
INTEGER*4       STATUS,
2               SYS$GETJPIW
                   .
                   . ! Define SUBPROCESS_PID
                   .
! Set up itmlst
JPI_LIST(1).BUFLEN    = 15
JPI_LIST(1).CODE      = JPI$_PRCNAM
JPI_LIST(1).BUFADR    = %LOC(PROCESS_NAME)
JPI_LIST(1).RETLENADR = %LOC(PNAME_LEN)
JPI_LIST(2).BUFLEN    = 12
JPI_LIST(2).CODE      = JPI$_USERNAME
JPI_LIST(2).BUFADR    = %LOC(USER_NAME)
JPI_LIST(2).RETLENADR = %LOC(UNAME_LEN)
JPI_LIST(3).END_LIST  = 0
! Request information and wait for it
STATUS = SYS$GETJPIW (,
2                     SUBPROCESS_PID,
2                     ,
2                     JPI_LIST,
2                     JPISTAT,
2                     ,)
IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS))
! Check final return status
IF (.NOT. JPISTAT.STATUS) THEN
  CALL LIB$SIGNAL (%VAL(JPISTAT.STATUS))
END IF
   .
   .
   .

4.2.3 Using SYS$GETJPI and LIB$GETJPI

SYS$GETJPI uses the PID or the process name to obtain information about one process and the -1 wildcard as the pidadr to obtain information about all processes on the local system. If a PID or process name is not specified, SYS$GETJPI returns information about the calling process. SYS$GETJPI cannot perform a selective search---it can search for only one process at a time in the cluster or for all processes on the local system. If you want to perform a selective search for information or get information about processes across the cluster, use SYS$GETJPI with SYS$PROCESS_SCAN.

4.2.3.1 Requesting Information About a Single Process

Example 4-2 is a Fortran program that displays the process name and the PID of the calling program. If you want to get the same information about each process on the system, specify the initial process identification argument as -1 when you invoke LIB$GETJPI or SYS$GETJPI(W). Call the GETJPI routine (whichever you choose) repeatedly until it returns a status of SS$_NOMOREPROC, indicating that all processes on the system have been examined.

Example 4-2 Using SYS$GETJPI to Obtain Calling Process Information

! No process name or PID is specified; $GETJPI returns data on the
! calling process.

        PROGRAM CALLING_PROCESS

        IMPLICIT NONE                   ! Implicit none

        INCLUDE '($jpidef)   /nolist'   ! Definitions for $GETJPI

        INCLUDE '($ssdef)    /nolist'    ! System status codes

        STRUCTURE /JPIITMLST/           ! Structure declaration for
         UNION                          !  $GETJPI item lists
          MAP
           INTEGER*2 BUFLEN,
        2            CODE
           INTEGER*4 BUFADR,
        2            RETLENADR
          END MAP
          MAP                           ! A longword of 0 terminates
           INTEGER*4 END_LIST           !  an item list
          END MAP
         END UNION
        END STRUCTURE
        RECORD /JPIITMLST/              ! Declare the item list for
        2         JPILIST(3)            !  $GETJPI

        INTEGER*4 SYS$GETJPIW           ! System service entry points

        INTEGER*4 STATUS,               ! Status variable
        2         PID                   ! PID from $GETJPI

        INTEGER*2 IOSB(4)               ! I/O Status Block for $GETJPI

        CHARACTER*16
        2         PRCNAM                ! Process name from $GETJPI
        INTEGER*2 PRCNAM_LEN            ! Process name length
        ! Initialize $GETJPI item list

        JPILIST(1).BUFLEN    = 4
        JPILIST(1).CODE      = JPI$_PID
        JPILIST(1).BUFADR    = %LOC(PID)
        JPILIST(1).RETLENADR = 0
        JPILIST(2).BUFLEN    = LEN(PRCNAM)
        JPILIST(2).CODE      = JPI$_PRCNAM
        JPILIST(2).BUFADR    = %LOC(PRCNAM)
        JPILIST(2).RETLENADR = %LOC(PRCNAM_LEN)
        JPILIST(3).END_LIST  = 0
        ! Call $GETJPI to get data for this process

        STATUS = SYS$GETJPIW (
        2                    ,           ! No event flag
        2                    ,           ! No PID
        2                    ,           ! No process name
        2                    JPILIST,    ! Item list
        2                    IOSB,       ! Always use IOSB with $GETJPI!
        2                    ,           ! No AST
        2                    )           ! No AST arg
        ! Check the status in both STATUS and the IOSB, if
        ! STATUS is OK then copy IOSB(1) to STATUS

        IF (STATUS) STATUS = IOSB(1)

        ! If $GETJPI worked, display the process, if done then
        ! prepare to exit, otherwise signal an error

        IF (STATUS) THEN
                TYPE 1010, PID, PRCNAM(1:PRCNAM_LEN)
1010                FORMAT (' ',Z8.8,'  ',A)
        ELSE
                CALL LIB$SIGNAL(%VAL(STATUS))
        END IF

        END

Example 4-3 creates the file PROCNAME.RPT that lists, using LIB$GETJPI, the process name of each process on the system. If the process running this program does not have the privilege necessary to access a particular process, the program writes the words NO PRIVILEGE in place of the process name. If a process is suspended, LIB$GETJPI cannot access it and the program writes the word SUSPENDED in place of the process name. Note that, in either of these cases, the program changes the error value in STATUS to a success value so that the loop calling LIB$GETJPI continues to execute.

Example 4-3 Obtaining the Process Name

   .
   .
   .
! Status variable and error codes
INTEGER STATUS,
2       STATUS_OK,
2       LIB$GET_LUN,
2       LIB$GETJPI
INCLUDE '($SSDEF)'
PARAMETER (STATUS_OK = 1)

! Logical unit number and file name
INTEGER*4 LUN
CHARACTER*(*) FILE_NAME
PARAMETER (FILE_NAME = 'PROCNAME.RPT')
! Define item codes for LIB$GETJPI
INCLUDE '($JPIDEF)'

! Process name
CHARACTER*15 NAME
INTEGER LEN
! Process identification
INTEGER PID /-1/
   .
   .
   .
! Get logical unit number and open the file
STATUS = LIB$GET_LUN (LUN)
OPEN (UNIT = LUN,
2     FILE = 'PROCNAME.RPT',
2     STATUS = 'NEW')
! Get information and write it to file
DO WHILE (STATUS)
  STATUS = LIB$GETJPI(JPI$_PRCNAM,
2                     PID,
2                     ,,
2                     NAME,
2                     LEN)
  ! Extra space in WRITE commands is for
  ! FORTRAN carriage control
  IF (STATUS) THEN
    WRITE (UNIT = LUN,
2          FMT = '(2A)') ' ', NAME(1:LEN)
    STATUS = STATUS_OK
  ELSE IF (STATUS .EQ. SS$_NOPRIV) THEN
    WRITE (UNIT = LUN,
2          FMT = '(2A)') ' ', 'NO PRIVILEGE'
    STATUS = STATUS_OK
  ELSE IF (STATUS .EQ. SS$_SUSPENDED) THEN
    WRITE (UNIT = LUN,
2          FMT = '(2A)') ' ', 'SUSPENDED'
    STATUS = STATUS_OK
  END IF

END DO
! Close file
IF (STATUS .EQ. SS$_NOMOREPROC)
2  CLOSE (UNIT = LUN)
   .
   .
   .

Example 4-4 demonstrates how to use the process name to obtain information about a process.

Example 4-4 Using SYS$GETJPI and the Process Name to Obtain Information About a Process

! To find information for a particular process by name,
! substitute this code, which includes a process name,
! to call $GETJPI in Example 4-2

! Call $GETJPI to get data for a named process

STATUS = SYS$GETJPIW (
2                    ,           ! No event flag
2                    ,           ! No PID
2                    'SMITH_1',  ! Process name
2                    JPILIST,    ! Item list
2                    IOSB,       ! Always use IOSB with $GETJPI!
2                    ,           ! No AST
2                    )           ! No AST arg


4.2.3.2 Requesting Information About All Processes on the Local System

You can use SYS$GETJPI to perform a wildcard search on all processes on the local system. When the initial pidadr argument is specified as -1 , SYS$GETJPI returns requested information for each process that the program has privilege to access. The requested information is returned for one process per call to SYS$GETJPI.

To perform a wildcard search, call SYS$GETJPI in a loop, testing the return status.

When performing wildcard searches, SYS$GETJPI returns an error status for processes that are inaccessible. When a program that uses a -1 wildcard checks the status value returned by SYS$GETJPI, it should test for the following status codes:

Status Explanation
SS$_NOMOREPROC All processes have been returned.
SS$_NOPRIV The caller lacks sufficient privilege to examine a process.
SS$_SUSPENDED The target process is being deleted or is suspended and cannot return the information.

Example 4-5 is a C program that demonstrates how to use the SYS$GETJPI -1 wildcard to search for all processes on the local system.

Example 4-5 Using SYS$GETJPI to Request Information About All Processes on the Local System

#include <stdio.h>
#include <jpidef.h>
#include <stdlib.h>
#include <ssdef.h>

/* Item descriptor */

struct {
        unsigned short buflen, item_code;
        void *bufaddr;
        void *retlenaddr;
        unsigned int terminator;
}itm_lst;

/* I/O Status Block */

struct {
        unsigned short iostat;
        unsigned short iolen;
        unsigned int device_info;
}iosb;

main() {

        unsigned short len;
        unsigned int efn=1,pidadr = -1,status, usersize;
        char username[12];

/* Initialize the item list */

        itm_lst.buflen = 12;
        itm_lst.item_code = JPI$_USERNAME;
        itm_lst.bufaddr = username;
        itm_lst.retlenaddr = &usersize;
        itm_lst.terminator = 0;

        do{

        status = SYS$GETJPIW(0,                 /* no event flag */
                             &pidadr,           /* process id */
                             0,                 /* process name */
                             &itm_lst,          /* item list */
                             &iosb,             /* I/O status block */
                             0,                 /* astadr (AST routine) */
                             0);                /* astprm (AST parameter) */
                 switch(status)
                 {
case SS$_NOPRIV:
                printf("\nError: No privileges for attempted operation");
                break;
case SS$_SUSPENDED:
                printf("\nError: Process is suspended");
                break;
case SS$_NORMAL:
                if (iosb.iostat == SS$_NORMAL)
                     printf("\nUsername: %s",username);
                else
                     printf("\nIOSB condition value  %d returned",iosb.iostat);
                        }

        }while(status != SS$_NOMOREPROC);

}


Previous Next Contents Index