 |
OpenVMS Programming Concepts Manual
13.5.6.1 Creating Sections
To create a disk file section, follow these steps:
- Open or create the disk file containing the section.
- Define which virtual blocks in the file constitute the section.
- Define the characteristics of the section.
13.5.6.2 Opening the Disk File
Before you can use a file as a section, you must open it using OpenVMS
Record Management Services (RMS). The following example shows the
OpenVMS RMS file access block ($FAB) and $OPEN macros used to open the
file and the channel specification to the SYS$CRMPSC system service
necessary for reading an existing file:
#include <rms.h>
#include <rmsdef.h>
#include <string.h>
#include <secdef.h>
struct FAB secfab;
main() {
unsigned short chan;
unsigned int status, retadr[1], pagcnt=1, flags;
char *fn = "SECTION.TST";
/* Initialize FAB fields */
secfab = cc$rms_fab;
secfab.fab$l_fna = fn;
secfab.fab$b_fns = strlen(fn);
secfab.fab$l_fop = FAB$M_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 );
flags = SEC$M_EXPREG;
chan = secfab.fab$l_stv;
status = SYS$CRMPSC(0, &retadr, 0, 0, 0, 0, flags, chan, pagcnt, 0, 0, 0);
if ((status & 1) != 1)
LIB$SIGNAL( status );
}
|
In this example, the file options parameter (FOP) indicates that the
file is to be opened for user I/O; this parameter is required so that
OpenVMS RMS assigns the channel using the access mode of the caller.
OpenVMS RMS returns the channel number on which the file is accessed;
this channel number is specified as input to SYS$CRMPSC
(chan argument). The same channel number can be used
for multiple create and map section operations.
The option RTV=--1 tells the file system to keep all of the pointers to
be mapped in memory at all times. If this option is omitted, SYS$CRMPSC
requests the file system to expand the pointer areas, if necessary.
Storage for these pointers is charged to the BYTLM quota, which means
that opening a badly fragmented file can fail with an EXBYTLM failure
status. Too many fragmented sections may cause the byte limit to be
exceeded.
The file may be a new file that is to be created while it is in use as
a section. In this case, use the $CREATE macro to open the file. If you
are creating a new file, the file access block (FAB) for the file must
specify an allocation quantity (ALQ parameter).
You can also use SYS$CREATE to open an existing file; if the file does
not exist, it is created. The following example shows the required
fields in the FAB for the conditional creation of a file:
GBLFAB: $FAB FNM=<GLOBAL.TST>, -
ALQ=4, -
FAC=PUT,-
FOP=<UFO,CIF,CBT>, -
SHR=<PUT,UPI>
.
.
.
$CREATE FAB=GBLFAB
|
When the $CREATE macro is invoked, it creates the file GLOBAL.TST if
the file does not currently exist. The CBT (contiguous best try) option
requests that, if possible, the file be contiguous. Although section
files are not required to be contiguous, better performance can result
if they are.
13.5.6.3 Defining the Section Extents
After the file is opened successfully, SYS$CRMPSC can create a section
either from the entire file or from certain portions of it. The
following arguments to SYS$CRMPSC define the extents of the file that
constitute the section:
- pagcnt (page count). This argument is required. It
indicates the number of virtual blocks that will be mapped. These
blocks correspond to pages in the section.
- vbn (virtual block number). This argument is
optional. It defines the number of the virtual block in the file that
is the beginning of the section. If you do not specify this argument,
the value 1 is passed (the first virtual block in the file is the
beginning of the section). If you have specified physical page frame
number (PFN) mapping, the vbn argument specifies the
starting PFN. The system does not allow you to specify a virtual block
number outside of the file.
13.5.6.4 Defining the Section Characteristics
The flags argument to SYS$CRMPSC defines the following
section characteristics:
- Whether it is a private section or a global section. The default is
to create a private section.
- How the pages of the section are to be treated when they are copied
into physical memory or when a process refers to them. The pages in a
section can be either or both of the following:
- Read/write or read-only
- Created as demand-zero pages or as copy-on-reference pages,
depending on how the processes are going to use the section and whether
the file contains any data (see Section 13.5.6.10)
- Whether the section is to be mapped to a disk file or to specific
physical page frames (see Section 13.5.6.15).
Table 13-2 shows the flag bits that must be set for specific
characteristics.
Table 13-2 Flag Bits to Set for Specific Section Characteristics on VAX Systems
|
Section to Be Created |
|
Correct Flag Combinations |
Private |
Global |
PFN Private |
PFN Global |
Shared Memory |
SEC$M_GBL
|
0
|
1
|
0
|
1
|
1
|
SEC$M_CRF
|
Optional
|
Optional
|
0
|
0
|
0
|
SEC$M_DZRO
|
Optional
|
Optional
|
0
|
0
|
Optional
|
SEC$M_WRT
|
Optional
|
Optional
|
Optional
|
Optional
|
Optional
|
SEC$M_PERM
|
Not used
|
Optional
|
Optional
|
1
|
1
|
SEC$M_SYSGBL
|
Not used
|
Optional
|
Not used
|
Optional
|
Optional
|
SEC$M_PFNMAP
|
0
|
0
|
1
|
1
|
0
|
SEC$M_EXPREG
|
Optional
|
Optional
|
Optional
|
Optional
|
Optional
|
SEC$M_PAGFIL
|
0
|
Optional
|
0
|
0
|
0
|
When you specify section characteristics, the following restrictions
apply:
- Global sections cannot be both demand-zero and copy-on-reference.
- Demand-zero sections must be writable.
- Shared memory private sections are not allowed.
13.5.6.5 Defining Global Section Characteristics
If the section is a global section, you must assign a character string
name (gsdnam argument) to it so that other processes
can identify it when they map it. The format of this character string
name is explained in Section 13.5.6.6.
The flags argument specifies the following types of
global sections:
- Group temporary (the default)
- Group permanent
- System temporary
- System permanent
Group global sections can be shared only by processes executing with
the same group number.
The name of a group global section is implicitly qualified by the group
number of the process that created it. When other processes map it,
their group numbers must match.
A temporary global section is automatically deleted when no processes
are mapped to it, but a permanent global section remains in existence
even when no processes are mapped to it. A permanent global section
must be explicitly marked for deletion with the Delete Global Section
(SYS$DGBLSC) system service.
You need the user privileges PRMGBL and SYSGBL to create permanent
group global sections or system global sections (temporary or
permanent), respectively.
A system global section is available to all processes in the system.
Optionally, a process creating a global section can specify a
protection mask (prot argument), restricting all
access or a type of access (read, write, execute, delete) to other
processes.
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 );
}
|
|