Linux 使calloc机会主义
在linux上,malloc的行为是机会主义的,只有在第一次访问虚拟内存时才使用真实内存来支持虚拟内存。是否可以修改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
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()
如何不总是导致内存为零。谢谢你的例子。这和我在这个问题上给出的非常相似,也许你可以看看?