c - 使用 munmap 时回收更高的页面

标签 c mmap

在 Mac 上,我使用 munmap 可以看到更高的页面回收率。

我的munmap的返回值为0,这表明请求的页面已成功取消映射。

当我使用以这种方式映射和取消映射的内存测试程序时,为什么会看到更高的页面回收量?

有没有办法调试 munmap 并查看我对该函数的调用是否对传递给它的映射内存没有执行任何操作。

我使用“/usr/bin/time -l”来查看运行程序时获得的页面回收量。每当我使用 munmap 时,我的页面回收量都会比不使用时更高。

int           main(void)          
{                                                           
        int i = 0; char *addr;
        while (i < 1024)
        {
            addr = mmap(0, getpagesize(), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
            addr[0] = 23;
            if (!munmap(addr, getpagesize()))
                print("Success\n");
            i++;
        }


        return (NULL);                                      
}

关于分配

当我调用 munmap 时:

  • 我向它传递的指针与它给我的指针相同。
  • 我检查返回值并检查它是否为 0 <-- 这是我大部分时间得到的结果。

我做了一个测试程序,我调用 mmap 1024 次,并且 munmap 也调用了同样的次数。

当我不调用munmap时,回收的页面在1478区域内,并且该值与我调用munmap时相同。

如何检查我对该内存的使用是否正确?

最佳答案

关于mmap需要记住的重要一点是MAP_ANONYMOUS内存必须清零。因此,通常发生的情况是,内核将映射一个仅包含零的页框 - 并且仅当写入命中该页时,才会将读写映射的零页映射到位。

然而,这就是内核无法立即重用原始映射页面的原因 - 它不知道只有页面的第一个字节是脏的 - 相反,它必须将该页面上的所有 4 kiB 字节清零可以在新的匿名映射中返回给进程。因此,在这两个示例中,至少发生了 1024 个页面错误。

如果内存不需要清零,例如 Linux 有一个名为 MAP_UNINITIALIZED 的额外标志,它告诉内核页面不需要清零,但它仅在嵌入式设备中可用:

MAP_UNINITIALIZED (since Linux 2.6.33)

Don't clear anonymous pages. This flag is intended to improve performance on embedded devices. This flag is honored only if the kernel was configured with the
CONFIG_MMAP_ALLOW_UNINITIALIZED option. Because of the security implications, that option is normally enabled only on embedded devices (i.e., devices where one has complete control of the contents of user memory).

我猜它在通用 Linux 内核中不可用的原因是因为内核不跟踪先前映射页框的进程,因此该页可能会泄漏来自敏感进程的信息。

<小时/>

bzero 自己对页面进行归零不会影响性能 - 内核不会知道它已被归零,因为没有硬件支持它的架构 - 然后 更便宜在页面上写入零,而不是检查页面是否充满了全零并且然后在 99.9999999 % 的情况下无论如何都在其上写入零。

关于c - 使用 munmap 时回收更高的页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57073719/

相关文章:

python - 将 mmap 与 popen 一起使用

python - 如何将 mmap 中的行读入字典?

c - 如何将 C 文件编译成可执行 (.exe) 文件?

linux - 文件如何映射到进程地址空间?

c - mmap 的最小尺寸

c - 打印带空格的函数入口和导出

linux - 将页面插入大型 mmap() 文件而不复制数据

c - 全局变量编译错误

c - C 数组中的查询

c - 以下是什么意思。 C 语言中符号类型的二进制表示?