C 如何分配零内存?
据我所知,我必须在C 如何分配零内存?,c,linux,memory-management,C,Linux,Memory Management,据我所知,我必须在calloc和malloc之间做出选择,前者将分配零内存,后者可按需分配内存 是否有一个函数结合了这两个属性?可以直接调用mmap 如果可能的话,为什么calloc不这样做?如果您试图用malloc模拟calloc(即使用malloc但接收零内存),那么您可以使用memset: foo = (char*)malloc(BLOCK_SIZE); memset(foo,'\0',BLOCK_SIZE); 但是,这是一个坏主意(它比calloc慢,请参阅:),并且不会由于中所述的原
calloc
和malloc
之间做出选择,前者将分配零内存,后者可按需分配内存
是否有一个函数结合了这两个属性?可以直接调用mmap
如果可能的话,为什么
calloc
不这样做?如果您试图用malloc模拟calloc(即使用malloc但接收零内存),那么您可以使用memset:
foo = (char*)malloc(BLOCK_SIZE);
memset(foo,'\0',BLOCK_SIZE);
但是,这是一个坏主意(它比calloc慢,请参阅:),并且不会由于中所述的原因导致您所指的“延迟分配”。
calloc
与malloc
相同,只是,正如您所说,它将分配的内存归零,并且它接受两个参数-(NumberOfElements,ElementSize)
。所以
malloc(size);
相当于
calloc(1, size);
除了后者提供零内存
您所说的“按需”分配内存是什么?有几种机制可以从操作系统获取预调零内存:
mmap(2)
的MAP\u匿名
标志强制将内容初始化为零
POSIX共享内存段也可以归零
为您提供文件描述符shm\u open(3)
将“文件”设置为所需的大小ftruncate(2)
将“文件”插入您的地址空间mmap(2)
This volume of IEEE Std 1003.1-2001 specifies that memory
objects have initial contents of zero when created. This is
consistent with current behavior for both files and newly
allocated memory. For those implementations that use physical
memory, it would be possible that such implementations could
simply use available memory and give it to the process
uninitialized. This, however, is not consistent with standard
behavior for the uninitialized data area, the stack, and of
course, files. Finally, it is highly desirable to set the
allocated memory to zero for security reasons. Thus,
initializing memory objects to zero is required.
此内存似乎在使用时已归零:mm/shmem.c
functionshmem\u zero\u setup()
:
calloc
在概念上与malloc
相同,后面是内存区域的归零
我不明白你为什么认为malloc在做懒惰的分配。事实并非如此
好的,有些Linux系统有,但你不应该依赖它(它更像是一个设计缺陷,而不是一个特性,IMHO)。此外,大型内存区域的calloc
通常由一些不需要额外清除该区域的调用来实现
如果您需要一些惰性的东西,您可以使用MAP\u NORESERVE
,但要小心。在Linux上(可能也有其他操作系统,但不确定),当您执行malloc时,您分配的是虚拟地址空间,而不是真实地址空间。当您读取或写入该虚拟地址空间时,内核将找到可用的内存页,并将它们映射到该虚拟地址空间(它们可能是交换的,也可能是易失性内存)。如果运行htop之类的工具,它将显示一些内存统计信息。这里要看的大内存是驻留内存和虚拟内存。常驻内存是进程实际拥有的内存量,虚拟内存是所有已请求内存的总和
因此,当您调用calloc时,它将像malloc一样分配内存。然后它将向整个地址空间写入零。这些写操作将导致内核分配真实地址空间并将其映射到虚拟地址空间
因此,记住这一点,malloc本身并不是懒惰的,而是内核是懒惰的,并且在需要之前不会为进程分配内存页
一般来说,如果您需要将内存归零,您必须先使用calloc之类的工具将其归零,或者您需要自己跟踪哪些内存块已归零。感谢指向malloc+memset与calloc performanceGlibc的链接。
calloc
知道mmap
已将其归零内存,所以其他声称calloc
总是自己写零(弄脏页面)的答案是错误的。但幸运的是,gcc甚至尽可能将malloc+memset优化为calloc
。glibc的calloc
知道mmap
中的内存已经归零。使用calloc
的大型分配不会使系统开始交换,因为它不会弄脏页面。gcc甚至将mmap
+memset
优化为calloc
。(相关:除了原始mmap之外,为什么没有对齐的calloc
,它生成的指针不能传递到free
)良好的calloc
实现已经避免了弄脏从操作系统获得的已知为零的页面。看见如果您希望这种行为具有额外的对齐方式,您只需要自己执行,因为似乎没有类似于calloc
的函数接受对齐参数。
/**
* shmem_zero_setup - setup a shared anonymous mapping
* @vma: the vma to be mmapped is prepared by do_mmap_pgoff
*/
int shmem_zero_setup(struct vm_area_struct *vma)
{
struct file *file;
loff_t size = vma->vm_end - vma->vm_start;
file = shmem_file_setup("dev/zero", size, vma->vm_flags);
if (IS_ERR(file))
return PTR_ERR(file);
if (vma->vm_file)
fput(vma->vm_file);
vma->vm_file = file;
vma->vm_ops = &shmem_vm_ops;
return 0;
}