mmap()
Posted Li-Yongjun
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mmap()相关的知识,希望对你有一定的参考价值。
活动地址:CSDN21天学习挑战赛
前言
之前,我们使用 devmem 命令的方式和在内核空间使用 ioremap() 的方式,操作寄存器,实现了控制 LED 亮灭的功能。
今天,我们使用一种在用户空间操作寄存器的方法来实现该功能,用到的函数就是 mmap()。
mmap()
函数原型如下
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数:
addr:映射区的开始地址,设置为 0 时表示由系统决定映射区的起始地址。需要按照页面大小对齐,否则会出错。
length:映射区的长度。长度以字节为单位,不足一内存页按一内存页处理。
prot:期望的内存保护标志,类似于可读可写等
flags:指定映射对象的类型
fd:文件标识符
offset:被映射对象内容的起点,需要按照页面大小对齐,否则会出错。
返回值:
成功时,mmap() 返回被映射区的地址,
失败时,mmap() 返回 MAP_FAILED,错误原因记录于 errno。
示例
led_mem.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#define BCM2837_GPIOFS_BASE 0x3F200000
#define GPIO_CLR_REG_OFFSET 0x28
#define GPIO_SET_REG_OFFSET 0x1C
#define BLOCK_SIZE (4 * 1024)
int main(int argc, char *argv[])
int mem_fd;
void *gpio_base_map;
int i;
mem_fd = open("/dev/mem", O_RDWR | O_NDELAY);
if (mem_fd < 0)
perror("open /dev/mem");
return -1;
gpio_base_map = mmap(NULL, BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd, BCM2837_GPIOFS_BASE);
close(mem_fd);
if (gpio_base_map == MAP_FAILED)
printf("mmap error %d\\n", (int)gpio_base_map);
return -1;
for (i = 0; i < 10; i++)
*(volatile unsigned int *)(gpio_base_map + GPIO_CLR_REG_OFFSET) = 0x7F;
printf("led on\\n");
usleep(200000);
*(volatile unsigned int *)(gpio_base_map + GPIO_SET_REG_OFFSET) = 0x7F;
printf("led off\\n");
usleep(200000);
munmap(gpio_base_map, BLOCK_SIZE);
return 0;
Makefile
CROSS_COMPILE=/home/liyongjun/project/board/buildroot/RPi3/host/bin/arm-buildroot-linux-uclibcgnueabihf-
all:
$(CROSS_COMPILE)gcc -Wall led_mem.c -o led_mem.out
测试
在 ubuntu 上交叉编译
$ make
/home/liyongjun/project/board/buildroot/RPi3/host/bin/arm-buildroot-linux-uclibcgnueabihf-gcc -Wall led_mem.c -o led_mem.out
$ cp led_mem.out ~/tftp/
在树莓派上下载、运行
# tftp -gr led_mem.out 192.168.31.223
# chmod +x led_mem.out
# ./led_mem.out
led on
led off
led on
led off
led on
led off
led on
led off
led on
led off
led on
led off
led on
led off
led on
led off
led on
led off
led on
led off
以上是关于mmap()的主要内容,如果未能解决你的问题,请参考以下文章
Linux 内核 内存管理mmap 系统调用源码分析 ⑤ ( mmap_region 函数执行流程 | mmap_region 函数源码 )
Linux 内核 内存管理mmap 系统调用源码分析 ③ ( vm_mmap_pgoff 函数执行流程 | vm_mmap_pgoff 函数源码 )