Document revision date: 30 March 2001 | |
Previous | Contents | Index |
FILE DISK$USER:MYFILE.DAT DOES NOT EXIST |
Mailboxes are virtual devices that can be used for communication among processes. You accomplish actual data transfer by using OpenVMS RMS or I/O services. When the Create Mailbox and Assign Channel (SYS$CREMBX) system service creates a mailbox, it also assigns a channel to it for use by the creating process. Other processes can then assign channels to the mailbox using either the SYS$CREMBX or SYS$ASSIGN system service.
The SYS$CREMBX system service creates the mailbox. The SYS$CREMBX system service identifies a mailbox by a user-specified logical name and assigns it an equivalence name. The equivalence name is a physical device name in the format MBAn, where n is a unit number. The equivalence name has the terminal attribute.
When another process assigns a channel to the mailbox with the SYS$CREMBX or SYS$ASSIGN system service, it can identify the mailbox by its logical name. The service automatically translates the logical name. The process can obtain the MBAn name either by translating the logical name (with the SYS$TRNLNM system service), or by calling the Get Device/Volume Information (SYS$GETDVI) system service to obtain the unit number and the physical device name.
On VAX systems, channels assigned to mailboxes can be either bidirectional or unidirectional. Bidirectional channels (read/write) allow both SYS$QIO read and SYS$QIO write requests to be issued to the channel. Unidirectional channels (read-only or write-only) allow only a read request or a write request to the channel. The unidirectional channels and unidirectional $QIO function modifiers provide for greater synchronization between users of the mailbox.
On VAX systems, the Create Mailbox and Assign Channel (SYS$CREMBX) and Assign I/O Channel (SYS$ASSIGN) system services use the flags argument to enable unidirectional channels. If the flags argument is not specified or is zero, then the channel assigned to the mailbox is bidirectional (read/write). For more information, see the discussion and programming examples in the mailbox driver chapter in the OpenVMS I/O User's Reference Manual. Chapter 3 of this manual also discusses the use of mailboxes.
Mailboxes are either temporary or permanent. You need the user privileges TMPMBX and PRMMBX to create temporary and permanent mailboxes, respectively.
For a temporary mailbox, the SYS$CREMBX service enters the logical name and equivalence name in the logical name table LNM$TEMPORARY_MAILBOX. This logical name table name usually specifies the LNM$JOB logical name table name. The system deletes a temporary mailbox when no more channels are assigned to it.
For a permanent mailbox, the SYS$CREMBX service enters the logical name and equivalence name in the logical name table LNM$PERMANENT_MAILBOX. This logical name table name usually specifies the LNM$SYSTEM logical name table name. Permanent mailboxes continue to exist until they are specifically marked for deletion with the Delete Mailbox (SYS$DELMBX) system service.
The following example shows how processes can communicate by means of a mailbox:
/* Process ORION */ #include <descrip.h> #include <iodef.h> #include <lib$routines.h> #include <ssdef.h> #include <starlet.h> #include <stdio.h> #define MBXBUFSIZ 128 #define MBXBUFQUO 384 /* I/O status block */ struct { unsigned short iostat, iolen; unsigned int remainder; }mbxiosb; main() { void *p1, mbxast(); char mbuffer[MBXBUFSIZ], prmflg=0; unsigned short mbxchan, mbxiosb; unsigned int status, outlen; unsigned int mbuflen=MBXBUFSIZ, bufquo=MBXBUFQUO, promsk=0; $DESCRIPTOR(mblognam,"GROUP100_MAILBOX"); /* Create a mailbox */ status = SYS$CREMBX( prmflg, /* Permanent or temporary */ (1) &mbxchan, /* chan - channel number */ mbuflen, /* maxmsg - buffer length */ bufquo, /* bufquo - quota */ promsk, /* promsk - protection mask */ 0, /* acmode - access mode */ &mblognam, /* lognam - mailbox logical name */ 0); /* flags - options */ if (!$VMS_STATUS_SUCCESS(status)) LIB$SIGNAL(status); . . . /* Request I/O */ status = SYS$QIO(0, /* efn - event flag */ (2) mbxchan, /* chan - channel number */ IO$_READVBLK, /* func - function modifier */ &mbxiosb, /* iosb - I/O status block */ &mbxast, /* astadr - AST routine */ &mbuffer, /* p1 - output buffer */ mbuflen); /* p2 - length of buffer */ if (!$VMS_STATUS_SUCCESS(status)) LIB$SIGNAL(status); . . . } void mbxast(void) { (3) if (mbxiosb.iostat != SS$_NORMAL) status = SYS$QIOW(..., &mbuffer, &outlen,...) if (!$VMS_STATUS_SUCCESS(status)) LIB$SIGNAL(status); return; } /* Process Cygnus */ #include <descrip.h> #include <iodef.h> #include <lib$routines.h> #include <ssdef.h> #include <starlet.h> #include <stdio.h> #include <stsdef.h> #define MBXBUFSIZ 128 main() { unsigned short int mailchan; unsigned int status, outlen; char outbuf[MBXBUFSIZ]; $DESCRIPTOR(mailbox,"GROUP100_MAILBOX"); status = SYS$ASSIGN(&mailbox, &mailchan, 0, 0, 0); (4) if (!$VMS_STATUS_SUCCESS(status)) LIB$SIGNAL(status); . . . status = SYS$QIOW(0, mailchan, 0, 0, 0, 0, &outbuf, outlen, 0, 0, 0, 0) if (!$VMS_STATUS_SUCCESS(status)) LIB$SIGNAL(status); . . . } |
The lognam argument to the SYS$CREMBX service specifies a descriptor that points to a character string for the mailbox name.
Translation of the lognam argument proceeds as follows:
For example, assume that you have made the following logical name assignment:
$ DEFINE MBX$CHKPNT CHKPNT_001 |
Assume also that your program contains the following statements:
$DESCRIPTOR(mbxdesc,"CHKPNT"); . . . status = SYS$CREMBX(...,&mbxdesc,...); |
The following logical name translation takes place:
Because further translation is unsuccessful, the logical name CHKPNT_001 is created with the equivalence name MBAn (n is a number assigned by the system).
There are two exceptions to the logical name translation method discussed in this section:
The system uses mailboxes for communication among system processes. All system mailbox messages contain, in the first word of the message, a constant that identifies the sender of the message. These constants have symbolic names (defined in the $MSGDEF macro) in the following format:
MSG$_sender |
The symbolic names included in the $MSGDEF macro and their meanings are as follows:
Symbolic Name | Meaning |
---|---|
MSG$_TRMUNSOLIC | Unsolicited terminal data |
MSG$_CRUNSOLIC | Unsolicited card reader data |
MSG$_ABORT | Network partner aborted link |
MSG$_CONFIRM | Network connect confirm |
MSG$_CONNECT | Network inbound connect initiate |
MSG$_DISCON | Network partner disconnected |
MSG$_EXIT | Network partner exited prematurely |
MSG$_INTMSG | Network interrupt message; unsolicited data |
MSG$_PATHLOST | Network path lost to partner |
MSG$_PROTOCOL | Network protocol error |
MSG$_REJECT | Network connect reject |
MSG$_THIRDPARTY | Network third-party disconnect |
MSG$_TIMEOUT | Network connect timeout |
MSG$_NETSHUT | Network shutting down |
MSG$_NODEACC | Node has become accessible |
MSG$_NODEINACC | Node has become inaccessible |
MSG$_EVTAVL | Events available to DECnet Event Logger |
MSG$_EVTRCVCHG | Event receiver database change |
MSG$_INCDAT | Unsolicited incoming data available |
MSG$_RESET | Request to reset the virtual circuit |
MSG$_LINUP | PVC line up |
MSG$_LINDWN | PVC line down |
MSG$_EVTXMTCHG | Event transmitter database change |
The remainder of the message contains variable information, depending on the system component that is sending the message.
The format of the variable information for each message type is
documented with the system function that uses the mailbox.
23.20.3 Mailboxes for Process Termination Messages
When a process creates another process, it can specify the unit number of a mailbox as an argument to the Create Process ($CREPRC) system service. When you delete the created process, the system sends a message to the specified termination mailbox.
You cannot use a mailbox in memory shared by multiple processors as a
process termination mailbox.
23.21 Example of Using I/O Services
In the following Fortran example, the first program, SEND.FOR, creates a mailbox named MAIL_BOX, writes data to it, and then indicates the end of the data by writing an end-of-file message.
The second program, RECEIVE.FOR, creates a mailbox with the same logical name, MAIL_BOX. It reads the messages from the mailbox into an array. It stops the read operations when a read operation generates an end-of-file message and the second longword of the I/O status block is nonzero. By checking that the I/O status block is nonzero, the second program confirms that the writing process sent the end-of-file message.
The processes use common event flag number 64 to ensure that SEND.FOR does not exit until RECEIVE.FOR has established a channel to the mailbox. (If RECEIVE.FOR executes first, an error occurs because SYS$ASSIGN cannot find the mailbox.)
SEND.FOR INTEGER STATUS ! Name and channel number for mailbox CHARACTER*(*) MBX_NAME PARAMETER (MBX_NAME = 'MAIL_BOX') INTEGER*2 MBX_CHAN ! Mailbox message CHARACTER*80 MBX_MESSAGE INTEGER LEN CHARACTER*80 MESSAGES (255) INTEGER MESSAGE_LEN (255) INTEGER MAX_MESSAGE PARAMETER (MAX_MESSAGE = 255) ! I/O function codes and status block INCLUDE '($IODEF)' INTEGER*4 WRITE_CODE INTEGER*2 IOSTAT, 2 MSG_LEN INTEGER READER_PID COMMON /IOBLOCK/ IOSTAT, 2 MSG_LEN, 2 READER_PID ! System routines INTEGER SYS$CREMBX, 2 SYS$ASCEFC, 2 SYS$WAITFR, 2 SYS$QIOW ! Create the mailbox. STATUS = SYS$CREMBX (, 2 MBX_CHAN, 2 ,,,, 2 MBX_NAME) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Fill MESSAGES array . . . ! Write the messages. DO I = 1, MAX_MESSAGE WRITE_CODE = IO$_WRITEVBLK .OR. IO$M_NOW MBX_MESSAGE = MESSAGES(I) LEN = MESSAGE_LEN(I) STATUS = SYS$QIOW (, 2 %VAL(MBX_CHAN), ! Channel 2 %VAL(WRITE_CODE), ! I/O code 2 IOSTAT, ! Status block 2 ,, 2 %REF(MBX_MESSAGE), ! P1 2 %VAL(LEN),,,,) ! P2 IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) IF (.NOT. IOSTAT) CALL LIB$SIGNAL (%VAL(STATUS)) END DO ! Write end of file WRITE_CODE = IO$_WRITEOF .OR. IO$M_NOW STATUS = SYS$QIOW (, 2 %VAL(MBX_CHAN), ! Channel 2 %VAL(WRITE_CODE), ! End of file code 2 IOSTAT, ! Status block 2 ,,,,,,,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) IF (.NOT. IOSTAT) CALL LIB$SIGNAL (%VAL(IOSTAT)) . . . ! Make sure cooperating process can read the information ! by waiting for it to assign a channel to the mailbox. STATUS = SYS$ASCEFC (%VAL(64), 2 'CLUSTER',,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = SYS$WAITFR (%VAL(64)) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) END RECEIVE.FOR INTEGER STATUS INCLUDE '($IODEF)' INCLUDE '($SSDEF)' ! Name and channel number for mailbox CHARACTER*(*) MBX_NAME PARAMETER (MBX_NAME = 'MAIL_BOX') INTEGER*2 MBX_CHAN ! QIO function code INTEGER READ_CODE ! Mailbox message CHARACTER*80 MBX_MESSAGE INTEGER*4 LEN ! Message arrays CHARACTER*80 MESSAGES (255) INTEGER*4 MESSAGE_LEN (255) ! I/O status block INTEGER*2 IOSTAT, 2 MSG_LEN INTEGER READER_PID COMMON /IOBLOCK/ IOSTAT, 2 MSG_LEN, 2 READER_PID ! System routines INTEGER SYS$ASSIGN, 2 SYS$ASCEFC, 2 SYS$SETEF, 2 SYS$QIOW ! Create the mailbox and let the other process know STATUS = SYS$ASSIGN (MBX_NAME, 2 MBX_CHAN,,,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = SYS$ASCEFC (%VAL(64), 2 'CLUSTER',,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = SYS$SETEF (%VAL(64)) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Read first message READ_CODE = IO$_READVBLK .OR. IO$M_NOW LEN = 80 STATUS = SYS$QIOW (, 2 %VAL(MBX_CHAN), ! Channel 2 %VAL(READ_CODE), ! Function code 2 IOSTAT, ! Status block 2 ,, 2 %REF(MBX_MESSAGE), ! P1 2 %VAL(LEN),,,,) ! P2 IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) IF ((.NOT. IOSTAT) .AND. 2 (IOSTAT .NE. SS$_ENDOFFILE)) THEN CALL LIB$SIGNAL (%VAL(IOSTAT)) ELSE IF (IOSTAT .NE. SS$_ENDOFFILE) THEN I = 1 MESSAGES(I) = MBX_MESSAGE MESSAGE_LEN(I) = MSG_LEN END IF ! Read messages until cooperating process writes end-of-file DO WHILE (.NOT. ((IOSTAT .EQ. SS$_ENDOFFILE) .AND. 2 (READER_PID .NE. 0))) STATUS = SYS$QIOW (, 2 %VAL(MBX_CHAN), ! Channel 2 %VAL(READ_CODE), ! Function code 2 IOSTAT, ! Status block 2 ,, 2 %REF(MBX_MESSAGE), ! P1 2 %VAL(LEN),,,,) ! P2 IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) IF ((.NOT. IOSTAT) .AND. 2 (IOSTAT .NE. SS$_ENDOFFILE)) THEN CALL LIB$SIGNAL (%VAL(IOSTAT)) ELSE IF (IOSTAT .NE. SS$_ENDOFFILE) THEN I = I + 1 MESSAGES(I) = MBX_MESSAGE MESSAGE_LEN(I) = MSG_LEN END IF END DO . . . |
Fast I/O and Fast Path are two optional features that can provide improved I/O performance. Performance improvement is achieved by reducing the CPU cost per I/O request, and improving symmetric multiprocessing (SMP) scaling of I/O operations. The CPU cost per I/O is reduced by optimizing code for high-volume I/O and by using better SMP CPU memory cache. SMP scaling of I/O is increased by reducing the number of spinlocks taken per I/O and by substituting finer-granularity spinlocks for global spinlocks.
The improvements follow a division that already exists between the device-independent and device-dependent layers in the OpenVMS I/O subsystem. The device-independent overhead is addressed by Fast I/O, which is a set of system services that can substitute for certain $QIO operations. Using these services requires some coding changes in existing applications, but the changes are usually modest and well contained. The device-dependent overhead is addressed by Fast Path, which is an optional performance feature that creates a "fast path" to the device. It requires no application changes.
Fast I/O and Fast Path can be used independently. However, together
they can provide a reduction in CPU cost per I/O on uniprocessor and on
multiprocessor systems.
23.22.1 Fast I/O (Alpha Only)
Fast I/O is a set of three system services, SYS$IO_SETUP, SYS$IO_PERFORM, and SYS$IO_CLEANUP, that were developed as an alternative to $QIO. These services are not a $QIO replacement; $QIO is unchanged, and $QIO interoperation with these services is fully supported. Rather, the services substitute for a subset of $QIO operations, namely, only the high-volume read/write I/O requests.
The Fast I/O services support 64-bit addresses for data transfers to and from disk and tape devices.
While Fast I/O services are available on OpenVMS VAX, the performance advantage applies only to OpenVMS Alpha. OpenVMS VAX has a run-time library (RTL) compatibility package that translates the Fast I/O service requests to $QIO system service requests, so one set of source code can be used on both VAX and Alpha systems.
Previous | Next | Contents | Index |
privacy and legal statement | ||
5841PRO_065.HTML |