Linux 使calloc机会主义

Linux 使calloc机会主义,linux,malloc,glibc,calloc,Linux,Malloc,Glibc,Calloc,在linux上,malloc的行为是机会主义的,只有在第一次访问虚拟内存时才使用真实内存来支持虚拟内存。是否可以修改calloc,使其也以这种方式运行(首次访问页面时分配页面并将其归零)?来自以下内容中的相关/proc/sys/vm/overmit\u memory部分: 系统上当前分配的内存量。提交的内存是进程分配的所有内存的总和,即使到目前为止还没有被进程“使用”。分配1GB内存的进程(使用malloc(3)或类似的),但仅涉及300MB内存的进程将仅显示为使用300MB内存,即使它为整个1

在linux上,malloc的行为是机会主义的,只有在第一次访问虚拟内存时才使用真实内存来支持虚拟内存。是否可以修改
calloc
,使其也以这种方式运行(首次访问页面时分配页面并将其归零)?

来自以下内容中的相关
/proc/sys/vm/overmit\u memory
部分:

系统上当前分配的内存量。提交的内存是进程分配的所有内存的总和,即使到目前为止还没有被进程“使用”。分配1GB内存的进程(使用malloc(3)或类似的),但仅涉及300MB内存的进程将仅显示为使用300MB内存,即使它为整个1GB分配了地址空间。这个1GB内存已经被VM“提交”到,并且可以在任何时候被分配的应用程序使用。如果在系统上启用了严格的过度分配(模式2/proc/sys/vm/overmit_memory),则不允许分配超过提交限制(如上所述)。如果需要保证在成功分配内存后,进程不会因内存不足而失败,则这一点非常有用


虽然没有明确说明,但我认为这里的“相似”是指
calloc
realloc
。因此,
calloc
已经表现得像
malloc

一样机会主义,这并不是
malloc()
的一个特性让它变得“机会主义”。这是内核的一个特性,
malloc()
与此无关


malloc()
每当内核需要更多内存来满足请求时,它都会要求内核提供少量内存,而内核每次都会在不提供内存的情况下说“是的,当然,你拥有它”。它也是通过提供零内存页来处理后续页面错误的内核。请注意,出于安全考虑,内核提供的任何内存都将被归零,因此它同样适用于
malloc()
calloc()

也就是说,除非
calloc()
实现通过无条件地将页面本身归零(生成提示内核实际提供内存的页面错误)破坏了这一点,否则它将具有与
malloc()
相同的“机会主义”行为


更新: 在我的系统上,以下程序在只有2 GiB内存的系统上成功分配1 TiB(!):

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

int main() {
    size_t allocationCount = 1024, successfullAllocations = 0;
    char* allocations[allocationCount];
    for(int i = allocationCount; i--; ) {
        if((allocations[i] = calloc(1, 1024*1024*1024))) successfullAllocations++;
    }
    if(successfullAllocations == allocationCount) {
        printf("all %zd allocations were successfull\n", successfullAllocations);
    } else {
        printf("there were %zd failed allocations\n", allocationCount - successfullAllocations);
    }
}
#包括
#包括
int main(){
size\u t allocationCount=1024,successfullAllocations=0;
char*分配[allocationCount];
for(int i=分配计数;i--;){
如果((分配[i]=calloc(1,1024*1024*1024)))成功分配++;
}
if(successfullAllocations==allocationCount){
printf(“所有%zd分配均已成功\n”,successfullAllocations);
}否则{
printf(“有%zd个分配失败\n”,allocationCount-successfullAllocations);
}
}

我认为,可以肯定地说,至少我的机器上的
calloc()
实现表现出“机会主义”的行为。请注意,对于大块,Linux/glibc上的
calloc
已经是机会主义的(使用相同的
MAP|u PRIVATE | MAP|u anonyman
mmap调用,因为新映射的页面承诺读取为零).
calloc
malloc
非常不同
calloc
保证它返回的内存被初始化为零<代码>malloc没有。除非您知道
calloc
能够在不接触页面的情况下将页面归零,或者以某种方式将归零推迟到首次访问,否则在进行此类概括之前,您应该三思而后行。“内核提供的任何内存都将已经归零”。这很好,但是通过
free
返回到堆中,然后
calloc
ed再次执行的内存呢?谢谢,我不知道内核通常会将所有内存归零。但这并不能解释我接受了一个应用程序(我没有编写)并将调用更改为
calloc
malloc
,然后它崩溃了。我假设这是因为分配的内存没有归零,而应用程序假设它会归零。@n.m.如果要用于新的分配,任何尚未返回内核的内存都必须由
calloc()
归零。但是,如果
free()
实现将内存返回内核(通过
munmap()
sbrk()
),那么通过
mmap()
sbrk()
创建的新映射将再次被内核归零。@socks从内核请求内存和分配内存不是一回事。从内核请求的内存用于通过
malloc()
支持分配,但不是每个
malloc()
调用都从内核请求内存。由于
malloc()
允许重用以前释放的分配中的内存,
malloc()
可以返回未直接从内核请求的内存区域,因此这些内存区域不会归零。
malloc()
实现通常避免将内存返回内核,以避免系统调用的开销。@cmaster谢谢!我现在明白了
free()
如何不总是导致内存为零。谢谢你的例子。这和我在这个问题上给出的非常相似,也许你可以看看?