2012-02-03 19 views
6

我尝试使用mmap()来操纵虚拟内存。我想保留并提交一段内存。我测试了这个代码:为什么调用大尺寸的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上运行。任何人都可以告诉我这件事吗

+1

阅读关于内存过量使用 – PlasmaHH 2012-02-03 12:58:42

+0

您发布的代码没有提交任何内容。尝试通过这些内存区域。 – Mat 2012-02-03 13:04:00

回答

11

mmap保留的区域进程的虚拟地址空间,但不会立即为其分配物理RAM。因此,在64位平台上,您可以保留大量数据而不会失败(尽管您仍然需要检查失败;您的示例代码不会)。内存访问时,稍后分配RAM的物理页面。

mprotect只是改变保留存储器的读/写访问权限;它也不会让它驻留在RAM中。您将通过传递PROT_READ | PROT_WRITE而不是PROT_NONEmmap并取消呼叫mprotect来获得相同的效果。

如果您需要将内存直接驻留在RAM中,那么请使用mlock。如果没有足够的RAM,它将会失败。在许多Linux平台(包括Ubuntu)上,有一个资源限制(RLIMIT_MEMLOCK),它限制了任何进程可以锁定的内存量;你可以用ulimit -l来调整。

+0

它看起来像这样吗? 'pMemory =(char *)mmap(NULL,maxCapacity,PROT_READ | PROT_WRITE,MAP_SHARED | MAP_ANONYMOUS,-1,0); mlock(pMemory,maxCapacity)'我认为mlock()中使用的内存不是mmap()保留的内存。 – antpetr89 2012-02-03 14:56:53

+0

我试图保留1GB并通过这种方式提交它们。但是mlock()返回-1。 – antpetr89 2012-02-03 15:02:36

+1

@ user1173593:之后检查“errno”的值。它可能是'EPERM',表示你的资源限制太低(你可以用'ulimit -l'设置它,但也可能有硬限制),或者可能是'ENOMEM',表示没有足够的内存或者联机帮助页中记录的其他错误。 – 2012-02-03 17:44:21

0

您应该首先检查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 */ 
} 
1

mmap对于准备要求的内存映射很有用,但它不会将它分配给您的程序。当你访问内核时,内核负责分配内存,因此如果你不能同时访问这8GB内存,则可以在4GB的内存上使用8GB的内存。

0

首先,你必须告诉Linux,您希望它做的承诺会计:

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

否则,它保持了原有默认(从当Linux是一个玩具OS),允许无限制的过量使用和可怕的使您的应用程序当物理内存不足时发生崩溃。

另外,正如其他人所说,您需要检查返回值mmapMAP_FAILED,并且不需要使用mprotect。只需将PROT_*的正确值传递给mmap即可。

相关问题