 |
HP OpenVMS Programming Concepts Manual
13.5.6.6 Global Section Name
The gsdnam argument specifies a descriptor that points
to a character string.
Translation of the gsdnam argument proceeds in the
following manner:
- The current name string is prefixed with GBL$ and the result is
subject to logical name translation.
- If the result is a logical name, step 1 is repeated until
translation does not succeed or until the number of translations
performed exceeds the number specified by the system parameter
LNM$C_MAXDEPTH.
- The GBL$ prefix is stripped from the current name string that could
not be translated. This current string is the name of the global
section.
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:
- GBL$ is prefixed to GDSDATA.
- GBL$GSDATA is translated to GSDATA_001. (Further translation is not
successful. When logical name translation fails, the string is passed
to the service.)
There are three exceptions to the logical name translation method
discussed in this section:
- If the name string starts with an underscore (_), the operating
system strips the underscore and considers the resultant string to be
the actual name (that is, further translation is not performed).
- If the name string is the result of a logical name translation,
then the name string is checked to see whether it has the
terminal attribute. If the name string is marked with
the terminal attribute, the operating system considers
the resultant string to be the actual name (that is, further
translation is not performed).
- If the global section has a name in the format name_nnn,
the operating system first strips the underscore and the digits
(nnn), then translates the resultant name according to the
sequence discussed in this section, and finally reappends the
underscore and digits. The system uses this method in conjunction with
known images and shared files installed by the system manager.
13.5.6.7 Mapping Sections
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:
- A base register or pointer and predefined symbolic offset names
- Labels defining offsets of an absolute program section or structure
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
- The OPEN macro opens the section file defined in the file access
block SECFAB. (The FOP parameter to the $FAB macro must specify the UFO
option.)
- SYS$CRMPSC uses the addresses specified at MAPRANGE to specify an
input range of addresses into which the section will be mapped. The
pagcnt argument requests that only 4 pages of the file
be mapped.
- The flags argument requests that the pages in the
section have read/write access. The symbolic flag definitions for this
argument are defined in the $SECDEF macro. Note that the file access
field (FAC parameter) in the FAB also indicates that the file is to be
opened for writing.
- When SYS$CRMPSC completes, the addresses of the 4 pages that were
mapped are returned in the output address array at RETRANGE. The
address of the beginning of the section is placed in general register
6, which serves as a pointer to the section.
13.5.6.8 Mapping Global Sections
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:
- A version identification (ident argument),
indicating the version number of the global section (when multiple
versions exist) and whether more recent versions are acceptable to the
process.
- A relative page number (relpag argument) that
specifies the page number relative to the beginning of the section to
begin mapping the section. In this way, processes can use only portions
of a section. Additionally, a process can map a piece of a section into
a particular address range and subsequently map a different piece of
the section into the same virtual address range.
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 13.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 13.5.6.10 shows one process (ORION) creating a
global section and a second process (CYGNUS) mapping the section.
13.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.
13.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:
- If the call to SYS$CRMPSC requested that pages in the section be
treated as demand-zero pages, these pages are initialized to zero when
they are created in physical memory. If the file is either a new file
being created as a section or a file being completely rewritten,
demand-zero pages provide a convenient way of initializing the pages.
The pages are paged back into the section file.
- When the virtual address space is deleted, all unreferenced pages
are written back to the file as zeros. This causes the file to be
initialized, no matter how few pages were modified.
- If the call to SYS$CRMPSC requested that pages in the section be
copy-on-reference pages, each process that maps to the section receives
its own copy of the section, on a page-by-page basis from the file, as
it refers to them. These pages are never written back into the section
file but are paged to the paging file as needed.
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 );
}
|
- The processes ORION and CYGNUS are in the
same group. Each process first associates with a common event flag
cluster named FLAG_CLUSTER to use common event flags to synchronize its
use of the section.
- The process ORION creates the global section
named GLOBAL_SECTION, specifying section flags that indicate that it is
a global section (SEC$M_GBL) and has read/write access. Input and
output address arrays, the page count parameter, and the channel number
arguments are not shown; procedures for specifying them are the same,
as shown in this example.
- The process CYGNUS associates with the common
event flag cluster and waits for the flag defined as FLGSET; ORION sets
this flag when it has finished creating the section. To map the
section, CYGNUS specifies the input and output address arrays, the flag
indicating that it is a global section, and the global section name.
The number of pages mapped is the same as that specified by the creator
of the section.
13.5.6.11 Reading and Writing Data Sections
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.
13.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:
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
|
13.5.6.13 Writing Back Sections
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 HP OpenVMS System Services Reference Manual.
13.5.6.14 Image Sections
Global sections can contain shareable code. The operating system uses
global sections to implement shareable code, as follows:
- The object module containing code to be shared is linked to produce
a shareable image. The shareable image is not, in itself, executable.
It contains a series of sections called image sections.
- You link private object modules with the shareable image to produce
an executable image. No code or data from the shareable image is put
into the executable image.
- The system manager uses the INSTALL command to create a permanent
global section from the shareable image file, making the image sections
available for sharing.
- When you run the executable image, the operating system
automatically maps the global sections created by the INSTALL command
into the virtual address space of your process.
For details about how to create and identify shareable images and how
to link them with private object modules, see the HP OpenVMS Linker Utility Manual. For
information about how to install shareable images and make them
available for sharing as global sections, see the HP OpenVMS System Manager's Manual.
13.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
either 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).
Caution
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.
|
13.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 both 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 HP 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).
!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
|
|