左手编程,右手年华。大家好,我是一点,关注我,带你走入编程的世界。
公众号:一点sir,关注领取编程资料
mmap是什么
mmap
是一个在 Unix 和类 Unix 系统中的 POSIX 标准系统调用,用于将一个文件或者其他对象映射到进程地址空间中的内存区域。简而言之,mmap
允许一个程序将磁盘上的文件内容直接映射到内存中,从而可以像访问普通内存一样访问文件内容。
mmap函数解释
mmap
函数的原型如下:
c
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
参数说明:
addr
:希望映射到的内存地址。通常设为NULL
,让系统自行选择映射区域的地址。length
:映射的长度,通常为文件大小。prot
:映射区域的保护方式,可以是PROT_EXEC
(可执行)、PROT_READ
(可读)、PROT_WRITE
(可写)、PROT_NONE
(不可访问)的组合。flags
:控制映射区域的特性,如MAP_SHARED
(对映射区域的修改会写回文件,允许多个进程共享映射)、MAP_PRIVATE
(私有副本,修改不写回文件)等。fd
:被映射文件的文件描述符。offset
:文件中的偏移量,通常为文件系统中分配单元的大小(如 4096 字节)。
mmap
返回值:
- 成功时,返回指向映射区域的指针。
- 失败时,返回
MAP_FAILED
(通常是(void *)-1
),并设置errno
以指示错误。
使用 mmap
后,通常还需要使用 munmap
来撤销映射,释放内存资源。
c
int munmap(void *addr, size_t length);
参数 addr
是 mmap
返回的地址,length
是映射的长度。munmap
函数在成功时返回 0,在失败时返回 -1,并设置 errno
。
示例说明
这里我用一个使用 mmap
的简单例子,它展示了如何在C语言中使用 mmap
将文件映射到内存中,并对文件内容进行读取和写入操作。
c
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
int main() {
// 打开一个文件,这里我们创建一个新文件
int fd = open("example.txt", O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 文件大小,这里我们设置为 10 个页面的大小
size_t length = 10 * sysconf(_SC_PAGESIZE);
// 调用 mmap
void *mapped_memory = mmap(NULL, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mapped_memory == MAP_FAILED) {
perror("mmap");
close(fd);
exit(EXIT_FAILURE);
}
// 写入一些数据到映射的内存区域
for (size_t i = 0; i < length; ++i) {
((char *)mapped_memory)[i] = (char)('A' + (i % 26));
}
// 等待用户输入,以便查看映射的内容
printf("Press Enter to unmap and exit...\n");
getchar();
// 撤销映射
if (munmap(mapped_memory, length) == -1) {
perror("munmap");
close(fd);
exit(EXIT_FAILURE);
}
// 关闭文件描述符
if (close(fd) == -1) {
perror("close");
exit(EXIT_FAILURE);
}
return 0;
}
我们首先打开(或创建)一个名为 "example.txt" 的文件,然后获取系统的页面大小,并将其乘以10以确定映射的长度。映射成功后,我们可以像操作普通内存一样操作这个映射区域。在这个例子中,我们用大写字母 'A' 到 'Z' 填充映射的内存。然后,程序暂停,等待用户按下回车键,之后使用 munmap
撤销映射,并关闭文件描述符。
这是一个非常简单的例子,但是基本上对于mmap
的用法做了大概的说明。
mmap的优点
使用 mmap
的主要优点包括:
-
性能:对映射区域的修改最终会回写到文件中,这比传统的 read 和 write 系统调用通常更高效,特别是对于大文件和/或多个连续的 read/write 操作。
-
简化编程模型 :通过
mmap
,程序员可以使用指针算术直接操作文件内容,而不需要编写额外的缓冲区管理代码。 -
共享内存 :
mmap
可以用来创建或访问共享内存区域,这对于进程间通信(IPC)非常有用。 -
自动管理:操作系统负责管理映射区域的内存,当映射的文件被关闭或程序结束时,映射会自动撤销。