繁体   English   中英

为什么调用大尺寸的mmap()不会失败?

[英]Why does calling mmap() with large size not fail?

我尝试使用mmap()来操纵虚拟内存。 我想保留并提交一个内存区域。 我测试了这段代码:

const unsigned long gygabyte = 1024 * 1024 * 1024;
const unsigned long gygabyteCount = 2;
const unsigned long maxCapacity = gygabyteCount * gygabyte;

int main()
{
    char* pMemory;

    pMemory = (char*)mmap(NULL, maxCapacity, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if ( mprotect(pMemory, maxCapacity, PROT_READ | PROT_WRITE) != 0 )
    {
        cout << "Memory Allocation has failed" << endl;
    }
    usleep(-1);

    return 0;
}

我从终端运行了我的程序的多个副本(例如6)。 我从没看过“内存分配失败”。 我在具有4GB RAM的64位Ubuntu上运行。 谁能告诉我一些有关此的信息?

mmap保留了进程的虚拟地址空间的一个区域,但没有立即为其分配物理RAM。 因此,在64位平台上,您可以保留大量资源而不会出现故障(尽管您仍然需要检查是否有故障;示例代码不需要)。 RAM的物理页在以后访问内存时分配。

mprotect只是更改保留内存的读/写访问权限; 它也不会使其驻留在RAM中。 通过传递PROT_READ | PROT_WRITE您将获得相同的效果PROT_READ | PROT_WRITE PROT_READ | PROT_WRITE而不是PROT_NONE进行mmap ,并删除对mprotect的调用。

如果您需要立即将内存驻留在RAM中,则可以使用mlock 如果没有足够的RAM,它将失败。 在许多Linux平台(包括Ubuntu)上,存在资源限制( RLIMIT_MEMLOCK ),该限制限制了任何进程可以锁定的内存量。 您可以使用ulimit -l进行调整。

mmap对于准备所需的内存映射很有用,但不会将其分配给程序。 内核负责,当你访问它分配内存,这样的mmap -ing 8 GB有可能在一个4GB内存,如果不同时访问这些8GB。

您应该首先检查mmap的结果。 如果返回MAP_FAILED ,则表示分配失败。 内核实际上不会一次分配太多内存,而是在您访问该块的相应区域时按需映射物理或交换的空间。

在您的特定情况下,您不需要单独调用mprotect ,因为可以在调用mmap时为整个区域传递这些标志:

pMemory = mmap(NULL, maxCapacity,
    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

if (pMemory == MAP_FAILED) {
    /* allocation failed */
}

首先,您必须告诉Linux您希望它执行提交记帐:

echo "2" > /proc/sys/vm/overcommit_memory

否则,它将保留传统的默认设置(从Linux作为玩具操作系统时开始),即允许无限的过量使用,并在物理内存用尽时使应用程序严重崩溃。

另外,正如其他人所说,您需要对照MAP_FAILED检查mmap的返回值,而无需使用mprotect 只需将正确的PROT_*值传递给mmap就可以了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM