根据我的理解,我必须在分配零内存的calloc
和可以根据需要分配内存的malloc
之间进行select。
是否有一个function,结合这两个属性? 也许直接调用mmap
?
如果可能的话,为什么calloc
不行呢?
有几种机制可以从操作系统中获得预清零内存:
mmap(2)
的MAP_ANONYMOUS
标志强制内容被初始化为零。
POSIX共享内存段也可以为零
shm_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
函数shmem_zero_setup()
:
/** * 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; }
如果你想用malloc来模拟calloc(即使用malloc但是接收零内存),那么你可以用memset来实现:
foo = (char*)malloc(BLOCK_SIZE); memset(foo,'\0',BLOCK_SIZE);
但是,这是一个坏主意(它比calloc慢,请参阅: 为什么malloc + memset比calloc慢? ),并不会导致您提到的“懒惰分配”,这是由于Fritschy的回答中所述的原因。
calloc
和malloc
是一样的,除了像你说的那样,它将分配的内存置零,并且它接受两个参数 – (NumberOfElements, ElementSize)
。 所以
malloc(size);
相当于
calloc(1, size);
除了后者提供归零内存。
这是什么分配你的内存“按需”,你谈论?
在Linux上(也许其他操作系统也是如此),当你做一个malloc时,你所分配的是虚拟地址空间,而不是真正的地址空间。 当你去读取或写入虚拟地址空间时,内核将找到可用的内存页面并将它们映射到该虚拟地址空间(它们可能是交换的,或者它们可能是易失性内存)。 如果你运行一个像htop这样的工具,它会显示一些内存统计信息。 这里要看的大部分是常驻内存和虚拟内存。 驻留内存是您的进程实际拥有多少内存,虚拟内存是已请求的所有内存的总和。
所以当你调用calloc时,就像malloc一样分配内存。 然后它将写入零到整个地址空间。 这些写操作将导致内核分配实际地址空间并将其映射到虚拟地址空间。
所以考虑到这一点,malloc本身并不懒惰,而内核是懒惰的,而不是实际分配内存页面的过程,直到需要。
一般来说,如果你需要内存归零,你将不得不使用类似calloc的东西来将其归零,否则你将需要跟踪哪些内存块已被归零。
calloc
在概念上与malloc
相同,然后是内存区域的零。
我不明白你为什么认为malloc在做懒惰分配。 它不是。
好的,有些Linux系统有内存过量使用 ,但是你不应该依赖它(这是一个设计错误,而不是一个功能,恕我直言)。 而且, 大内存区域的calloc
通常通过调用mmap来实现,而不需要额外清除该区域。
如果你需要一些懒惰的东西,你可以使用mmap和MAP_NORESERVE
但要小心。