Updated: 11 December 1998 |
OpenVMS Programming Concepts Manual
Previous | Contents | Index |
The gsdnam argument specifies a descriptor that points to a character string.
Translation of the gsdnam argument proceeds in the following manner:
For example, assume that you have made the following logical name assignment:
$ DEFINE GBL$GSDATA GSDATA_001 |
Your program contains the following statements:
#include <descrip.h> . . . $DESCRIPTOR(gsdnam,"GSDATA"); . . . status = sys$crmpsc(&gsdnam, ...); |
The following logical name translation takes place:
There are three exceptions to the logical name translation method discussed in this section:
When you call SYS$CRMPSC to create or map a section, or both, you must provide the service with a range of virtual addresses (inadr argument) into which the section is to be mapped.
If you know specifically which pages the section should be mapped into, you provide these addresses in a 2-longword array. For example, to map a private section of 10 pages into virtual pages 10 through 19 of the program region, specify the input address array as follows:
unsigned int maprange[1]; maprange[0]= 0x1400; /* Address (hex) of page 10 */ maprange[1]= 0x2300; /* Address (hex) of page 19 */ |
You do not need to know the explicit addresses to provide an input address range. If you want the section mapped into the first available virtual address range in the program region (P0) or the control region (P1), you can specify the SEC$M_EXPREG flag bit in the flags argument. In this case, the addresses specified by the inadr argument control whether the service finds the first available space in P0 or P1. The value specified or defaulted for the pagcnt argument determines the number of pages mapped. The following example shows part of a program used to map a section at the current end of the program region:
unsigned int status, inadr[1], retadr[1], flags; inadr[0]= 0x200; /* Any program (P0) region address */ inadr[1]= 0x200; /* Any P0 address (can be same) */ . . . /* Address range returned in retadr */ flags = SEC$M_EXPREG; status = sys$crmpsc(&inadr, &retadr, flags, ...); |
The addresses specified do not have to be currently in the virtual address space of the process. SYS$CRMPSC creates the required virtual address space during the mapping of the section. If you specify the retadr argument, the service returns the range of addresses actually mapped.
After a section is mapped successfully, the image can refer to the pages using one of the following:
The following example shows part of a program used to create and map a process section:
#include <rms.h> #include <rmsdef.h> #include <string.h> #include <secdef.h> struct FAB secfab; main() { unsigned short chan; unsigned int status, inadr[1], retadr[1], pagcnt=1, flags; char *fn = "SECTION.TST"; /* Initialize FAB fields */ secfab = cc$rms_fab; secfab.fab$b_fac = FAB$M_PUT; secfab.fab$b_shr = FAB$M_SHRGET || FAB$V_SHRPUT || FAB$V_UPI; secfab.fab$l_fna = fn; secfab.fab$b_fns = strlen(fn); secfab.fab$l_fop = FAB$V_CIF; secfab.fab$b_rtv = -1; /* Create a file if none exists */ status = SYS$CREATE( &secfab, 0, 0 ); if ((status & 1) != 1) LIB$SIGNAL( status ); inadr[0] = X1400; inadr[1] = X2300; flags = SEC$M_WRT; chan = secfab.fab$l_stv; status = SYS$CRMPSC(&inadr, &retadr, 0, 0, 0, 0, flags, chan, pagcnt, 0, 0, 0); if ((status & 1) != 1) LIB$SIGNAL( status ); } |
Notes on Example
A process that creates a global section can map that global section. Then other processes can map it by calling the Map Global Section (SYS$MGBLSC) system service.
When a process maps a global section, it must specify the global section name assigned to the section when it was created, whether it is a group or system global section, and whether it wants read-only or read/write access. The process may also specify the following:
To specify that the global section being mapped is located in physical memory that is being shared by multiple processors, you can include the shared memory name in the gsdnam argument character string (see Section 21.5.6.6). A demand-zero global section in memory shared by multiple processors must be mapped when it is created.
Cooperating processes can issue a call to SYS$CRMPSC to create and map the same global section. The first process to call the service actually creates the global section; subsequent attempts to create and map the section result only in mapping the section for the caller. The successful return status code SS$_CREATED indicates that the section did not already exist when the SYS$CRMPSC system service was called. If the section did exist, the status code SS$_NORMAL is returned.
The example in Section 21.5.6.10 shows one process (ORION) creating a
global section and a second process (CYGNUS) mapping the section.
21.5.6.9 Global Page-File Sections
Global page-file sections are used to store temporary data in a global section. A global page-file section is a section of virtual memory that is not mapped to a file. The section can be deleted when processes have finished with it. (Contrast this to demand-zero pages, where initialization is not necessary but the pages are saved in a file.) The system parameter GBLPAGFIL controls the total number of global page-file pages in the system.
To create a global page-file section, you must set the flag bits SEC$M_GBL and SEC$M_PAGFIL in the flags argument to the Create and Map Section (SYS$CRMPSC) system service. The channel (chan argument) must be 0.
You cannot specify the flag bit SEC$M_CRF with the flag bit
SEC$M_PAGFIL.
21.5.6.10 Section Paging
The first time an image executing in a process refers to a page that was created during the mapping of a disk file section, the page is copied into physical memory. The address of the page in the virtual address space of a process is mapped to the physical page. During the execution of the image, normal paging can occur; however, pages in sections are not written into the page file when they are paged out, as is the normal case. Rather, if they have been modified, they are written back into the section file on disk. The next time a page fault occurs for the page, the page is brought back from the section file.
If the pages in a section were defined as demand-zero pages or copy-on-reference pages when the section was created, the pages are treated differently, as follows:
In the case of global sections, more than one process can be mapped to the same physical pages. If these pages need to be paged out or written back to the disk file defined as the section, these operations are done only when the pages are not in the working set of any process.
In the following example, process ORION creates a global section, and process CYGNUS maps to that section:
/* Process ORION */ #include <rms.h> #include <rmsdef.h> #include <string.h> #include <secdef.h> #include <descrip.h> struct FAB gblfab; main() { unsigned short chan; unsigned int status, flags, efn=65; char *fn = "SECTION.TST"; $DESCRIPTOR(name, "FLAG_CLUSTER"); /* Common event flag cluster name */ $DESCRIPTOR(gsdnam, "GLOBAL_SECTION"); /* Global section name */ (1)status = SYS$ASCEFC(efn, &name, 0); if ((status & 1) != 1) LIB$SIGNAL( status ); /* Initialize FAB fields */ gblfab = cc$rms_fab; gblfab.fab$l_alq = 4; gblfab.fab$b_fac = FAB$M_PUT; gblfab.fab$l_fnm = fn; gblfab.fab$l_fop = FAB$M_CIF | FABM$_CBT; . . . /* Create a file if none exists */ (2)status = SYS$CREATE( &gblfab, 0, 0 ); if ((status & 1) != 1) LIB$SIGNAL( status ); flags = SEC$M_GBL || SEC$M_WRT; status = SYS$CRMPSC(0, 0, 0, flags, &gsdnam, ...); if ((status & 1) != 1) LIB$SIGNAL( status ); status = SYS$SETEF(efn); if ((status & 1) != 1) LIB$SIGNAL( status ); . . . } /* Process CYGNUS */ unsigned int status, efn=65; $DESCRIPTOR(cluster,"FLAG_CLUSTER"); $DESCRIPTOR(section,"GLOBAL_SECTION"); . . . (3)status = SYS$ASCEFC(efn, &cluster, 0); if ((status & 1) != 1) LIB$SIGNAL( status ); status = SYS$WAITFR(efn); if ((status & 1) != 1) LIB$SIGNAL( status ); status = SYS$MGBLSC(&inadr, &retadr, 0, flags, §ion, 0, 0); if ((status & 1) != 1) LIB$SIGNAL( status ); } |
Read/write sections provide a way for a process or cooperating processes to share data files in virtual memory.
The sharing of global sections may involve application-dependent synchronization techniques. For example, one process can create and map to a global section in read/write fashion; other processes can map to it in read-only fashion and interpret data written by the first process. Alternatively, two or more processes can write to the section concurrently. (In this case, the application must provide the necessary synchronization and protection.)
After a file is updated, the process or processes can release (or unmap) the section. The modified pages are then written back into the disk file defined as a section.
When this is done, the revision number of the file is incremented, and
the version number of the file remains unchanged. A full directory
listing indicates the revision number of the file and the date and time
that the file was last updated.
21.5.6.12 Releasing and Deleting Sections
A process unmaps a section by deleting the virtual addresses in its own virtual address space to which it has mapped the section. If a return address range was specified to receive the virtual addresses of the mapped pages, this address range can be used as input to the Delete Virtual Address Space (SYS$DELTVA) system service, as follows:
$DELTVA_S INADR=RETRANGE |
When a process unmaps a private section, the section is deleted; that is, all control information maintained by the system is deleted. A temporary global section is deleted when all processes that have mapped to it have unmapped it. Permanent global sections are not deleted until they are specifically marked for deletion with the Delete Global Section (SYS$DGBLSC) system service; they are then deleted when no more processes are mapped.
Note that deleting the pages occupied by a section does not delete the section file but rather cancels the process's association with the file. Moreover, when a process deletes pages mapped to a read/write section and no other processes are mapped to it, all modified pages are written back into the section file.
After a section is deleted, the channel assigned to it can be deassigned. The process that created the section can deassign the channel with the Deassign I/O Channel (SYS$DASSGN) system service, as follows:
$DASSGN_S CHAN=GBLFAB+FAB$L_STV |
Because read/write sections are not normally updated on disk until the physical pages they occupy are paged out or until all processes referring to the section have unmapped it, a process should ensure that all modified pages are successfully written back into the section file at regular intervals.
The Update Section File on Disk (SYS$UPDSEC) system service writes the
modified pages in a section into the disk file. SYS$UPDSEC is described
in the OpenVMS System Services Reference Manual.
21.5.6.14 Image Sections
Global sections can contain shareable code. The operating system uses global sections to implement shareable code, as follows:
For details about how to create and identify shareable images and how
to link them with private object modules, see the OpenVMS Linker Utility Manual. For
information about how to install shareable images and make them
available for sharing as global sections, see the OpenVMS System Manager's Manual.
21.5.6.15 Page Frame Sections
A page frame section is one or more contiguous pages of physical memory or I/O space that have been mapped as a section. One use of page frame sections is to map to an I/O page, thus allowing a process to read device registers. A process mapped to an I/O page can also connect to a device interrupt vector.
A page frame section differs from a disk file section in that it is not associated with a particular disk file and is not paged. However, it is similar to a disk file section in most other respects: you create, map, and define the extent and characteristics of a page frame section in essentially the same manner as you do for a disk file section.
To create a page frame section, you must specify page frame number (PFN) mapping by setting the SEC$M_PFNMAP flag bit in the flags argument to the Create and Map Section (SYS$CRMPSC) system service. The vbn argument is now used to specify that the first page frame is to be mapped instead of the first virtual block. You must have the user privilege PFNMAP to create or delete a page frame section but not to map to an existing one.
Because a page frame section is not associated with a disk file, you do not use the relpag, chan, and pfc arguments to the SYS$CRMPSC service to create or map this type of section. For the same reason, the SEC$M_CRF (copy-on-reference) and SEC$M_DZRO (demand-zero) bit settings in the flags argument do not apply. Pages in page frame sections are not written back to any disk file (including the paging file).
You must use caution when working with page frame sections. If you permit write access to the section, each process that writes to it does so at its own risk. Serious errors can occur if a process writes incorrect data or writes to the wrong page, especially if the page is also mapped by the system or by another process. Thus, any user who has the PFNMAP privilege can damage or violate the security of a system. |
21.5.7 Example of Using Memory Management System Services
In the following example, two programs are communicating through a global section. The first program creates and maps a global section (by using SYS$CRMPSC) and then writes a device name to the section. This program also defines the device terminal and process names and sets the event flags that synchronize the processes.The second program maps the section (by using SYS$MGBLSC) and then reads the device name and the process that allocated the device and any terminal allocated to that process. This program also writes the process named to the terminal global section where the process name can be read by the first program.
The common event cluster is used to synchronize access to the global section. The first program sets REQ_FLAG to indicate that the device name is in the section. The second program sets INFO_FLAG to indicate that the process and terminal names are available.
Data in a section must be page aligned. The following is the option file used at link time that causes the data in the common area named DATA to be page aligned:
PSECT_ATTR = DATA, PAGE
For high-level language usage, use the solitary attribute of the linker. See the OpenVMS Linker Utility Manual for an explanation of how to use the solitary attribute.
Before executing the first program, you need to write a user-open routine that sets the user open bit (FAB$V_UFO) of the FAB options longword (FAB$L_FOP). The user-open routine would then read the channel number that the file is opened on from the status longword (FAB$L_STV) and return that channel number to the main program by using a common block (CHANNEL in this example).
#1 |
---|
!This is the program that creates the global section. ! Define global section flags INCLUDE '($SECDEF)' ! Mask for section flags INTEGER SEC_MASK ! Logical unit number for section file INTEGER INFO_LUN ! Channel number for section file ! (returned from useropen routine) INTEGER SEC_CHAN COMMON /CHANNEL/ SEC_CHAN ! Length for the section file INTEGER SEC_LEN ! Data for the section file CHARACTER*12 DEVICE, 2 PROCESS CHARACTER*6 TERMINAL COMMON /DATA/ DEVICE, 2 PROCESS, 2 TERMINAL ! Location of data INTEGER PASS_ADDR (2), 2 RET_ADDR (2) ! Two common event flags INTEGER REQUEST_FLAG, 2 INFO_FLAG DATA REQUEST_FLAG /70/ DATA INFO_FLAG /71/ ! User-open routines INTEGER UFO_CREATE EXTERNAL UFO_CREATE . . . ! Open the section file STATUS = LIB$GET_LUN (INFO_LUN) IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS)) SEC_MASK = SEC$M_WRT .OR. SEC$M_DZRO .OR. SEC$M_GBL ! (Last element - first element + size of last element + 511)/512 SEC_LEN = ( (%LOC(TERMINAL) - %LOC(DEVICE) + 6 + 511)/512 ) OPEN (UNIT=INFO_LUN, 2 FILE='INFO.TMP', 2 STATUS='NEW', 2 INITIALSIZE = SEC_LEN, 2 USEROPEN = UFO_CREATE) ! Free logical unit number and map section CLOSE (INFO_LUN) ! Get location of data PASS_ADDR (1) = %LOC (DEVICE) PASS_ADDR (2) = %LOC (TERMINAL) STATUS = SYS$CRMPSC (PASS_ADDR, ! Address of section 2 RET_ADDR, ! Addresses mapped 2 , 2 %VAL(SEC_MASK), ! Section mask 2 'GLOBAL_SEC', ! Section name 2 ,, 2 %VAL(SEC_CHAN), ! I/O channel 2 ,,,) IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS)) ! Create the subprocess STATUS = SYS$CREPRC (, 2 'GETDEVINF', ! Image 2 ,,,,, 2 'GET_DEVICE', ! Process name 2 %VAL(4),,,) ! Priority IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS)) ! Write data to section DEVICE = '$FLOPPY1' ! Get common event flag cluster and set flag STATUS = SYS$ASCEFC (%VAL(REQUEST_FLAG), 2 'CLUSTER',,) IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS)) STATUS = SYS$SETEF (%VAL(REQUEST_FLAG)) IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS)) ! When GETDEVINF has the information, INFO_FLAG is set STATUS = SYS$WAITFR (%VAL(INFO_FLAG)) IF (.NOT. STATUS) CALL LIB$SIGNAL(%VAL(STATUS)) . . . ! This is the program that maps to the global section ! created by the previous program. ! Define section flags INCLUDE '($SECDEF)' ! Mask for section flags INTEGER SEC_MASK ! Data for the section file CHARACTER*12 DEVICE, 2 PROCESS CHARACTER*6 TERMINAL COMMON /DATA/ DEVICE, 2 PROCESS, 2 TERMINAL ! Location of data INTEGER PASS_ADDR (2), 2 RET_ADDR (2) ! Two common event flags INTEGER REQUEST_FLAG, 2 INFO_FLAG DATA REQUEST_FLAG /70/ DATA INFO_FLAG /71/ . . . ! Get common event flag cluster and wait ! for GBL1.FOR to set REQUEST_FLAG STATUS = SYS$ASCEFC (%VAL(REQUEST_FLAG), 2 'CLUSTER',,) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) STATUS = SYS$WAITFR (%VAL(REQUEST_FLAG)) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Get location of data PASS_ADDR (1) = %LOC (DEVICE) PASS_ADDR (2) = %LOC (TERMINAL) ! Set write flag SEC_MASK = SEC$M_WRT ! Map the section STATUS = SYS$MGBLSC (PASS_ADDR, ! Address of section 2 RET_ADDR, ! Address mapped 2 , 2 %VAL(SEC_MASK), ! Section mask 2 'GLOBAL_SEC',,) ! Section name IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) ! Call GETDVI to get the process ID of the ! process that allocated the device, then ! call GETJPI to get the process name and terminal ! name associated with that process ID. ! Set PROCESS equal to the process name and ! set TERMINAL equal to the terminal name. . . . ! After information is in GLOBAL_SEC STATUS = SYS$SETEF (%VAL(INFO_FLAG)) IF (.NOT. STATUS) CALL LIB$SIGNAL (%VAL(STATUS)) END |
Previous | Next | Contents | Index |
Copyright © Compaq Computer Corporation 1998. All rights reserved. Legal |
5841PRO_057.HTML
|