Typed memory
POSIX typed memory provides an interface that lets you open named memory objects and perform mapping operations on them.
Typed memory is useful in providing an abstraction between BSP- or board-specific address layouts and device drivers or user code. You can reserve memory in advance for specific purposes, such as graphics, and remove that memory from the system RAM that programs typically allocate from.
POSIX specifies that typed memory pools (or objects) are created and defined in an implementation-specific fashion. Under QNX OS, typed memory objects are defined from the memory regions specified in the asinfo section of the system page. Thus, typed memory objects map directly to the address space hierarchy (asinfo segments) defined by startup. The typed memory objects also inherit the properties defined in asinfo, namely the physical address (or bounds) of the memory segments.
In general, the naming and properties of the asinfo entries are arbitrary and completely under the user's control. There are, however, some mandatory entries:
- memory
- Physical addressability of the processor, which depends on the architecture.
- ram
- All of the RAM on the system. This may consist of multiple entries.
- sysram
- System RAM, which is memory that has been given to the OS to manage. This may also consist of multiple entries. The OS uses this pool for all general-purpose memory allocations on the system, including code, data, stack, heap, kernel and process manager data, shared memory objects, and memory-mapped files.
You can create additional entries, but only in startup, using the
as_add()
function (see the Startup Library
chapter of Building Embedded Systems).
The names of typed memory regions are derived directly from the names of the asinfo segments. The asinfo section itself describes a hierarchy, and so the naming of typed memory objects is a hierarchy. Their names may contain intermediate slash (/) characters that are considered as path-component separators.
Header size=0x00000108, Total Size=0x00000cd0, #Cpu=2, Type=256
Section:asinfo offset:0x00000710 size:0x00000340 elsize:0x00000020
0000) 0000000000000000-000000000000ffff o:ffff a:0000 p:100 c:0 n:/io
0020) 0000000000000000-000fffffffffffff o:ffff a:0010 p:100 c:0 n:/memory
0040) 0000000000000000-00000000ffffffff o:0020 a:0010 p:100 c:0 n:/memory/below4G
0060) 0000000000000000-0000000000ffffff o:0020 a:0010 p:100 c:0 n:/memory/isa
0080) 0000000006000000-00000000ffefffff o:0020 a:0013 p:100 c:0 n:/memory/device
00a0) 00000000fff00000-00000000ffffffff o:0020 a:0005 p:100 c:0 n:/memory/rom
00c0) 0000000000000000-000000000009f7ff o:0060 a:0017 p:100 c:0 n:/memory/isa/ram
00e0) 0000000000100000-0000000000ffffff o:0060 a:0037 p:100 c:0 n:/memory/isa/ram
0100) 0000000001000000-0000000005ffffff o:0040 a:0037 p:100 c:0 n:/memory/below4G/ram
0120) 0000000006000000-000000003fedffff o:0080 a:0017 p:100 c:0 n:/memory/device/ram
0140) 000000003ff00000-000000003fffffff o:0080 a:0017 p:100 c:0 n:/memory/device/ram
0160) 00000000000f6a00-00000000000f6a23 o:0020 a:0007 p:100 c:0 n:/memory/acpi_rsdp
0180) 00000000fee00000-00000000fee003ef o:0020 a:0003 p:100 c:0 n:/memory/lapic
01a0) 000000000142c038-0000000001c9bb7b o:0020 a:0005 p:100 c:0 n:/memory/imagefs
01c0) 0000000001400f30-000000000142c037 o:0020 a:0007 p:100 c:0 n:/memory/startup
01e0) 000000000142c038-0000000001c9bb7b o:0020 a:0007 p:100 c:0 n:/memory/bootram
0200) 0000000000000000-00000000ffffffff o:ffff a:0010 p:100 c:0 n:/virtual
0220) ffff800000001000-ffff8000000f25d0 o:0200 a:0000 p:100 c:0 n:/virtual/vboot
0240) 0000000000001000-000000000009efff o:00c0 a:0007 p:100 c:0 n:/memory/isa/ram/sysram
0260) 0000000000106000-0000000000108fff o:00e0 a:0007 p:100 c:0 n:/memory/isa/ram/sysram
0280) 000000000010f000-00000000004f6fff o:00e0 a:0007 p:100 c:0 n:/memory/isa/ram/sysram
02a0) 00000000004f8000-0000000000ffffff o:00e0 a:0027 p:100 c:0 n:/memory/isa/ram/sysram
02c0) 0000000001000000-000000000142bfff o:0100 a:0007 p:100 c:0 n:/memory/below4G/ram/sysram
02e0) 0000000001c9c000-0000000005ffffff o:0100 a:0027 p:100 c:0 n:/memory/below4G/ram/sysram
0300) 0000000006000000-000000003f2d4fff o:0120 a:0007 p:100 c:0 n:/memory/device/ram/sysram
0320) 000000003ff00000-000000003fffffff o:0140 a:0007 p:100 c:0 n:/memory/device/ram/sysram
For details about the above information, see the section on
asinfo
in the System Page
chapter of Building Embedded Systems.
You use posix_typed_mem_open() to open a typed memory object, specifying the name of the object, the access mode, and flags that indicate how the object behaves when it's mapped. The name you pass to this function follows the above naming convention. If the name starts with a leading slash (/), an exact match is done. POSIX allows an implementation to define what happens when the name doesn't start with a leading slash; in QNX OS, a tail match is done on the pathname components specified.
You can also use ampersands and vertical bars (& and |) between segments to specify intersections and unions, respectively. You can specify an arbitrary number of them; they're evaluated from left to right, but parentheses aren't supported.
Here are some examples of how posix_typed_mem_open() resolves names, using the above sample configuration:
This name: | Resolves to: |
---|---|
/memory | /memory |
isa | Fails because isa isn't a leaf in the hierarchy |
/memory/rom | /memory/rom |
/sysram | Fails because sysram isn't at the top of the hierarchy |
sysram | All sysram segments, including four occurrences of /memory/isa/ram/sysram, two occurrences of /memory/device/below4G/sysram, and two occurrences of /memory/device/ram/sysram |
below4G&sysram | The intersection of all physical address ranges for below4G
with all physical address ranges for sysram.
For example, if you have two memory regions, one being /ram/below4G with addresses from 0 to 4 GB, and the other being /ram/sysram with addresses from 1 GB to 6 GB, then below4G&sysram gives pages in the range 1 GB to 4 GB. |
Specifying a union or intersection can be more useful than specifying a full name.
As an extension to POSIX, the typed memory name hierarchy is exported through the process manager namespace under /dev/tymem. Applications can list this hierarchy and look at the asinfo entries in the system page to get information about the typed memory.
If successful, posix_typed_mem_open() returns a file descriptor for the typed memory object. What you do with the file descriptor depends on which approach you want to take:
- the POSIX approach, using mmap() to establish a memory mapping from the typed memory object
- the QNX OS approach, using shm_open() and shm_ctl(). This isn't portable, but it's more efficient and secure.
Memory that's mapped from a typed-memory file descriptor is implicitly locked.
POSIX also defines
posix_typed_mem_get_info(),
which you can use to get information about a typed memory object.
For more information about working with typed memory, see
Typed memory
in the Working with Memory
chapter of the QNX OS Programmer's Guide.