存储映射IO:
mmap(): 将一块内存或者是某一个文件的存储内容 映射到当前进程空间里面来。结果就是 我们在当前进程中访问目标空间中的数据。
NAME
mmap, munmap - map or unmap files or devices into memory
SYNOPSIS
#include <sys/mman.h>
/* 映射,返回值为映射到的最终地址。
addr: 目标内存空间 放到当前进程空间的起始地址,若为空,则函数自己找可用的位置
length:需要映射目标空间的长度
port : 映射过来的内存属性,即可以对该内存做什么操作,即映射后的操作权限
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:进程对映射过来的内存修改,只是改动当前进程空间中目标内存空间,不会同步到真实的内存空间
可选:
如:MAP_ANONYMOUS 匿名映射,当前映射不依赖于任何文件(fd选项为-1),类似于 malloc()功能,空间会被初始化为0
fd : 文件描述符,如 需要映射一个文件过来,那么需要先将目标文件打开。
offset :偏移量
从 fd 文件的 offset偏移量开始映射,映射length长度的空间到当前进程空间的addr地址,空间权限设置为port ,特殊要求是flags
*/
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
/*解除映射
对 addr地址处 映射过来的空间(大小为length) 进行解除映射
如果 mmap()的时候 flags 有MAP_ANONYMOUS 匿名映射要求,则此处munmap() 类似于 free()
*/
int munmap(void *addr, size_t length);
RETURN VALUE
On success, mmap() returns a pointer to the mapped area. On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is set to indicate the cause of the error.
On success, munmap() returns 0. On failure, it returns -1, and errno is set to indicate the cause of the error (probably to EINVAL).
实验1 :查看一段内存空间中有多少 ‘a’。 用mmap()将目标空间映射过来,并做查找处理。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
int main(int argc,char *argv[])
{
int fd;
struct stat statres;
char *str;
int i,count=0;
if(argc < 2)
{
fprintf(stderr,"Usage...\n");
exit(1);
}
fd = open(argv[1],O_RDONLY);
if(fd < 0)
{
perror("open()");
exit(1);
}
if(fstat(fd,&statres) < 0)
{
perror("fstat()");
exit(1);
}
str = mmap(NULL,statres.st_size,PROT_READ,MAP_SHARED,fd,0);
if(str == MAP_FAILED)
{
perror("mmap()");
exit(1);
}
close(fd);
for(i = 0; i < statres.st_size; i++)
{
if(str[i] == 'a')
count ++;
}
printf("%d\n",count);
munmap(str,statres.st_size);
}
实验2:父子进程之间的通信,mmap()实现共享内存。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#define MEMSIZE 1024
int main(int argc,char *argv[])
{
char *ptr;
pid_t pid;
//不依赖于任何文件fd, 相当于 malloc()一段空间后映射过来,不依赖任何文件 所以fd==-1
ptr = mmap(NULL,MEMSIZE,PROT_READ | PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);
if(ptr == MAP_FAILED)
{
perror("mmap()");
exit(1);
}
pid = fork();//先mmap 后fork
if(pid < 0)
{
perror("fork()");
munmap(ptr,MEMSIZE);
exit(1);
}
if(pid == 0) //Child write
{
strcpy(ptr,"Hello!");
munmap(ptr,MEMSIZE);
exit(0);
}
else //Parent read
{
wait(NULL);
puts(ptr);//puts()将字符串s和末尾的换行符写入标准输出。
munmap(ptr,MEMSIZE);
exit(0);
}
}