本文共 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 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!