gpt4 book ai didi

c - 如何实现calloc

转载 作者:行者123 更新时间:2023-12-04 14:25:16 29 4
gpt4 key购买 nike

我正在尝试重写 malloc 和 calloc,我的问题是关于 calloc 的实现,而不是如何使用它。

应该始终使用 calloc() 而不是 malloc()+memset(),因为它可以利用 copy-on-write (牛)。

有些 calloc 是这样实现的:

void * calloc(size_t nelem, size_t elsize)
{
void *p;

p = malloc (nelem * elsize);
if (p == 0)
return (p);

bzero (p, nelem * elsize);
return (p);
}

但他们根本不使用 COW(并且他们不检查溢出)。

如果这些实现不调用 bzero(),它们必须假设它们接收到的 mmap 页面是零填充的。它们可能是出于安全原因,我们不希望其他进程的数据泄漏,但我找不到任何关于此的标准引用。

我们可以从 /dev/zerommap 而不是使用 MAP_ANON:

fd = open("/dev/zero", O_RDWR); 
a = mmap (0, 4096e4, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);

但是 /dev/zero 不是 POSIX 强制要求的,可以很容易地执行 sudo mv/dev/zero/dev/foo,破坏我的实现。

什么是有效重写 calloc() 的正确方法,尊重写时复制?

最佳答案

纯 POSIX 不支持匿名内存映射,并且没有比 calloc 更低级别的接口(interface)来分配零内存。

现有的 POSIX 实现支持匿名私有(private)内存映射作为扩展,通过 MAP_ANONMAP_ANONYMOUS 标志(或者从历史上看,通过从 /dev/zero)。内核确保应用程序只看到归零的内存。 (也有较旧的接口(interface),例如 brksbrk,但它们很难使用并且不是线程安全的。)

malloc 函数族的实现通常使用 mmap 分配更大的 block ,并为每个 block 保留一个水印指针,指示哪个部分已分配给应用程序至少一次(通过 malloc/realloc/calloc,无所谓)。 calloc 在返回分配之前检查水印指针,如果应用程序之前使用过内存,则将其清除。否则,直接返回,因为它知道它是新鲜的,因此已被内核清除。

也可以使用 mmap 直接分配大块。但是内核最终也必须清除内存(在将其用于触发写时复制错误的反向映射之前),所以如果分配比实际需要的大得多,那么这只是一个明显的胜利,而且大部分都是从未写过。

关于c - 如何实现calloc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46853908/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com