Lighting an LED on Linux with mmap: From Folklore to Kernel Memory Mapping
The article uses a cultural analogy about Emperor Yongzheng to introduce the concept of mapping, then explains how Linux's mmap can map a physical GPIO register into user space, provides a complete code example for toggling an LED, and discusses mmap's broader uses and performance trade‑offs.
From Folklore to Memory Mapping
Observing how male and female viewers picture Emperor Yongzheng differently, the author draws a parallel with the folk practice of "扎小人" (stabbing a paper figure) – a technique that creates a symbolic link between something you can manipulate and the target you cannot.
In Linux kernel development a similar idea is realized with mmap : you cannot directly access a hardware register from user space, so you create a mapping that links a user‑space virtual address to the physical address of the register.
Core Idea of mmap
mmap maps a physical memory region into a process’s virtual address space, allowing the process to read or write the hardware simply by dereferencing a pointer. The mapping is performed by the kernel, which translates virtual addresses to the underlying physical addresses.
Typical usage steps:
Open /dev/mem (or another device file) with open().
Call mmap() with appropriate length, protection flags, and the physical base address.
Cast the returned pointer to the appropriate type and read/write the register.
mmap Function Prototype
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);Parameters:
addr : usually NULL, letting the kernel choose the virtual address.
length : size of the region to map.
prot : protection flags (e.g., PROT_READ | PROT_WRITE).
flags : MAP_SHARED or MAP_PRIVATE.
fd : file descriptor of the device (e.g., open("/dev/mem", O_RDWR|O_SYNC)).
offset : physical address of the region; must be aligned to the system page size (typically 4096 bytes).
Practical Example: Toggling an LED via GPIO
Assume the GPIO control register is at physical address 0x43C00000. The following code opens /dev/mem, maps the register, and writes a pattern that makes the LED blink:
#define AXI_GPIO_BASEADDR 0x43C00000
int memfd = open("/dev/mem", O_RDWR | O_SYNC);
if (memfd == -1) {
printf("Can't open /dev/mem
");
return -1;
}
unsigned int *led_gpio = (unsigned int *)mmap(
NULL, MMAP_SIZE, PROT_READ | PROT_WRITE,
MAP_SHARED, memfd, AXI_GPIO_BASEADDR);
// Write alternating bits 0x0101 to toggle the LED
*led_gpio = 0x0101;After the mapping, any write to *led_gpio is reflected in the physical GPIO register, causing the LED to flash.
Other mmap Applications
Beyond GPIO, mmap is commonly used for:
Inter‑process communication via shared memory.
Mapping block devices to avoid extra copy operations; the data is placed in the page cache and accessed directly from user space.
While mmap can eliminate a copy between kernel and user buffers, it introduces page‑fault overhead, which may offset the performance gain in many scenarios.
Performance Considerations
When mapping large files or devices, the initial access triggers a page‑fault that loads the required page into memory. This fault handling is more expensive than a simple read() / write() copy for small, infrequent accesses, so mmap is most beneficial when the mapped region is accessed repeatedly.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
