在Linux上,如果我使用malloc(1024 * 1024 * 1024),malloc到底能做什么?
我确信它会为分配分配一个虚拟地址(通过遍历空闲列表并在必要时创建一个新的映射),但是它真的会创建1 GiB的交换页面吗?还是像mmap那样,当你实际触摸页面时,它会mprotect地址范围并创建页面?
(我之所以指定Linux,是因为the standard对这些细节保持沉默,但我很有兴趣知道其他平台也做些什么。)
发布于 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,请参阅
发布于 2009-05-26 17:49:07
( Andries Brouwer的, 的一部分)是一个很好的文档。
它包含以下程序,演示Linux对物理内存和实际内存的处理,并解释内核的内部结构。
通常,在malloc()返回NULL之前,第一个演示程序将获得大量内存。第二个演示程序将获得更少的内存量,因为之前获得的内存实际上已被使用。第三个程序将获得与第一个程序相同的大量内存,然后当它想要使用其内存时,它将被终止。
演示程序1:分配内存而不使用它。
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int n = 0;
while (1) {
if (malloc(1<<20) == NULL) {
printf("malloc failure after %d MiB\n", n);
return 0;
}
printf ("got %d MiB\n", ++n);
}
}演示程序2:分配内存并实际触摸所有内存。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void) {
int n = 0;
char *p;
while (1) {
if ((p = malloc(1<<20)) == NULL) {
printf("malloc failure after %d MiB\n", n);
return 0;
}
memset (p, 0, (1<<20));
printf ("got %d MiB\n", ++n);
}
}演示程序3:先分配,后使用。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define N 10000
int main (void) {
int i, n = 0;
char *pp[N];
for (n = 0; n < N; n++) {
pp[n] = malloc(1<<20);
if (pp[n] == NULL)
break;
}
printf("malloc failure after %d MiB\n", n);
for (i = 0; i < n; i++) {
memset (pp[i], 0, (1<<20));
printf("%d\n", i+1);
}
return 0;
}(在功能良好的系统上,如Solaris,这三个演示程序获得相同的内存量并且不会崩溃,但请参阅malloc() return NULL。)
发布于 2009-05-26 19:16:01
我在同一主题的一篇类似的帖子中给出了以下答案:
这开始有点离题(然后我将把它与您的问题联系起来),但是发生的情况类似于您在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.008sbigmalloc程序分配了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;
}https://stackoverflow.com/questions/911860
复制相似问题