-
mmap(2)
#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
功能:将文件和设备映射到内存
参数:
addr 指示内核分配的地址,linux会分配附近的页,该参数一般为NULL,由内核选择地址建立映射区域
length 指定了映射区域的长度
prot
PROT_EXEC Pages may be executed.
PROT_READ Pages may be read.
PROT_WRITE Pages may be written.
PROT_NONE Pages may not be accessed.
flags
二选一:
MAP_SHARED 共享映射区域 对映射区域的更新可以被另外一个映射同一文件的进程看到,并且同步到底层的文件中
MAP_PRIVATE 私有映射 对映射区域的更新不可以被另外一个映射同一文件的进程看到,并且不同步到底层的文件中
另外 以下的标记可以选择0或多个按位或到flags中,详见man手册
MAP_ANONYMOUS 匿名映射 fd被忽略fd设置为-1 offset被忽略.
fd 指定了文件 将这个文件映射到进程的虚拟地址空间里
offset 指定了文件映射的起始位置 这个值必须是页的整数倍
返回值:
错误 MAP_FAILED被返回 errno被设置
成功 返回映射区域的起始地址 -
int munmap(void *addr, size_t length);
功能 解除文件或设备到内存的映射
参数
addr 指定了映射区域的起始地址
length 指定了长度
返回值 成功 0 错误 -1 errno被设置
匿名映射
物理地址空间 有些设备文件没有文件名.这些设备的确是一个文件但是没有记录到文件管理系统中
这类文件称为匿名文件.个人理解:匿名映射就是建立一个虚拟地址到内存中物理地址的一个映射关系,然后对虚拟内存的操作,会折射到实际的物理内存中,与非匿名映射相比,只是匿名映射时,与文件无关,匿名映射更像是标准C语言中的malloc,calloc等
#ifndef __T_STDIO_H__
#define __T_STDIO_H__
#include <stdio.h>
#define E_MSG(STR,VAL) do{\
perror(STR);\
return (VAL);\
}while(0)
#endif
匿名映射
#include <t_stdio.h>
#include <sys/mman.h>
#include <string.h>
int main(void){
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_PRIVATE | MAP_ANONYMOUS;
//建立匿名映射,物理地址空间映射到进程的虚拟地址
char *p = (char *)mmap(NULL, 1024, prot, flags, -1, 0);
if(p==MAP_FAILED) E_MSG("mmap", -1);
//使用p
strcpy(p, "hello beijing");
printf("%s\n", p);
//解除映射关系
munmap(p,1024);
return 0;
}
文件映射
#include <t_stdio.h>
#include <sys/mman.h>
#include <t_file.h>
int main(int argc, char *argv[]){
int prot = PROT_READ | PROT_WRITE;
int flags = MAP_SHARED;
//以可读可写的方式打开文件
int fd = open(argv[1], O_RDWR);
if(fd == -1) E_MSG("open", -1);
//将文件映射到进程的虚拟地址空间
int *p = (int *)mmap(NULL, 6, prot, flags, fd, 0);
if(p==MAP_FAILED){
//关闭文件描述符,不解除映射
close(fd);
E_MSG("mmap", -1);
}
//到这里已经建立起映射了
//关闭文件描述符,不解除映射
close(fd);
*p = 0x31323334;
//解除映射
munmap(p,6);
return 0;
}