Working with Memory
(or The Persistence of Memory, with a nod to Salvador Dali)
In the Process Manager
chapter of the System Architecture guide, we looked at how the OS manages memory.
This chapter describes how you can work with memory.
Let's start with some definitions. By memory, we mean anything that can be accessed via physical addresses, but there are various classifications of memory:
- RAM vs non-RAM
- RAM refers to what we typically consider to be memory; you can read from it or write to it.
Non-RAM refers to memory-mapped I/O or memory-mapped devices. For example, some hardware exposes its registers in this way. You can treat non-RAM as RAM, and it behaves somewhat as RAM, but it really isn't.
- SYSRAM vs non-SYSRAM
- This is a QNX OS distinction.
SYSRAM is any RAM that's available for general-purpose allocation by the system.
Once the system has booted, this is the memory that you can allocate by using
malloc().
If you call
mmap()
to map a file, the backing memory comes from SYSRAM.
Non-SYSRAM is whatever RAM isn't included in SYSRAM, including memory that's reserved by startup for memory pools to be used for specific purposes such as USB, graphics, or cameras.
- Pageable vs wired
- Pageable memory is reserved when you allocate it, but might not yet be backed; that is,
it might not yet be associated with physical memory.
The physical memory association can change under your feet, so you need to be careful.
Pageable memory is fine for malloc() or memory-backed files.
Wired memory is backed as soon as it's allocated.
- Specificity
- There's a range of specificity in the memory chosen, from allowing the OS to select whatever memory is
most convenient for it, to accessing memory at a particular physical address:
- If you use malloc(), you usually don't care where the backing memory really is, and there isn't a way for you to specify where it is.
- If you're memory-mapping a file, you want the content of the memory to reflect what's in the file, but you usually don't care where the backing memory is—the content might not even be in RAM yet; it might still be on the disk.
- You might need memory in a given range, such as below 4 GB.
- If you're mapping a memory-mapped device, the memory needs to be at the exact physical address identified.
- Non-contiguous, contiguous, and mostly contiguous
-
- If you call malloc() or map a file, you usually don't care if the memory is contiguous. Note that if you don't ask for contiguous memory, you'll likely get the most scattered memory available; the memory manager does this in order to reduce the fragmentation of contiguous regions in the system.
- Contiguous memory must be in one block.
- If you ask for mostly contiguous memory,
the physical memory allocator tries to get contiguous memory,
but without taking
too long
to look for it. This is handy if you want to minimize the number of page table entries, but you don't want to wait while the allocator scans all the physical memory looking for a contiguous block.
- Shared vs private
- Changes that you make to a shared memory mapping are propagated back to the backing object; private memory is your own copy.
- Memory attributes
- These include the caching policy and memory ordering.
- Object-backed vs direct mapping
- Is there an object underneath, or are you directly mapping RAM?
Let's look at an example. The pidin utility displays (among other things) information about sections of the system page. If you run pidin syspage=asinfo, the output might look like this:
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.
The memory regions in this example include the following:
- /io: non-RAM; memory-mapped I/O
- /memory: the physical addressability of the processor
- Specific uses:
- /memory/acpi_rsdp: Advanced Configuration and Power Interface's Root System Description Pointer
- /memory/below4G: addresses below 4 GB
- /memory/bootram: RAM that's reserved for processes that are in the image filesystem
- /memory/device: device-specific memory
- /memory/imagefs: location of the image filesystem
- /memory/isa: ISA devices
- /memory/lapic: local APIC (/memory/lapic.cpu_num if not all CPUs have the same LAPIC address)
- /memory/rom: read-only memory
- /memory/startup: location of startup
- RAM:
- /memory/below4G/ram
- /memory/device/ram
- /memory/isa/ram
- SYSRAM:
- /memory/below4G/ram/sysram
- /memory/device/ram/sysram
- /memory/isa/ram/sysram
The /virtual and /virtual/vboot regions aren't currently used.