|
|
1
0
内存可以通过多种方式分配……两种广泛的方式是静态和动态分配。 静态分配意味着一个程序可以使用的所有内存都是一次性分配的,并且它可以使用这个数量的内存。 动态分配是指当程序需要分配内存时,它将进入堆并在第一个可用内存块处放置一个指针(根据使用中的动态分配算法指定大小)。然后,根据需要(如在数组中),它需要更多, 将指针保持在原来的位置,这样它就知道数组的开头在哪里。 . 现代计算机通常能很好地将资源(包括内存)分配给应用程序,这就减少了 deadlock . 在更高的层次上,当对象/数组/任何可以从内存中移除的对象/数组时,垃圾收集会处理这个内存。 这里的问题是,当释放内存时,不同的程序可以随意获取不同的块,而这些块不一定是有序的。这就是我们所说的碎片化(这就是为什么您不时地对磁盘驱动器进行碎片化)。当以连续的方式分配内存时,可以更有效地读取内存。 内存中有大量的信息,所以这里有少量的数据供您在自己的内存中分配;)
Wiki Link to OSDev on Dynamic Allocation
快乐阅读! |
|
|
2
3
据我所知(至少在Unix上),有问题的程序调用系统库以获取内存(例如malloc和friends)。这些库在程序的虚拟地址空间中维护一个空闲内存块列表,并从此列表中分配内存(这过于简单化,它们维护此列表并处理单词对齐、连续块等的方法相当复杂)。至于确保程序不接触彼此的内存,操作系统有一个虚拟内存的概念,它本质上把每个程序的可寻址内存映射到物理内存的不同部分。见 http://en.wikipedia.org/wiki/Virtual_memory 更多信息。 |
|
|
3
0
最简单的解决方案是不允许释放分配的内存。假设操作系统有一个内存堆,它知道可以从中分配程序。操作系统在这个空闲区域的开头跟踪一个地址。如果有足够的内存供第一个alloc使用,那么alloc将获得空闲指针地址,并且空闲指针将按alloc的数量向前移动。这将继续向前发展,直到没有更多的内存或者没有人分配更多的内存。因此,如果起始地址是0x1000,并且有人想要0x20字节,那么作为alloc的指针返回0x1000,空闲指针移到0x1200。say 0x100的下一个alloc返回0x1200,空闲指针移动到0x1120等。 你也可以从一个高地址开始,自上而下而不是自下而上。内存顶部可能是0x1000,第一个0x20分配结果是0x1000-0x20=0xffe0,因此将0xffe0发送到应用程序,并另存为可用内存顶部。0x100 alloc得到0xfee0等。 这个简单的想法的问题是,永远不要释放内存,你很快就会耗尽内存。到那时,如果它可能已经被那些已经完成的程序孤立了,那就太多了。因此,它可能在一些嵌入式系统中工作,但一般来说,还需要做更多的工作。 因此,与文件系统不同的是,表必须由内存分配系统(操作系统)维护,该系统至少包含为发生的每个分配分配分配的起始地址和数据量。然后某种搜索算法通过这个列表,试图确定用来完成分配的开放内存块。当一个空闲发生时,它可能是一种简单的方法,查找具有匹配地址的条目并将其从表中删除。创建一个能够快速解析、排序的表结构,但是也允许小的和大的分配,而不会浪费太多的内存。 MMU可以使这变得更容易,部分原因是它们已经由表驱动,硬件导航MMU表以查找物理地址等。这里的主要特点是,您可以获取物理地址空间中彼此不相邻但可以线性放置在虚拟地址空间中的内存块。因此,您的应用程序可能需要12345字节,而您的MMU系统的最小内存分区可能是4Kbytes,因此您只需找到四个不必彼此远程相邻的空闲内存块,您必须找到彼此相邻的四个MMU表条目,并且您可以将这四个MMU条目指向四个单独的创建分配给该应用程序的16kbyte空间的物理条目。您仍然需要MMU系统之外的其他一些表,告诉您这四个MMU条目是同一分配空间的一部分。这与12345字节文件可能存储在磁盘上彼此不一定相邻的4 4096字节扇区中的文件系统不同。目录结构和文件系统表使用一个链接列表或其他方法来跟踪一个文件使用的扇区。 至于内存的管理,选择什么物理地址等等。在几十年的操作系统中,有无数的解决方案,无数小时的实验和研究。想想餐馆的主人。你和三个人一起进来,想要一张桌子。你看到选择的桌子有多少种不同的方式?有时他们有一张图表和一支蜡笔,有时他们只是在座位区闲逛,找到一张桌子。你可能意识到,也可能意识不到,但有时他们不仅仅是希望找到四个最好的,而且在绝望中找到六个最好的,他们还试图平衡每个服务员/服务员的顾客数量。他们可能还试图保留大量的桌子,以防一个8人或10人的聚会进来,他们可以把桌子推到一起。对于许多不同的餐厅和招待所,可能会有许多不同的解决方案来为您的宴会分配一张桌子。同样,从早期的分时计算机到现在,内存分配的解决方案也有很多种。 没有什么可以阻止你自己尝试这个。编写一个程序,它占用一块内存,并创建自己的malloc和free例程,尝试将内存块分割成多个部分,以服务malloc和free,也可以使用一个随机化程序来调用malloc和free例程。 |
|
|
4
0
假设您是从用户模式程序员的角度来探讨这个主题的,那么这个答案有两部分:第二部分:
malloc()或类似的代码调用将是一个用户模式库,它通常管理堆数据结构。最简单的分配器只调用通常称为brk(…)的系统/内核函数,它返回所需大小的内存块。然而,每次你的应用需要内存时进行系统调用是很昂贵的。所以您的malloc库从brk()中获取一个大的块,并将其管理在一个堆中,然后从那里返回小的块。
这是BRK实现。在较高的层次上,进程描述符有一个“内存区域”列表,组成其已使用的地址空间。brk()基本上分配一个页面帧块来增加数据段。它如何分配页面框架,以及如何在页面框架上进行讨论,可能超出了这个问题的范围,但是如果您想进一步了解,请询问。 |