Previous | Contents | Index |
Within the OpenVMS system, many global symbol definitions are used and accessed by programs and procedures in many ways. The most common uses are to define symbolic names for the following:
From a PL/I program, you can declare the symbolic names for system global symbols with the GLOBALREF and VALUE attributes. The format of these declarations is as follows:
DECLARE symbol-name GLOBALREF FIXED BINARY(31) VALUE; |
The GLOBALREF attribute indicates to PL/I that the variable is a reference to a global symbol defined in another module. The VALUE attribute indicates that the value of the variable is to be treated as if it were a constant.
The definitions for system global symbols are declared in the default system object module libraries. These libraries are automatically searched when you link a PL/I program. Of particular interest are the global symbols that define symbolic names for system service and file system return status values. Their use is described in Chapter 11.
A mailbox is a virtual I/O device that provides a means of communication for images executing in different processes. Mailboxes are used by the operating system to initiate and record system operations; they can also provide communication facilities for user applications.
This chapter provides some general information on using mailboxes, and examples of simple procedures that perform input and output to mailboxes.
Note that this chapter provides only information that is pertinent to
mailbox I/O and does not describe mailbox creation. There is a system
procedure to create a mailbox, the Create Mailbox and Assign Channel
system service (SYS$CREMBX). For an annotated example of a call to this
system service, see Chapter 11.
13.1 Using Mailboxes
This section provides information on how the system controls the
creation and use of mailboxes, and shows a typical use of mailboxes in
an application.
13.1.1 System Information
When a program creates a mailbox, the operating system allocates dynamic memory to store control information about the device and to buffer input and output data. The ability to create mailboxes is controlled by two separate privileges:
In either case, when the system creates a mailbox, it defines a unique device with the name MBn (where n is a unit number) and equates this device name with the logical name specified by the program that created the mailbox.
The logical name of a temporary mailbox is placed in the group logical name table for the group of the creating process. The logical name of a permanent mailbox is placed in the system logical name table.
The process that creates a mailbox can define its protection; that is,
it can control which users are allowed to write messages to the mailbox
and which users are allowed to read messages from the mailbox.
13.1.2 Applications
A mailbox usually has only one reader and multiple writers. In a typical application, two or more program images would be executed concurrently in separate processes. One program, the controlling program, receives requests or messages from the other cooperating programs by way of the mailbox.
The controlling program takes the following actions:
Each cooperating program takes the following actions:
The following describes a typical application of mailbox communication between processes:
OPEN FILE (MFILE) INPUT RECORD TITLE('PLI_MAILBOX'); |
LOOP: READ FILE (MFILE) INTO(M_REC); . . . GOTO LOOP; |
The mailbox remains available to other processes until the controlling process deletes the mailbox.
To write to the mailbox, a program does the following:
OPEN FILE (MAILB) OUTPUT RECORD TITLE('PLI_MAILBOX'); |
WRITE FILE (MAILB) FROM (M_TEXT); |
CLOSE FILE (MAILB); |
All processes writing to the mailbox must specify the TITLE defined by
the process that created the mailbox, but it can specify its own file
and record names.
13.1.3 Effects of the OPEN Statement
When the TITLE option of an OPEN statement specifies the logical name of a mailbox, the run-time system associates a PL/I file with the mailbox device. The OPEN statement actually assigns an I/O channel to the mailbox; a channel is an I/O path used by the operating system to perform data transfers.
Every OPEN statement executed for the same mailbox assigns another
channel to the device. The system counts all channels assigned to a
mailbox; therefore, it knows when to delete the mailbox.
13.1.4 Effects of the CLOSE Statement
A CLOSE statement for a mailbox dissociates the PL/I file from the device and deassigns the channel to the device. When the count of channels assigned to a temporary mailbox reaches zero, the system deletes the mailbox and its logical name equivalence, if any. When the count of channels assigned to a permanent mailbox that is marked for deletion reaches zero, the system deletes the permanent mailbox and its logical name equivalence, if any. You must invoke the Delete Mailbox system service (SYS$DELMBX) to mark a permanent mailbox for deletion.
Each time a CLOSE statement is executed for a mailbox, the file system writes an end-of-file to the mailbox. When this end-of-file is encountered during an input operation, the ENDFILE condition is signaled.
Note that in the context of reading a mailbox, an end-of-file does not
necessarily mean that there is no more data; it only means that one
channel
has been deassigned. Thus, a program that is reading a mailbox must
take end-of-file records into account and handle the ENDFILE condition
accordingly. The manner in which the ENDFILE condition is handled
depends on the type of I/O being performed, as described in
Section 13.2.
13.2 Mailbox Input/Output
You can use either the stream I/O statements GET and PUT or the record I/O statements READ and WRITE to read from and write to mailboxes. The type of I/O you use depends on your application and the type of data that will be sent.
When you plan an application using mailboxes, you must also determine
whether to use synchronous or asynchronous I/O operations. These types
of operations are described in the following sections. Each involves
special programming considerations.
13.2.1 Synchronous Input/Output
By default, all I/O operations to a mailbox are synchronous. This means that when an image executing in one process performs an output operation to a mailbox, the operation is not completed until an image being executed in another process reads the data from the mailbox. Similarly, when a program requests an input operation from a mailbox, control is not returned until an actual input operation is performed: if there is no data in the mailbox, the process must wait until another process writes data to the mailbox.
Example 13-1 shows a program that reads a mailbox synchronously. This program reads all data sent to a particular mailbox and copies all messages into a central log file. This procedure assumes that the mailbox PLI_MAILBOX already exists. For an example of a procedure that creates this mailbox, see Chapter 11.
The following notes are keyed to Example 13-1:
Example 13-1 Synchronous Mailbox Input/Output |
---|
LOGGER: PROCEDURE; DECLARE (MAILFILE,OUTFILE) FILE; /* (1) */ DECLARE 1 LOG_MESSAGE, /* (2) */ 2 TYPE FIXED BINARY(31), 2 SYSTEM_TIME CHARACTER(25), 2 REQUESTOR CHARACTER(15), 2 STATUS FIXED BINARY(31); %REPLACE END_RUN BY -1; OPEN FILE(MAILFILE) RECORD INPUT SEQUENTIAL /* (3) */ TITLE ('PLI_MAILBOX'); OPEN FILE(OUTFILE) PRINT TITLE('MAILTEST.OUT'); /* (4) */ ON ENDFILE(MAILFILE) GOTO LOOP; /* Ignore end-of-file */ /* (5) */ LOOP: READ FILE(MAILFILE) INTO (LOG_MESSAGE); IF LOG_MESSAGE.TYPE = END_RUN /* (6) */ THEN GOTO FINISH; PUT FILE(OUTFILE) SKIP LIST(TYPE, SYSTEM_TIME,REQUESTOR,STATUS); GOTO LOOP; FINISH: CLOSE FILE(MAILFILE), FILE(OUTFILE); /* (7) */ END LOGGER; |
It is not always practical for a procedure that is reading a mailbox to wait until the mailbox has been written. To perform an I/O operation that is completed immediately, you must code a call to the Queue I/O Request system service (SYS$QIO). This service permits you to specify I/O functions that are not possible using PL/I statements.
Example 13-2 illustrates a procedure that uses the SYS$QIO system service to perform asynchronous I/O to a mailbox. This procedure, EMPTY_BOX, reads all of the messages in a mailbox. If the mailbox is empty, EMPTY_BOX displays a message to that effect.
The following notes are keyed to Example 13-2:
Example 13-2 Asynchronous Mailbox Input/Output |
---|
EMPTY_BOX: PROCEDURE OPTIONS(MAIN) RETURNS (FIXED BINARY(31)); %INCLUDE LIB$GET_EF; %INCLUDE LIB$FREE_EF; %INCLUDE SYS$ASSIGN; /* (1) */ %INCLUDE SYS$QIO; %INCLUDE SYS$WAITFR; %INCLUDE $IODEF; /* (2) */ %INCLUDE $SSDEF; %INCLUDE $STSDEF; DECLARE MBXCHAN FIXED BINARY(15); DECLARE EFN FIXED BIN(31); DECLARE 1 IO_STATUS, 2 VALUE FIXED (15), 2 BYTES_TRANSFERRED FIXED(15), 2 NOT_USED FIXED(31), IO_SUCCESS BIT(1) ALIGNED BASED(ADDR(IO_STATUS.VALUE)); DECLARE MESSAGE CHARACTER(132); /* (3) */ STS$VALUE = SYS$ASSIGN('PLI_MAILBOX',MBXCHAN,,); /* (4) */ IF ^STS$SUCCESS THEN RETURN (STS$VALUE); /* * Get an event flag to use */ STS$VALUE = LIB$GET_EF(EFN); IF ^STS$SUCCESS THEN RETURN (STS$VALUE); /* * Use a DO-loop to read the mailbox; each QIO is followed * by a test of the return status from QIO, then a wait for * the I/O completion. Then the status value in the I/O * status block is checked. If it contains SS$_ENDOFFILE, * return STS$SUCCESS. Otherwise, return error value. */ IO_STATUS.VALUE = 0; DO WHILE(IO_STATUS.VALUE ^= SS$_ENDOFFILE); STS$VALUE = SYS$QIO ( EFN, /* (5) */ MBXCHAN, IO$_READVBLK | IO$M_NOW, /* (6) */ IO_STATUS,,, /* (7) */ MESSAGE, /* (8) */ LENGTH(MESSAGE),,,,); IF ^STS$SUCCESS THEN RETURN(STS$VALUE); STS$VALUE = SYS$WAITFR(EFN); /* (9) */ IF IO_STATUS.VALUE = SS$_ENDOFFILE THEN DO; PUT SKIP LIST('Mailbox empty'); /* (10) */ RETURN(1); END; IF ^IO_SUCCESS THEN RETURN(IO_STATUS.VALUE); /* * If successful read, fall through to here */ PUT SKIP LIST(SUBSTR(MESSAGE,1,IO_STATUS.BYTES_TRANSFERRED), 'status ',IO_STATUS.VALUE); END; /* * Release the event flag */ STS$VALUE = LIB$FREE_EF(EFN); RETURN (STS$VALUE); END EMPTY_BOX; |
Previous | Next | Contents | Index |