|
HP OpenVMS systems documentation |
Previous | Contents | Index |
The Get Device/Volume Information (SYS$GETDVI) system service returns information about devices. The information returned is specified by an item list created before the call to SYS$GETDVI.
When you call the SYS$GETDVI system service, you must provide the address of an item list that specifies the information to be returned. The format of the item list is described in the description of SYS$GETDVI in the HP OpenVMS System Services Reference Manual. The HP OpenVMS I/O User's Reference Manual contains details on the device-specific information these services return.
In cases where a generic (that is, nonspecific) device name is used in an I/O service, a program may need to find out what device has been used. To do this, the program should provide SYS$GETDVI with the number of the channel to the device and request the name of the device with the DVI$_DEVNAM item identifier.
The operating system also supports a device called the null device for program development. The mnemonic for the null device is NL. Its characteristics are as follows:
The null device functions as a virtual device to which you can direct
output but from which the data does not return.
23.16.1 Checking the Terminal Device
You are restricted to a terminal device if you use any of the special functions described in this section. If the user of your program redirects SYS$INPUT or SYS$OUTPUT to a file or nonterminal device, an error occurs. You can use the SYS$GETDVIW system service to make sure the logical name is associated with a terminal, as shown in Example 23-7. SYS$GETDVIW returns a status of SS$_IVDEVNAM if the logical name is defined as a file or otherwise does not equate to a device name. The type of device is the response associated with the DVI$_DEVCLASS request code and should be DC$_TERM for a terminal.
Example 23-7 Using SYS$GETDVIW to Verify the Device Name |
---|
RECORD /ITMLST/ DVI_LIST LOGICAL*4 STATUS ! GETDVI buffers INTEGER CLASS, ! Response buffer 2 CLASS_LEN ! Response length ! GETDVI symbols INCLUDE '($DCDEF)' INCLUDE '($SSDEF)' INCLUDE '($DVIDEF)' ! Define subprograms INTEGER SYS$GETDVIW ! Find out the device class of SYS$INPUT DVI_LIST.BUFLEN = 4 DVI_LIST.CODE = DVI$_DEVCLASS DVI_LIST.BUFADR = %LOC (CLASS) DVI_LIST.RETLENADR = %LOC (CLASS_LEN) STATUS = SYS$GETDVIW (,,'SYS$INPUT', 2 DVI_LIST,,,,,) IF ((.NOT. STATUS) .AND. (STATUS .NE. SS$_IVDEVNAM)) THEN CALL LIB$SIGNAL (%VAL (STATUS)) END IF ! Make sure device is a terminal IF ((STATUS .NE. SS$_IVDEVNAM) .AND. (CLASS .EQ. DC$_TERM)) THEN . . . ELSE TYPE *, 'Input device not a terminal' END IF |
The HP OpenVMS I/O User's Reference Manual describes device-specific characteristics associated with terminals. To examine a characteristic, issue a call to SYS$QIO or SYS$QIOW system service with the IO$_SENSEMODE function and examine the appropriate bit in the structure returned to the P1 argument. To change a characteristic:
Example 23-8 turns off the HOSTSYNC terminal characteristic. To check whether NOHOSTSYNC has been set, enter the SHOW TERMINAL command.
Example 23-8 Disabling the HOSTSYNC Terminal Characteristic |
---|
. . . INTEGER*4 STATUS ! I/O channel INTEGER*2 INPUT_CHAN ! I/O status block STRUCTURE /IOSTAT_BLOCK/ INTEGER*2 IOSTAT BYTE TRANSMIT, 2 RECEIVE, 2 CRFILL, 2 LFFILL, 2 PARITY, 2 ZERO END STRUCTURE RECORD /IOSTAT_BLOCK/ IOSB ! Characteristics buffer ! Note: basic characteristics are first three ! bytes of second longword -- length is ! last byte STRUCTURE /CHARACTERISTICS/ BYTE CLASS, 2 TYPE INTEGER*2 WIDTH UNION MAP INTEGER*4 BASIC END MAP MAP BYTE LENGTH(4) END MAP END UNION INTEGER*4 EXTENDED END STRUCTURE RECORD /CHARACTERISTICS/ CHARBUF ! Define symbols used for I/O and terminal operations INCLUDE '($IODEF)' INCLUDE '($TTDEF)' ! Subroutines INTEGER*4 SYS$ASSIGN, 2 SYS$QIOW ! Assign channel to terminal STATUS = SYS$ASSIGN ('SYS$INPUT', 2 INPUT_CHAN,,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) ! Get current characteristics STATUS = SYS$QIOW (, 2 %VAL (INPUT_CHAN), 2 %VAL (IO$_SENSEMODE), 2 IOSB,,, 2 CHARBUF, ! Buffer 2 %VAL (12),,,,) ! Buffer size IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT)) ! Turn off hostsync CHARBUF.BASIC = IBCLR (CHARBUF.BASIC, TT$V_HOSTSYNC) ! Set new characteristics STATUS = SYS$QIOW (, 2 %VAL (INPUT_CHAN), 2 %VAL (IO$_SETMODE), 2 IOSB,,, 2 CHARBUF, 2 %VAL (12),,,,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL (STATUS)) IF (.NOT. IOSB.IOSTAT) CALL LIB$SIGNAL (%VAL (IOSB.IOSTAT)) END |
If you modify terminal characteristics with set mode QIO operations,
you should save the characteristics buffer that you obtain on the first
sense mode operation, and restore those characteristics with a set mode
operation before exiting. (Resetting is not necessary if you just use
modifiers on each read operation.) To ensure that the restoration is
performed if the program aborts (for example, if the user presses
Ctrl/Y), you should restore the user's environment in an exit handler.
See Chapter 9 for a description of exit handlers.
23.16.3 Record Terminators
A QIO read operation ends when the user enters a terminator or when the input buffer fills, whichever occurs first. The standard set of terminators applies unless you specify the 4 argument in the read QIO operation. You can examine the terminator that ended the read operation by examining the input buffer starting at the terminator offset (second word of the I/O status block). The length, in bytes, of the terminator is specified by the high-order word of the I/O status block. The third word of the I/O status block contains the value of the first character of the terminator.
Examining the terminator enables you to read escape sequences from the
terminal, provided that you modify the QIO read operation with the
IO$M_ESCAPE modifier (or the ESCAPE terminal characteristic is set).
The first character of the terminator will be the ESC character (an
ASCII value of 27). The remaining characters will contain the value of
the escape sequence.
23.16.4 File Terminators
You must examine the terminator to detect end-of-file (Ctrl/Z) on the
terminal. No error condition is generated at the QIO level. If the user
presses Ctrl/Z, the terminator will be the SUB character (an ASCII
value of 26).
23.17 Device Allocation
Many I/O devices are shareable; that is, more than one process at a time can access the device. By calling the Assign I/O Channel (SYS$ASSIGN) system service, a process is given a channel to the device for I/O operations.
In some cases, a process may need exclusive use of a device so that data is not affected by other processes. To reserve a device for exclusive use, you must allocate it.
Device allocation is normally accomplished with the DCL command ALLOCATE. A process can also allocate a device by calling the Allocate Device (SYS$ALLOC) system service. When a device has been allocated by a process, only the process that allocated the device and any subprocesses it creates can assign channels to the device.
When you call the SYS$ALLOC system service, you must provide a device name. The device name specified can be any of the following:
If you specify a physical device name, SYS$ALLOC attempts to allocate the specified device.
If you specify a logical name, SYS$ALLOC translates the logical name and attempts to allocate the physical device name equated to the logical name.
If you specify a generic device name (that is, if you specify a device type but do not specify a controller or unit number, or both), SYS$ALLOC attempts to allocate any device available of the specified type. For more information about the allocation of devices by generic names, see Section 23.15.
When you specify generic device names, you must provide fields for the SYS$ALLOC system service to return the name and the length of the physical device that is actually allocated so that you can provide this name as input to the SYS$ASSIGN system service.
The following example illustrates the allocation of a tape device specified by the logical name TAPE:
#include <descrip.h> #include <lib$routines.h> #include <ssdef.h> #include <starlet.h> #include <stdio.h> main() { unsigned int status; char devstr[64]; unsigned short phylen, tapechan; $DESCRIPTOR(logdev,"TAPE"); /* Descriptor for logical name */ $DESCRIPTOR(devdesc,devstr); /* Descriptor for physical name */ /* Allocate a device */ status = SYS$ALLOC( &logdev, /* devnam - device name */ (1) &phylen, /* phylen - length device name string */ &devdesc, /* phybuf - buffer for devnam string */ 0, 0); if (!$VMS_STATUS_SUCCESS( status )) LIB$SIGNAL( status ); /* Assign a channel to the device */ status = SYS$ASSIGN( &devdesc, /* devnam - device name */ (2) &tapechan, /* chan - channel number */ 0, 0, 0); if (!$VMS_STATUS_SUCCESS( status )) LIB$SIGNAL( status ); /* Deassign the channel */ status = SYS$DASSGN( tapechan ); /* chan - channel number */(3) if (!$VMS_STATUS_SUCCESS( status )) LIB$SIGNAL( status ); /* Deallocate the device */ status = SYS$DALLOC( &devdesc, /* devnam - device name */ 0 ); /* acmode - access mode */ if (!$VMS_STATUS_SUCCESS( status )) LIB$SIGNAL( status ); } |
Devices that cannot be shared by more than one process (for example,
terminals and line printers) do not have to be explicitly allocated.
Because they are nonshareable, they are implicitly allocated by the
SYS$ASSIGN system service when SYS$ASSIGN is called to assign a channel
to the device.
23.17.2 Deallocation
When the program has finished using an allocated device, it should release the device with the Deallocate Device (SYS$DALLOC) system service to make it available for other processes.
At image exit, the system automatically deallocates devices allocated
by the image.
23.18 Mounting, Dismounting, and Initializing Volumes
This section introduces you to using system services to mount,
dismount, and initialize disk and tape volumes.
23.18.1 Mounting a Volume
Mounting a volume establishes a link between a volume, a device, and a process. A volume, or volume set, must be mounted before I/O operations can be performed on the volume. You interactively mount or dismount a volume from the DCL command stream with the MOUNT or DISMOUNT command. A process can also mount or dismount a volume or volume set programmatically using the Mount Volume (SYS$MOUNT) or the Dismount Volume (SYS$DISMOU) system service, respectively.
Mounting a volume involves two operations:
The Mount Volume (SYS$MOUNT) system service allows a process to mount a single volume or a volume set. When you call the SYS$MOUNT system service, you must specify a device name.
The SYS$MOUNT system service has a single argument, which is the address of a list of item descriptors. The list is terminated by a longword of binary zeros. Figure 23-8 shows the format of an item descriptor.
Figure 23-8 SYS$MOUNT Item Descriptor
Most item descriptors do not have to be in any order. To mount volume sets, you must specify one item descriptor per device and one item descriptor per volume; you must specify the descriptors for the volumes in the same order as the descriptors for the devices on which the volumes are loaded.
For item descriptors other than device and volume names, if you specify the same item descriptor more than once, the last occurrence of the descriptor is used.
The following example illustrates a call to SYS$MOUNT. The call is equivalent to the DCL command that precedes the example.
$ MOUNT/SYSTEM/NOQUOTA DRA4:,DRA5: USER01,USER02 USERD$ |
#include <descrip.h> #include <lib$routines.h> #include <mntdef.h> #include <starlet.h> #include <stdio.h> . . . struct { unsigned short buflen, item_code; void *bufaddr; int *retlenaddr; }itm; struct itm itm[7]; main() { . . . unsigned int status, flags; $DESCRIPTOR(dev1,"DRA4:"); $DESCRIPTOR(vol1,"USER01"); $DESCRIPTOR(dev2,"DRA5:"); $DESCRIPTOR(vol2,"USER02"); $DESCRIPTOR(log,"USERD$:"); flags = MNT$M_SYSTEM | MNT$M_NODISKQ; i = 0; itm[i].buflen = sizeof( flags ); itm[i].item_code = MNT$_FLAGS; itm[i].bufaddr = flags; itm[i++].retlenaddr = NULL; itm[i].buflen = dev1.dsc$w_length; itm[i].item_code = MNT$_DEVNAM; itm[i].bufaddr = dev1.dsc$a_pointer; itm[i++].retlenaddr = NULL; itm[i].buflen = vol1.dsc$w_length; itm[i].item_code = MNT$_VOLNAM; itm[i].bufaddr = vol1.dsc$a_pointer; itm[i++].retlenaddr = NULL; itm[i].buflen = dev2.dsc$w_length; itm[i].item_code = MNT$_DEVNAM; itm[i].bufaddr = dev2.dsc$a_pointer; itm[i++].retlenaddr = NULL; itm[i].buflen = vol2.dsc$w_length; itm[i].item_code = MNT$_VOLNAM; itm[i].bufaddr = vol2.dsc$a_pointer; itm[i++].retlenaddr = NULL; itm[i].buflen = log.dsc$w_length; itm[i].item_code = MNT$_LOGNAM; itm[i].bufaddr = log.dsc$a_pointer; itm[i++].retlenaddr = NULL; itm[i].buflen = 0; itm[i].item_code = 0; itm[i].bufaddr = NULL; itm[i++].retlenaddr = NULL; . . . status = SYS$MOUNT ( itm ); if (!$VMS_STATUS_SUCCESS(status)) LIB$SIGNAL( status ); . . . } |
The SYS$DISMOU system service allows a process to dismount a volume or volume set. When you call SYS$DISMOU, you must specify a device name. If the volume mounted on the device is part of a fully mounted volume set, and you do not specify flags, the whole volume set is dismounted.
The following example illustrates a call to SYS$DISMOU. The call dismounts the volume set mounted in the previous example.
$DESCRIPTOR(dev1_desc,"DRA4:"); . . . status = SYS$DISMOU(&dev1_desc); /* devnam - device */ . . . |
Initializing a volume writes a label on the volume, sets protection and ownership for the volume, formats the volume (depending on the device type), and overwrites data already on the volume.
You interactively initialize a volume from the DCL command stream using
the INITIALIZE command. A process can programmatically initialize a
volume using the Initialize Volume (SYS$INIT_VOL) system service.
23.18.2.1 Calling the Initialize Volume System Service
You must specify a device name and a new volume name when you call the SYS$INIT_VOL system service. You can also use the itmlst argument of $INIT_VOL to specify options for the initialization. For example, you can specify that data compaction should be performed by specifying the INIT$_COMPACTION item code. See the HP OpenVMS System Services Reference Manual for more information on initialization options.
Before initializing the volume with SYS$INIT_VOL, be sure you have placed the volume on the device and started the device (by pressing the START or LOAD button).
The default format for files on disk volumes is called Files-11 On-Disk Structure Level 2. Files-11 On-Disk Structure Level 1 format, available on VAX systems, is used by other HP operating systems, including RSX-11M, RSX-11M-PLUS, RSX-11D, and IAS, but is not supported on Alpha systems. For more information, see the HP OpenVMS System Manager's Manual.
Here are two examples of calling SYS$INIT_VOL programmatically: one from a C program and one from a BASIC program.
The following example illustrates a call to SYS$INIT_VOL from HP C:
#include <descrip.h> #include <initdef.h> #include <lib$routines.h> #include <starlet.h> #include <stsdef.h> struct item_descrip_3 { unsigned short buffer_size; unsigned short item_code; void *buffer_address; unsigned short *return_length; }; main () { unsigned long density_code, status; $DESCRIPTOR(drive_dsc, "MUA0:"); $DESCRIPTOR(label_dsc, "USER01"); struct { struct item_descrip_3 density_item; long terminator; } init_itmlst; /* ** Initialize the input item list. */ density_code = INIT$K_DENSITY_6250_BPI; init_itmlst.density_item.buffer_size = 4; init_itmlst.density_item.item_code = INIT$_DENSITY; init_itmlst.density_item.buffer_address = &density_code; init_itmlst.terminator = 0; /* ** Initialize the volume. */ status = SYS$INIT_VOL (&drive_dsc, &label_dsc, &init_itmlst); /* ** Report an error if one occurred. */ if (!$VMS_STATUS_SUCCESS (status )) LIB$STOP (status); } |
The following example illustrates a call to SYS$INIT_VOL from VAX BASIC:
OPTION TYPE = EXPLICIT %INCLUDE '$INITDEF' %FROM %LIBRARY EXTERNAL LONG FUNCTION SYS$INIT_VOL RECORD ITEM_DESC VARIANT CASE WORD BUFLEN WORD ITMCOD LONG BUFADR LONG LENADR CASE LONG TERMINATOR END VARIANT END RECORD DECLARE LONG RET_STATUS, & ITEM_DESC INIT_ITMLST(2) ! Initialize the input item list. INIT_ITMLST(0)::ITMCOD = INIT$_READCHECK INIT_ITMLST(1)::TERMINATOR = 0 ! Initialize the volume. RET_STATUS = SYS$INIT_VOL ("DJA21:" BY DESC, "USERVOLUME" BY DESC, INIT_ITMLST() BY REF) |
OpenVMS dynamic volume expansion (DVE) allows you to expand explicitly a file system if the container is itself expandable. The container can be expanded by the following methods:
If you use only parts of disks for performance reasons, and then if your application suddenly needs more storage space, DVE lets you expand without having to take the application offline.
You prepare the disks for future volume expansion by using either the SYS$INIT_VOL system service, or the DCL SET VOLUME command with the /LIMIT=nn and /SIZE[=nnnn] qualifiers. The SET VOLUME/LIMIT=nn specifies the new maximum volume size and causes the storage bitmap to be reallocated and extended. The SET VOLUME/ SIZE[=nnnn] specifies that the logical volume size is extended to the size requested. If no value is specified in the command, the size is extended to the space available on the device. Both qualifiers can be combined in the same command. Both qualifiers can be combined to increase the volume expansion limit and expand the volume in one operation.
The volume must be mounted privately (nonshared disk) and allocated to the particular process. But once prepared, the file system size can be grown as many times as you would like, up to the size specified in the preparation command.
For more information about DVE, see the HP OpenVMS DCL Dictionary: N--Z, the HP OpenVMS System Services Reference Manual: GETUTC--Z, and the HP OpenVMS System Manager's Manual.
Previous | Next | Contents | Index |