首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >malloc会懒惰地为Linux (和其他平台)上的分配创建支持页吗?

malloc会懒惰地为Linux (和其他平台)上的分配创建支持页吗?
EN

Stack Overflow用户
提问于 2009-05-26 17:40:49
回答 5查看 19.1K关注 0票数 75

在Linux上,如果我使用malloc(1024 * 1024 * 1024),malloc到底能做什么?

我确信它会为分配分配一个虚拟地址(通过遍历空闲列表并在必要时创建一个新的映射),但是它真的会创建1 GiB的交换页面吗?还是像mmap那样,当你实际触摸页面时,它会mprotect地址范围并创建页面?

(我之所以指定Linux,是因为the standard对这些细节保持沉默,但我很有兴趣知道其他平台也做些什么。)

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-05-26 17:50:18

Linux确实延迟了页面分配,也就是。‘乐观内存分配’。从malloc得到的内存没有任何支持,当你接触它时,你实际上可能会得到一个OOM条件(如果你请求的页面没有交换空间),在这种情况下是a process is unceremoniously terminated

有关示例http://www.linuxdevcenter.com/pub/a/linux/2006/11/30/linux-out-of-memory.html,请参阅

票数 43
EN

Stack Overflow用户

发布于 2009-05-26 19:16:01

我在同一主题的一篇类似的帖子中给出了以下答案:

Are some allocators lazy?

这开始有点离题(然后我将把它与您的问题联系起来),但是发生的情况类似于您在Linux中派生进程时发生的情况。在forking时,有一种称为写入时复制的机制,它只在内存也被写入时为新进程复制内存空间。这样,如果派生的进程exec立即是一个新程序,那么您就节省了复制原始程序内存的开销。

回到你的问题上,想法是相似的。正如其他人指出的那样,请求内存会立即获得虚拟内存空间,但实际的页面只有在写入时才会被分配。

这是什么目的?它基本上将内存错位变成了一个或多或少的恒定时间操作Big O(1),而不是一个Big O(n)操作(类似于Linux调度器分散它的工作而不是在一个大块中完成的方式)。

为了演示我的意思,我做了以下实验:

rbarnes@rbarnes-desktop:~/test_code$ time ./bigmalloc

real    0m0.005s
user    0m0.000s
sys 0m0.004s
rbarnes@rbarnes-desktop:~/test_code$ time ./deadbeef

real    0m0.558s
user    0m0.000s
sys 0m0.492s
rbarnes@rbarnes-desktop:~/test_code$ time ./justwrites

real    0m0.006s
user    0m0.000s
sys 0m0.008s

bigmalloc程序分配了2000万个整型数,但没有对它们做任何事情。deadbeef向每页写入一个整数,导致19531次写入,而justwrites分配19531个整数并将它们置零。正如你所看到的,死牛的执行时间大约是bigmalloc的100倍,而仅仅是times的50倍。

#include <stdlib.h>

int main(int argc, char **argv) {

    int *big = malloc(sizeof(int)*20000000); // Allocate 80 million bytes

    return 0;
}

#include <stdlib.h>

int main(int argc, char **argv) {

    int *big = malloc(sizeof(int)*20000000); // Allocate 80 million bytes

    // Immediately write to each page to simulate an all-at-once allocation
    // assuming 4k page size on a 32-bit machine.

    for (int* end = big + 20000000; big < end; big += 1024)
        *big = 0xDEADBEEF;

    return 0;
}

#include <stdlib.h>

int main(int argc, char **argv) {

    int *big = calloc(sizeof(int), 19531); // Number of writes

    return 0;
}
票数 11
EN

Stack Overflow用户

发布于 2009-05-27 01:20:26

Malloc从libc管理的块中分配内存。当需要额外的内存时,库使用brk系统调用进入内核。

内核将虚拟内存页分配给调用进程。页面作为进程拥有的资源的一部分进行管理。当内存为brk时,不分配物理页面。当进程访问brk页面之一中的任何内存位置时,就会发生页面错误。内核验证虚拟内存是否已被分配,并继续将物理页面映射到虚拟页面。

页面分配不限于写入,与写入时复制截然不同。任何访问,读或写,都会导致页错误和物理页的映射。

请注意,堆栈内存是自动映射的。也就是说,将页面映射到堆栈使用的虚拟内存时不需要显式brk。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/911860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档