Cab*_*age 5 c malloc ps virtual-memory page-fault
我正在尝试了解内存和页面错误,因此我编写了下面的代码来检查我的理解。我不明白为什么调用 malloc 会导致 MINFL 增加,因为 malloc() 不应该影响物理内存(据我所知)。
这是我的代码:
#include <stdio.h>
#include <stdlib.h>
void main() {
printf("Before malloc\n");
getchar();
malloc(1 << 20);
printf("After malloc\n");
getchar();
}
Run Code Online (Sandbox Code Playgroud)
这些是 ps 命令的最终结果。
在进行 malloc 之前:

malloc 之后:

有两件事我不明白:
请帮忙并谢谢。
他们两个的答案是相同的,而且非常简单。
您可能知道,Glibcmalloc将用于mmap直接分配大于 128 KiB 的块。但是,它需要在指针下方free写入簿记信息 - 因为如果只给定一个指针,否则如何知道应该做什么。如果打印返回的指针malloc,您会发现它没有页面对齐。
这是一个演示这一切的程序:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#define ALLOCATION_SIZE (1 << 20)
int main(void) {
struct rusage usage = {0};
getrusage(RUSAGE_SELF, &usage);
printf("1st before malloc: %lu\n", usage.ru_minflt);
getrusage(RUSAGE_SELF, &usage);
printf("2nd before malloc: %lu\n", usage.ru_minflt);
char *p = malloc(ALLOCATION_SIZE);
printf("pointer returned from malloc: %p\n", p);
getrusage(RUSAGE_SELF, &usage);
printf("after malloc: %lu\n", usage.ru_minflt);
p[0] = 42;
getrusage(RUSAGE_SELF, &usage);
printf("after writing to the beginning of the allocation: %lu\n", usage.ru_minflt);
for (size_t i = 0; i < ALLOCATION_SIZE; i++) {
p[i] = 42;
}
getrusage(RUSAGE_SELF, &usage);
printf("after writing to every byte of the allocation: %lu\n", usage.ru_minflt);
}
Run Code Online (Sandbox Code Playgroud)
输出类似的东西
1st before malloc: 108
2nd before malloc: 118
pointer returned from malloc: 0x7fbcb32aa010
after malloc: 119
after writing to the beginning of the allocation: 119
after writing to every byte of the allocation: 375
Run Code Online (Sandbox Code Playgroud)
即第一次会导致页面错误,所以我们调用它两次 - 现在调用前的错误计数为 118 getrusage,调用后为 119。如果你查看指针,0x010 不是 0x000,即分配不是页面 -对齐 - 前 16 个字节包含簿记信息,以便它知道需要用来释放内存块,以及分配块的大小!printfmallocmallocfreemunmap
现在这自然解释了为什么大小增加为 1028 Ki 而不是 1024 Ki -必须保留一个额外的页面,以便有足够的空间容纳这 16 个字节!它还解释了页面错误的根源 - 因为malloc必须将簿记信息写入写时复制清零页面。这可以通过写入分配的第一个字节来证明 - 它不再导致页面错误。
最后,for 循环将修改页面并触及映射的257个页面中剩余的 256 个页面。
如果您更改ALLOCATION_SIZE为((1 << 20) - 16)ie 只少分配 16 个字节,您会发现虚拟大小和页面错误数量都将与您期望的值匹配。