Updated: April 19, 2023 |
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 Neutrino, 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:
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.
Let's look at a sample asinfo configuration, which you can display with the pidin syspage=asinfo command:
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 Neutrino, 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:
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 Neutrino Programmer's Guide.