使用mmap时显示can not access memory

Posted friedCoder

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用mmap时显示can not access memory相关的知识,希望对你有一定的参考价值。

参考: https://www.cnblogs.com/charlesblc/p/6263665.html

mmap使用细节

1、使用mmap需要注意的一个关键点是,mmap映射区域大小必须是物理页大小(page_size)的整倍数(32位系统中通常是4k字节)。原因是,内存的最小粒度是页,而进程虚拟地址空间和内存的映射也是以页为单位。为了匹配内存的操作,mmap从磁盘到虚拟地址空间的映射也必须是页。

2、内核可以跟踪被内存映射的底层对象(文件)的大小,进程可以合法的访问在当前文件大小以内又在内存映射区以内的那些字节。也就是说,如果文件的大小一直在扩张,只要在映射区域范围内的数据,进程都可以合法得到,这和映射建立时文件的大小无关。具体情形参见“情形三”。

3、映射建立之后,即使文件关闭,映射依然存在。因为映射的是磁盘的地址,不是文件本身,和文件句柄无关。同时可用于进程间通信的有效地址空间不完全受限于被映射文件的大小,因为是按页映射。

缺点如下:

  1. 文件如果很小,是小于4096字节的,比如10字节,由于内存的最小粒度是页,而进程虚拟地址空间和内存的映射也是以页为单位。虽然被映射的文件只有10字节,但是对应到进程虚拟地址区域的大小需要满足整页大小,因此mmap函数执行后,实际映射到虚拟内存区域的是4096个字节,11~4096的字节部分用零填充。因此如果连续mmap小文件,会浪费内存空间

  2. 变长文件不适合,文件无法完成拓展,因为mmap到内存的时候,你所能够操作的范围就确定了。

  3. 如果更新文件的操作很多,会触发大量的脏页回写及由此引发的随机IO上。所以在随机写很多的情况下,mmap方式在效率上不一定会比带缓冲区的一般写快

解决办法

        fileSize = lseek( srcFd, 0, SEEK_END );
        lseek( srcFd, 0, SEEK_SET );


        lseek( destFd, fileSize-1, SEEK_SET );//下面write的时候多了一个字符,这里减去
        write( destFd, "",  1);//cannot access memory, 扩充为真实大小
        char *destMmap = (char *)mmap( NULL, fileSize, PROT_READ|PROT_WRITE, MAP_SHARED, destFd, 0);
        if( destMmap == MAP_FAILED ){
                fprintf( stderr, "mmap error : %s.\\n", strerror(errno));
                return SHARE_MEM_WRONG;
        }

以上是关于使用mmap时显示can not access memory的主要内容,如果未能解决你的问题,请参考以下文章

为啥 MyEclipse 在编译时显示 join_table not found 错误

在没有文件路径的 Access 中组合框更改时显示不同的图像

MS-Access 报告在执行时显示设计视图

Microsoft Access 在启动时显示“缺少 APSBrowsePanes.dll”错误。 (虚拟机)

登录时显示403 Access Denied

Access sql语句运行时显示无效的sql语句是啥原因