当您的
malloc()实现从系统内核中请求内存(通过
sbrk()或
mmap()系统调用)时,内核仅记录您已请求内存以及将其放置在地址空间中的位置。
它实际上还没有映射那些页面 。
当该过程随后访问新区域中的内存时,硬件将识别分段错误并向内核发出警报。然后内核在其自己的数据结构中查找该页面,并发现那里应该有一个零页面,因此它映射到一个零页面(可能首先从页面高速缓存中逐出了一个页面)并从中断中返回。您的进程没有意识到这一切都发生了,内核操作是完全透明的(除了内核工作时的短暂延迟)。
这种优化使系统调用可以非常快速地返回,并且最重要的是,它避免了在进行映射时将任何资源提交给您的进程。这样,进程就可以保留正常情况下不需要的相当大的缓冲区,而不必担心会占用过多的内存。
因此,如果要对内存消耗程序进行编程,则绝对必须对分配的内存进行实际操作。为此,您只需要在代码中添加一行:
int eat_kilobyte(){ if (memory == NULL) memory = malloc(1024); else memory = realloc(memory, (eaten_memory * 1024) + 1024); if (memory == NULL) { return 1; } else { //Force the kernel to map the containing memory page. ((char*)memory)[1024*eaten_memory] = 42; eaten_memory++; return 0; }}请注意,在每个页面中写入单个字节(在X86上包含4096个字节)就足够了。那是因为从内核到进程的所有内存分配都是以内存页面粒度完成的,这又是因为硬件不允许以较小粒度进行分页。



