inux中的两种共享内存。一种是我们的IPC通信System V版本的共享内存,另外的一种就是我们今天提到的存储映射I/O(mmap函数)

在说mmap之前我们先说一下普通的读写文件的原理,进程调用read或是write后会陷入内核,因为这两个函数都是系统调用,进入系统调用后,内核开始读写文件,假设内核在读取文件,内核首先把文件读入自己的内核空间,读完之后进程在内核回归用户态,内核把读入内核内存的数据再copy进入进程的用户态内存空间。实际上我们同一份文件内容相当于读了两次,先读入内核空间,再从内核空间读入用户空间。

Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改,mmap()系统调用使得进程之间可以通过映射一个普通的文件实现共享内存。普通文件映射到进程地址空间后,进程可以向访问内存的方式对文件进行访问,不需要其他系统调用(read,write)去操作。

mmap系统调用介绍

void *mmap(void *addr, size_t length, int prot, int flags,
                  int fd, off_t offset);

这就是mmap系统调用的接口,mmap函数成功返回指向内存区域的指针,图上的进程的地址空间的开始地址就是mmap函数的返回值,失败返回MAP_FAILED。

addr,某个特定的地址作为起始地址,当被设置为NULL,系统会在地址空间选择一块合适的内存区域。

length说的是内存段的长度。

prot是用来设定内存段的访问权限。

fd参数是用来被映射文件对应的文件描述符。通过open系统调用得到。offset设定从何处进行映射。

android mmap 写文件 安卓手机如何打开.mmap文件_#include

mmap使用注意事项:

android mmap 写文件 安卓手机如何打开.mmap文件_系统调用_02

利用mmap进行非血缘进程间通信代码:

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
#include<string.h>
 
struct STU
{
	int age;
	char name[20];
	char sex;
};
 
int main(int argc,char *argv[]) //这个进程用于创建映射区进行写。
{
	if(argc != 2)
	{
		printf("./a,out  file");
		exit(1);
	}
 
	struct STU student = {10,"xiaoming",'m'};
 
	int fd = open(argv[1],O_RDWR|O_CREAT|O_TRUNC,0644);
	if(fd < 0)
	{
		perror("open");
		exit(2);
	}
	ftruncate(fd,sizeof(struct STU)); //文件拓展大小。
	
	struct STU *p = (struct STU*)mmap(NULL,sizeof(struct STU),PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);//创建一个结构体大小的共享映射区。共享映射区我们可以当做数组区看待。
	if(p == MAP_FAILED)
	{
		perror("mmap");
		exit(3);
	}
	close(fd); //关闭不用的文件描述符。
	while(1)
	{
		memcpy(p,&student,sizeof(student));
		student.age++;
		sleep(1);
	}
	int ret = munmap(p,sizeof(student));
	if(ret < 0)
	{
		perror("mmumap");
		exit(4);
	}
	return 0;
}
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/mman.h>
 
struct STU
{
	int age;
	char name[20];
	char sex;
};
 
int main(int argc,char *argv[]) //这个进程读
{
	if(argc != 2)
	{
		printf("./a,out  file");
		exit(1);
	}
	int fd = open(argv[1],O_RDONLY,0644);
	if(fd < 0)
	{
		perror("open");
		exit(2);
	}
	struct STU student;
	struct STU *p = (struct STU*)mmap(NULL,sizeof(struct STU),PROT_READ,MAP_SHARED,fd,0);
	if(p == MAP_FAILED)
	{
		perror("mmap");
		exit(3);
	}
	close(fd);
	int i = 0;
	while(1)
	{
		printf("id = %d\tname = %s\t%c\n",p->age,p->name,p->sex);	
		sleep(2);
	}
	int ret = munmap(p,sizeof(student));
	if(ret < 0)
	{
		perror("mmumap");
		exit(4);
	}
	return 0;
}