我正在设计内核(我将实际上称之为<!> quot; core <!>;对于我正在工作的操作系统,它只是为了与众不同,但它基本相同)上。如果我无法完成多任务,内存管理和其他基本操作,那么操作系统本身的细节就无关紧要了,所以我需要先解决这个问题。我有一些关于设计malloc例程的任务。

我认为malloc()要么是内核本身的一部分(我倾向于这个),要么是程序的一部分,但是我将不得不编写自己的C实现标准库的方式,所以我得写一个malloc。在这方面,我的问题实际上相当简单,C(或C ++)如何管理它的堆?

我在理论类中一直被教导的是,堆是一个不断扩展的内存块,从指定的地址开始,并且在很多方面表现得像堆栈。通过这种方式,我知道在全局范围内声明的变量在开头,更多的变量是<!> quot; push <!> quot;在它们各自的作用域中声明它们到堆上时,超出作用域的变量只留在内存空间中,但是该空间被标记为空闲,因此如果需要,堆可以扩展更多。

我需要知道的是,C实际上如何以这种方式处理动态扩展堆?编译的C程序是否自己调用malloc例程并处理自己的堆,还是需要为它提供自动扩展的空间?另外,C程序如何知道堆的开始位置?

哦,我知道相同的概念适用于其他语言,但我希望任何示例都在C / C ++中,因为我对这种语言最为满意。我也不想担心其他事情,比如堆栈,因为我认为我可以自己处理这样的事情。

所以我想我的真正问题是,除了malloc / free(处理获取和释放页面本身等)之外,程序是否需要操作系统提供其他任何内容?

谢谢!

编辑我更感兴趣的是C如何使用malloc与堆相关而不是在malloc例程本身的实际工作中。如果它有帮助,我在x86上这样做,但C是交叉编译器所以它应该没关系。 ^ _ ^

进一步编辑:我知道我可能会让术语混乱。我被教导<!>“堆<!>”;是程序存储诸如全局/局部变量之类的东西。我习惯于处理<!> quot; stack <!> quot;在汇编编程中,我只是意识到我可能意味着相反。我的一点研究表明<!>“堆<!>”;更常用于指代程序为自己分配的总内存,或者操作系统提供的内存页面的总数(和顺序)。

因此,考虑到这一点,我如何处理不断扩展的堆栈? (看来我的C理论课有点......有缺陷。)

有帮助吗?

解决方案

malloc通常在用户空间的C运行时中实现,依赖于特定的OS系统调用来映射虚拟内存的页面。 freelib/malloc.c的工作是管理那些大小固定的内存页面(通常为4 KB,但有时更大),并将它们切片并分成应用程序可以使用的部分。

例如,请参阅 GNU libc 实施。

要实现更简单的实施,请查看上一页的 MIT操作系统课程年。具体来说,请参阅最终实验室讲义 ,并看看sys_page_alloc。此代码使用类中开发的操作系统JOS。它的工作方式是读取页面表(由OS提供只读),查找未映射的虚拟地址范围。然后,它使用sys_page_unmap和<=>系统调用将页面映射和取消映射到当前进程。

其他提示

有多种方法可以解决这个问题。

大多数情况下,C程序都有自己的malloc / free功能。那个适用于小物件。最初(并且一旦内存耗尽),内存管理器将要求操作系统获得更多内存。执行此操作的传统方法是unix变体上的mmap和sbrk(Win32上的GlobalAlloc / LocalAlloc)。

我建议您查看 Doug Lea内存分配器(谷歌:dlmalloc)从内存提供商(例如OS)的角度来看。该分配器在一个非常好的分配器中是顶级的,并且具有所有主要操作系统的钩子。如果您想知道高性能分配器对操作系统的期望,那么代码就是您的首选。

您是否混淆了堆和堆栈?

我问,因为你提到了<!>“一段不断扩展的内存<!>”,范围并在声明它们时在堆上推送变量。这听起来好像你在谈论堆栈。

在最常见的C实现中声明自动变量,如

int i;

通常会导致我被分配到堆栈中。通常,malloc不会涉及,除非您显式调用它,或者您调用它的某些库调用。

我建议查看<!>“专家C编程<!>”;作者:Peter Van Der Linden,了解C程序通常如何处理堆栈和堆栈。

必读:Knuth - 计算机程序设计,第1卷,第2章,第2.5节。否则,你可以阅读Kernighan <!> amp; Ritchie <!> C语言编程语言<!>看一个实现;或者,您可以阅读Plauger <!>“标准C库<!>”;看另一个实现。

我相信你在核心内部需要做的事情会与核心以外的程序有所不同。特别是,程序的内核内存分配将处理虚拟内存等,而代码外的程序只能看到内核提供的结果。

了解虚拟内存管理(分页)。它具有高度CPU特性,每个操作系统都专门为每个支持的CPU实施VM管理。如果您正在为x86 / amd64编写操作系统,请阅读各自的手册。

通常,C库处理malloc的实现,根据需要从OS请求内存(通过匿名mmap或在旧系统中,sbrk)。所以你的内核方面应该处理通过类似其中一种方式分配整个页面。

然后由<=>以一种不会过多地分割空闲内存的方式发布内存。尽管如此,我并不是很喜欢 au fait 。然而,脑海中会出现 arena 这个词。如果我可以搜索引用,我会更新这篇文章。

危险危险!!如果你甚至考虑尝试内核开发,你应该非常了解资源的成本以及相对有限的可用性......

关于递归的一件事是,它非常昂贵(至少在内核中),你不会看到许多函数被编写为简单地继续无关,否则你的内核会感到恐慌。

在此强调我的观点,(在stackoverflow.com嘿),请查看 NT调试博客关于内核堆栈溢出,特别是

  <!>

#183;在基于x86的平台上,   内核模式堆栈 12K

     <!>

#183;在基于x64的平台上,   内核模式堆栈 24K 。 (基于x64   平台包括系统   处理器使用AMD64   使用的架构和处理器   英特尔EM64T架构)。

     <!>

#183;在基于Itanium的平台上,   内核模式堆栈 32K 32K   支持商店。

这真的,不是很多;

  

常见嫌疑人

     
     

1。大量使用堆栈。

     

2。递归调用函数。

如果您稍微阅读一下博客,您会看到一系列相当独特的问题,内核开发有多么艰难。你的理论课没错,简单,简单。 ;)

从理论出发 - <!> gt;内核开发与上下文交换机一样重要(可能会在混合中保存一些虚拟机管理程序交互!!)。

无论如何,永远不要假设,验证和测试你的期望。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top