mmap实现共享内存
发布日期:2022-02-21 17:40:29 浏览次数:44 分类:技术文章

本文共 2554 字,大约阅读时间需要 8 分钟。

mmap概念:

mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。mmap在用户空间映射调用系统中作用很大。

mmap操作提供了一种机制,让直接访问设备内存,这种机制,相比较在和互相拷贝数据,效率更高。在要求高性能的应用中比较常用。mmap映射内存必须是页面大小的整数倍,面向流的设备不能进行mmap,mmap的实现和硬件有关。

函数原型:

头文件 <sys/mman.h>

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

参数fd为即将映射到进程空间的文件描述字,一般由open()返回;fd可以指定为-1,此时须指定flags参数中的MAP_ANON,表明进行的是匿名映射(不涉及具体的文件名,避免了文件的创建及打开,很显然只能用于具有亲缘关系的进程间通信);

len是映射到调用进程地址空间的字节数,它从被映射文件开头offset个字节开始算起,一般offset设置为0,表示从文件开始映射;

prot 参数指定共享内存的访问权限。一般有PROT_READ(可读) , PROT_WRITE (可写), PROT_EXEC (可执行), PROT_NONE(不可访问)

flags由以下几个常值指定:MAP_SHARED , MAP_PRIVATE , MAP_FIXED,其中,MAP_SHARED , MAP_PRIVATE必选其一,而MAP_FIXED则不推荐使用。

参数addr指定文件应被映射到进程空间的起始地址,一般被指定一个空指针,此时选择起始地址的任务留给内核来完成。

函数的返回值为最后文件映射到进程空间的地址,进程可直接操作起始地址为该值的有效地址。

int munmap(void* start,size_t length)

该调用在进程地址空间中解除一个映射关系,addr是调用mmap()时返回的地址,len是映射区的大小。当映射关系解除后,对原来映射地址的访问将导致段错误发生。

举例说明:

/*-------------map_normalfile1.c-----------*/ #include
 #include
 #include
#include
#include
 #include
 typedef struct{  char name[4];  int age; }people; void main(int argc,char **argv)//map a normal file as shared mem: {  int fd,i;  people *p_map;  char temp;  fd = open(argv[1],O_CREAT|O_RDWR|O_TRUNC,00777);  lseek(fd,sizeof(people)*5-1,SEEK_SET);  write(fd,"",1);  p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);  close(fd);  temp='a';  for(i=0;i<10;i++)  {  temp+=1;  memcpy((*(p_map+i)).name,&temp,2);  (*(p_map+i)).age=20+i;  }  printf("initializeover\n");  sleep(10);  munmap(p_map,sizeof(people)*10);  printf("umapok\n"); }  /*-------------map_normalfile2.c-----------*/ #include
 #include
 #include
#include
 #include
 typedef struct{  char name[4];  int age; }people; void main(int argc,char **argv)//map a normal file as shared mem: {  int fd,i;  people *p_map;  fd=open(argv[1],O_CREAT|O_RDWR,00777);  p_map=(people*)mmap(NULL,sizeof(people)*10,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);  for(i=0;i<10;i++)  {  printf("name:%sage%d;\n",(*(p_map+i)).name,(*(p_map+i)).age);  }  munmap(p_map,sizeof(people)*10); }

例子使用的是:

map_normfile1首先打开或创建一个文件,并把文件的长度设置为5个people结构大小。然后从mmap()的返回地址开始,设置了10个people结构。然后,进程睡眠10秒钟,等待其他进程映射同一个文件,最后解除映射。 

  map_normfile2.c只是简单的映射一个文件,并以people数据结构的格式从mmap()返回的地址处读取10个people结构,并输出读取的值,然后解除映射。 

提问:

如果进程A在共享内存区有一个指针ptr,这个指针存在共享内存区, 这个指针指向共享内存区的某个位置(place) ,请问进程B能不能正确使用place的值? 

解释: 不能。

理由: 因为当进程B通过自己的指针读到ptr时,ptr里面存放的内容是A的某一个虚拟地址(这个虚拟地址能映射为place),但B进程取到这个地址后,按照自己的映射方式,不能找到物理空间的这个place.

 

转载地址:https://blog.csdn.net/weixin_40599276/article/details/100100396 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:C++11 中的std::function和std::bind
下一篇:二叉树的中序遍历----递归、循环、以及空间复杂度O(1)解法

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月21日 12时45分36秒