|
HP OpenVMS systems documentation |
Previous | Contents | Index |
You can execute some input/output services either synchronously or asynchronously. A "W" at the end of a system service name indicates the synchronous version of the system service.
The synchronous version of a system service combines the functions of the asynchronous version of the service and the Synchronize (SYS$SYNCH) system service. The synchronous version acts exactly as if you had used the asynchronous version of the system service followed immediately by a call to SYS$SYNCH; it queues the I/O request, and then places the program in a wait state until the I/O request completes. The synchronous version takes the same arguments as the asynchronous version.
Table 23-2 lists the asynchronous and synchronous names of input/output services that have synchronous versions.
Asynchronous Name | Synchronous Name | Description |
---|---|---|
$BRKTHRU | $BRKTHRUW | Breakthrough |
$GETDVI | $GETDVIW | Get Device/Volume Information |
$GETJPI | $GETJPIW | Get Job/Process Information |
$GETLKI | $GETLKIW | Get Lock Information |
$GETQUI | $GETQUIW | Get Queue Information |
$GETSYI | $GETSYIW | Get Systemwide Information |
$QIO | $QIOW | Queue I/O Request |
$SNDJBC | $SNDJBCW | Send to Job Controller |
$UPDSEC | $UPDSECW | Update Section File on Disk |
The SYS$QIO and SYS$QIOW system services move one record of data from a terminal to a variable. For synchronous I/O, use SYS$QIOW. Complete information about the SYS$QIO and SYS$QIOW system services is presented in the HP OpenVMS System Services Reference Manual.
The SYS$QIO and SYS$QIOW system services place the data read in the variable specified in the 1 argument. The second word of the status block contains the offset from the beginning of the buffer to the terminator---hence, it equals the size of the data read. Always reference the data as a substring, using the offset to the terminator as the position of the last character (that is, the size of the substring). If you reference the entire buffer, your data will include the terminator for the operation (for example, the CR character) and any excess characters from a previous operation using the buffer. (The only exception to the substring guideline is if you deliberately overflow the buffer to terminate the I/O operation.)
Example 23-4 shows use of the SYS$QIOW system service and reads a line of data from the terminal and waits for the I/O to complete.
Example 23-4 Reading Data from the Terminal Synchronously |
---|
. . . INTEGER STATUS ! QIOW structures INTEGER*2 INPUT_CHAN ! I/O channel INTEGER CODE, ! Type of I/O operation 2 INPUT_BUFF_SIZE, ! Size of input buffer 2 PROMPT_SIZE, ! Size of prompt 2 INPUT_SIZE ! Size of input line as read PARAMETER (PROMPT_SIZE = 13, 2 INPUT_BUFF_SIZE = 132) CHARACTER*132 INPUT CHARACTER*(*) PROMPT PARAMETER (PROMPT = 'Input value: ') ! Define symbols used in I/O operations INCLUDE '($IODEF)' ! Status block for QIOW STRUCTURE /IOSTAT_BLOCK/ INTEGER*2 IOSTAT, ! Return status 2 TERM_OFFSET, ! Location of line terminator 2 TERMINATOR, ! Value of terminator 2 TERM_SIZE ! Size of terminator END STRUCTURE RECORD /IOSTAT_BLOCK/ IOSB ! Subprograms INTEGER*4 SYS$ASSIGN, 2 SYS$QIOW . . . ! Assign an I/O channel to SYS$INPUT STATUS = SYS$ASSIGN ('SYS$INPUT', 2 INPUT_CHAN,,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Read with prompt CODE = IO$_READPROMPT STATUS = SYS$QIOW (, 2 %VAL (INPUT_CHAN), 2 %VAL (CODE), 2 IOSB, 2 ,, 2 %REF (INPUT), 2 %VAL (INPUT_BUFF_SIZE), 2 ,, 2 %REF (PROMPT), 2 %VAL (PROMPT_SIZE)) ! Check QIOW status IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Check status of I/O operation IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT)) ! Set size of input string INPUT_SIZE = IOSB.TERM_OFFSET . . . |
To perform an asynchronous read operation, use the SYS$QIO system service and specify an event flag (the first argument, which must be passed by value). Your program continues while the I/O is taking place. When you need the input from the I/O operation, invoke the SYS$SYNCH system service to wait for the event flag and status block specified in the SYS$QIO system service. If the I/O is not complete, your program pauses until it is. In this manner, you can overlap processing within your program. Naturally, you must take care not to assume data has been returned by the I/O operation before you call SYS$SYNCH and it returns successfully. Example 23-5 demonstrates an asynchronous read operation.
Example 23-5 Reading Data from the Terminal Asynchronously |
---|
. . . INTEGER STATUS ! QIO structures INTEGER*2 INPUT_CHAN ! I/O channel INTEGER CODE, ! Type of I/O operation 2 INPUT_BUFF_SIZE, ! Size of input buffer 2 PROMPT_SIZE, ! Size of prompt 2 INPUT_SIZE ! Size of input line as read PARAMETER (INPUT_BUFF_SIZE = 132, 2 PROMPT = 13) CHARACTER*132 INPUT CHARACTER*(*) PROMPT PARAMETER (PROMPT = 'Input value: ') INCLUDE '($IODEF)' ! Symbols used in I/O operations ! Status block for QIO STRUCTURE /IOSTAT_BLOCK/ INTEGER*2 IOSTAT, ! Return status 2 TERM_OFFSET, ! Location of line terminator 2 TERMINATOR, ! Value of terminator 2 TERM_SIZE ! Size of terminator END STRUCTURE RECORD /IOSTAT_BLOCK/ IOSB ! Event flag for I/O INTEGER INPUT_EF ! Subprograms INTEGER*4 SYS$ASSIGN, 2 SYS$QIO, 2 SYS$SYNCH, 2 LIB$GET_EF . . . ! Assign an I/O channel to SYS$INPUT STATUS = SYS$ASSIGN ('SYS$INPUT', 2 INPUT_CHAN,,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Get an event flag STATUS = LIB$GET_EF (INPUT_EF) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Read with prompt CODE = IO$_READPROMPT STATUS = SYS$QIO (%VAL (INPUT_EF), 2 %VAL (INPUT_CHAN), 2 %VAL (CODE), 2 IOSB, 2 ,, 2 %REF (INPUT), 2 %VAL (INPUT_BUFF_SIZE), 2 ,, 2 %REF (PROMPT), 2 %VAL (PROMPT_SIZE)) ! Check status of QIO IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) . . . STATUS = SYS$SYNCH (%VAL (INPUT_EF), 2 IOSB) ! Check status of SYNCH IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Check status of I/O operation IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT)) ! Set size of input string INPUT_SIZE = IOSB.TERM_OFFSET . . . |
Be sure to check the status of the I/O operation as returned in the I/O
status block. In an asynchronous operation, you can check this status
only after the I/O operation is complete (that is, after the call to
SYS$SYNCH).
23.9.3 Write Operations with SYS$QIOW
The SYS$QIO and SYS$QIOW system services move one record of data from a character value to the terminal. Do not use these system services, as described here, for output to a file or nonterminal device.
For synchronous I/O, use SYS$QIOW and omit the first argument (the event flag number). For complete information about SYS$QIO and SYS$QIOW, refer to the HP OpenVMS System Services Reference Manual.
Example 23-6 writes a line of character data to the terminal.
Example 23-6 Writing Character Data to a Terminal |
---|
INTEGER STATUS, 2 ANSWER_SIZE CHARACTER*31 ANSWER INTEGER*2 OUT_CHAN ! Status block for QIO STRUCTURE /IOSTAT_BLOCK/ INTEGER*2 IOSTAT, 2 BYTE_COUNT, 2 LINES_OUTPUT BYTE COLUMN, 2 LINE END STRUCTURE RECORD /IOSTAT_BLOCK/ IOSB ! Routines INTEGER SYS$ASSIGN, 2 SYS$QIOW ! IO$ symbol definitions INCLUDE '($IODEF)' . . . STATUS = SYS$ASSIGN ('SYS$OUTPUT', 2 OUT_CHAN,,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) STATUS = SYS$QIOW (, 2 %VAL (OUT_CHAN), 2 %VAL (IO$_WRITEVBLK), 2 IOSB, 2 , 2 , 2 %REF ('Answer: '//ANSWER(1:ANSWER_SIZE)), 2 %VAL (8+ANSWER_SIZE), 2 , 2 %VAL (32),,) ! Single spacing IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT)) END |
When an I/O operation completes, the system posts the completion status in the I/O status block, if one is specified. The completion status indicates whether the operation completed successfully, the number of bytes that were transferred, and additional device-dependent return information.
Figure 23-7 illustrates the format for the SYS$QIO system service of the information written in the IOSB.
Figure 23-7 I/O Status Block
The first word contains a system status code indicating the success or failure of the operation. The status codes used are the same as for all returns from system services; for example, SS$_NORMAL indicates successful completion.
The second word contains the number of bytes actually transferred in the I/O operation. Note that for some devices this word contains only the low-order word of the count. For information about specific devices, see the HP OpenVMS I/O User's Reference Manual.
The second longword contains device-dependent return information.
System services other than SYS$QIO use the quadword I/O status block, but the format is different. See the description of each system service in the HP OpenVMS System Services Reference Manual for the format of the information written in the IOSB for that service.
To ensure successful I/O completion and the integrity of data
transfers, you should check the IOSB following I/O requests,
particularly for device-dependent I/O functions. For complete details
about how to use the I/O status block, see the HP OpenVMS I/O User's Reference Manual.
23.11 Deassigning I/O Channels
When a process no longer needs access to an I/O device, it should release the channel assigned to the device by calling the Deassign I/O Channel (SYS$DASSGN) system service:
$DASSGN_S CHAN=TTCHAN |
This service call releases the terminal channel assignment acquired in
the SYS$ASSIGN example shown in Section 23.5. The system automatically
deassigns channels for a process when the image that assigned the
channel exits.
23.12 Using Complete Terminal I/O
The following example shows a complete sequence of input and output operations using the $QIOW macro to read and write lines to the current default SYS$INPUT device. Because the input/output of this program must be to the current terminal, it functions correctly only if you execute it interactively.
#include <descrip.h> #include <iodef.h> #include <lib$routines.h> #include <ssdef.h> #include <starlet.h> #include <stdio.h> #include <string.h> #define BUFSIZ 80 /* I/O status block */ struct { (1) unsigned short iostat, ttiolen; unsigned int dev_info; }ttiosb; main() { unsigned int status ,outlen, inlen = BUFSIZ; unsigned short ttchan; char buffer[BUFSIZ]; (2) $DESCRIPTOR(ttname,"SYS$INPUT"); (3) /* Assign a channel */ status = SYS$ASSIGN(&ttname, /* devnam - device number */ (4) &ttchan, /* chan - channel number */ 0, 0, 0); if (!$VMS_STATUS_SUCCESS(status)) LIB$SIGNAL( status ); /* Request I/O */ status = SYS$QIOW(0, /* efn - event flag */ ttchan, /* chan - channel number */ IO$_READVBLK, /* func - function modifier */ &ttiosb, /* iosb - I/O status block */ 0, /* astadr - AST routine */ 0, /* astprm - AST parameter */ buffer, /* p1 - buffer */ inlen, /* p2 - length of buffer */ 0, 0, 0, 0); (5) if (!$VMS_STATUS_SUCCESS( status )) (6) LIB$SIGNAL( status ); /* Get length from IOSB */ outlen = ttiosb.ttiolen; (7) status = SYS$QIOW(0, ttchan, IO$_WRITEVBLK, &ttiosb, 0, 0, buffer, outlen, 0, 0, 0, 0); if (!$VMS_STATUS_SUCCESS( status )) LIB$SIGNAL( status ); (8) /* Deassign the channel */ status = SYS$DASSGN( ttchan ); /* chan - channel */ (9) if (!$VMS_STATUS_SUCCESS( status )) LIB$SIGNAL( status ); } |
If a process must cancel I/O requests that have been queued but not yet completed, it can issue the Cancel I/O On Channel (SYS$CANCEL) system service. All pending I/O requests issued by the process on that channel are canceled; you cannot specify a particular I/O request.
The SYS$CANCEL system service performs an asynchronous cancel operation. This means that the application must wait for each I/O operation issued to the driver to complete before checking the status for that operation.
For example, you can call the SYS$CANCEL system service as follows:
unsigned int status, efn1=3, efn2=4; . . . status = SYS$QIO(efn1, ttchan, &iosb1, ...); status = SYS$QIO(efn2, ttchan, &iosb2, ...); . . . status = SYS$CANCEL(ttchan); status = SYS$SYNCH(efn1, &iosb1); status = SYS$SYNCH(efn2, &iosb2); |
In this example, the SYS$CANCEL system service initiates the cancellation of all pending I/O requests to the channel whose number is located at TTCHAN.
The SYS$CANCEL system service returns after initiating the cancellation
of the I/O requests. If the call to SYS$QIO specified either an event
flag, AST service routine, or I/O status block, the system sets either
the flag, delivers the AST, or posts the I/O status block as
appropriate when the cancellation is completed.
23.14 Logical Names and Physical Device Names
When you specify a device name as input to an I/O system service, it can be a physical device name or a logical name. If the device name contains a colon (:), the colon and the characters after it are ignored. When an underscore character (_) precedes a device name string, it indicates that the string is a physical device name string, for example, _TTB3:.
Any string that does not begin with an underscore is considered a logical name, even though it may be a physical device name. Table 23-3 lists system services that translate a logical name iteratively until a physical device name is returned, or until the system default number of translations have been performed.
System Service | Definition |
---|---|
SYS$ALLOC | Allocate Device |
SYS$ASSIGN | Assign I/O Channel |
SYS$BRDCST | Broadcast |
SYS$DALLOC | Deallocate Device |
SYS$DISMOU | Dismount Volume |
SYS$GETDEV | Get I/O Device Information |
SYS$GETDVI | Get Device/Volume Information |
SYS$MOUNT | Mount Volume |
In each translation, the logical name tables defined by the logical name LNM$FILE_DEV are searched in order. These tables, listed in search order, are normally LNM$PROCESS, LNM$JOB, LNM$GROUP, and LNM$SYSTEM. If a physical device name is located, the I/O request is performed for that device.
If the services do not locate an entry for the logical name, the I/O service treats the name specified as a physical device name. When you specify the name of an actual physical device in a call to one of these services, include the underscore character to bypass the logical name translation.
When the SYS$ALLOC system service returns the device name of the physical device that has been allocated, the device name string returned is prefixed with an underscore character. When this name is used for the subsequent SYS$ASSIGN system service, the SYS$ASSIGN service does not attempt to translate the device name.
If you use logical names in I/O service calls, you must be sure to establish a valid device name equivalence before program execution. You can do this either by issuing a DEFINE command from the command stream, or by having the program establish the equivalence name before the I/O service call with the Create Logical Name (SYS$CRELNM) system service.
For details about how to create and use logical names, see
Chapter 34.
23.15 Device Name Defaults
If, after logical name translation, a device name string in an I/O system service call does not fully specify the device name (that is, device, controller, and unit), the service either provides default values for nonspecified fields, or provides values based on device availability.
The following rules apply:
Device | Device Name1 | Generic Device |
---|---|---|
dd: | ddA0: (unit 0 on controller A) | ddxy: (any available device of the specified type) |
ddc: | ddc0: (unit 0 on controller specified) | ddcy: (any available unit on the specified controller) |
ddu: | ddA u: (unit specified on controller A) | ddxu: (device of specified type and unit on any available controller) |
ddcu: | ddcu: (unit and controller specified) | ddcu: (unit and controller specified) |
dd ---Specified device type (capital letters indicate a specific controller; numbers indicate a specific unit)
c ---Specified controller
x ---Any controller
u ---Specified unit number
y ---Any unit number
Previous | Next | Contents | Index |