为什么malloc()会导致较小的页面错误?

为什么malloc()会导致较小的页面错误?,c,malloc,virtual-memory,ps,page-fault,C,Malloc,Virtual Memory,Ps,Page Fault,我试图了解内存和页面错误,所以我写了下面的代码来检查我的理解。我不明白为什么调用malloc会导致MINFL增加,因为malloc()不应该影响物理内存(据我所知) 这是我的代码: #include <stdio.h> #include <stdlib.h> void main() { printf("Before malloc\n"); getchar(); malloc(1 << 20); printf(&quo

我试图了解内存和页面错误,所以我写了下面的代码来检查我的理解。我不明白为什么调用malloc会导致MINFL增加,因为malloc()不应该影响物理内存(据我所知)

这是我的代码:

#include <stdio.h>
#include <stdlib.h>

void main() {
  printf("Before malloc\n");
  getchar();
  
  malloc(1 << 20);
  printf("After malloc\n");
  getchar();
}
#包括
#包括
void main(){
printf(“在malloc之前”);
getchar();

马洛克(1答案非常简单。Glibc
malloc
将使用
mmap
直接分配大于128 KiB的块。但是,它需要在指针下方写入簿记信息,因为在刚刚给定指针时,
free
如何知道应该做什么。如果打印指针,您会发现它不与页面对齐:

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>

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(1 << 20);
    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 < (1 << 20); i++) {
        p[i] = 42;
    }
    getrusage(RUSAGE_SELF, &usage);
    printf("after writing to every byte of the allocation: %lu\n", usage.ru_minflt);
}
i、 e.
getrusage
printf
第一次导致页面错误,所以我们称之为两次-现在计数是118;在
malloc
之后计数是119。如果你看指针,0x010不是0x000,即分配不是页面对齐的-前16个字节包含
free的簿记信息e> 这样它就知道需要使用
munmap
来释放内存块及其大小

现在,这很自然地解释了为什么大小增加了1028 Ki而不是1024 Ki-必须保留一个额外的页面,以便有足够的空间容纳这16个字节!这也解释了页面错误的来源-因为
malloc
必须在写零页面上将簿记信息写入副本。这可以通过写入分配的第一个字节来证明这一点——它不再导致页面错误


最后,for循环将修改页面,并在映射到的257页面中触摸剩余的256页。

为什么MINFL会增加。如果不查看实现细节,很难确定。但通常
malloc
将读/写内存以维护其数据结构(例如,已用和空闲列表).So
malloc
实际上是写入内存。这对我来说是新的。谢谢。谢谢你详细解释了页面错误的原因,我一开始不理解它。@Orielno我进一步改进了它。这很清楚。谢谢
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