对于我正在研究的操作系统,我正在设计内核(我将实际上称之为"核心"只是为了与众不同,但它基本相同).如果我无法完成多任务,内存管理和其他基本操作,那么操作系统本身的细节就无关紧要了,所以我需要先解决这个问题.我有一些关于设计malloc例程的任务.
我认为malloc()要么是内核本身的一部分(我倾向于这个),要么是程序的一部分,但是我将不得不编写自己的C标准库实现方式,所以我写了一个malloc.在这方面我的问题实际上相当简单,C(或C++)如何管理它的堆?
我在理论类中一直被教导的是,堆是一个不断扩展的内存块,从指定的地址开始,并且在很多方面表现得像堆栈一样.通过这种方式,我知道在全局范围内声明的变量在开头,并且更多的变量被"推"到堆上,因为它们在各自的作用域中声明,超出作用域的变量只留在内存空间中,但是该空间被标记为空闲,因此如果需要,堆可以扩展更多.
我需要知道的是,C实际上如何以这种方式处理动态扩展堆?编译的C程序是否自己调用malloc例程并处理自己的堆,还是需要为它提供自动扩展的空间?另外,C程序如何知道堆的开始位置?
哦,我知道相同的概念适用于其他语言,但我希望任何示例都在C/C++中,因为我对这种语言最为满意.我也不想担心其他事情,比如堆栈,因为我认为我能够自己处理这样的事情.
所以我想我真正的问题是,除了malloc/free(处理获取和释放页面本身等)之外,程序是否需要操作系统提供其他任何东西?
谢谢!
编辑我更感兴趣的是C如何使用malloc与堆相关而不是在malloc例程本身的实际工作中.如果它有帮助,我在x86上这样做,但C是交叉编译器所以它应该没关系.^ _ ^
进一步编辑:我理解我可能会对术语感到困惑.我被教导说"堆"是程序存储诸如全局/局部变量之类的东西.我习惯于在汇编编程中处理"堆栈",我只是意识到我可能意味着相反.对我的一点研究表明,"堆"更常用于指代程序为自己分配的总内存,或者操作系统提供的内存页面的总数(和顺序).
那么,考虑到这一点,我如何处理不断扩大的堆栈?(看来我的C理论课有点......有缺陷.)
malloc
通常在用户空间的C运行时中实现,依赖于特定的OS系统调用来映射虚拟内存的页面.的工作malloc
,并free
为管理这些内存页,大小是固定的(通常为4 KB,但有时更大),以及切片和切块他们到该应用程序可以使用块.
例如,参见GNU libc实现.
有关更简单的实现,请查看去年的MIT操作系统类.具体来说,请参阅最后的实验讲义,并查看lib/malloc.c
.此代码使用类中开发的操作系统JOS.它的工作方式是读取页面表(由OS提供只读),查找未映射的虚拟地址范围.然后,它使用sys_page_alloc
和sys_page_unmap
系统调用将页面映射和取消映射到当前进程.
有多种方法可以解决这个问题.
大多数情况下,C程序都有自己的malloc/free功能.那个适用于小物件.最初(并且一旦内存耗尽),内存管理器将要求操作系统获得更多内存.执行此操作的传统方法是unix变体上的mmap和sbrk(Win32上的GlobalAlloc/LocalAlloc).
我建议您从内存提供程序(例如OS)的角度来看看Doug Lea内存分配器(google:dlmalloc).该分配器在一个非常好的分配器中是顶级的,并且具有所有主要操作系统的钩子.如果您想知道高性能分配器对操作系统的期望,那么代码就是您的首选.