Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何将位图中的位映射到伙伴分配器中的物理页?_C_Memory_Memory Management_Kernel_Allocation - Fatal编程技术网

C 如何将位图中的位映射到伙伴分配器中的物理页?

C 如何将位图中的位映射到伙伴分配器中的物理页?,c,memory,memory-management,kernel,allocation,C,Memory,Memory Management,Kernel,Allocation,我用位图创建了我自己的buddy分配器(用于管理内核的物理内存),每个位对应一个特定大小的页面块。 因为我映射了整个4GiB地址空间,所以从逻辑上讲,第一位代表4GiB块,接下来的两位代表2GiB块,接下来的四位代表1GiB块,依此类推,直到我们只达到单个4KB块(页面大小)。 获取位的子元素非常简单,只需记录位位置、位n和: leftNode=bitN*2 rightNode=bitN*2+1 获取任何位的父级将被计算为bitN/2。 从某种意义上说,整个位图看起来像: bit number:

我用位图创建了我自己的buddy分配器(用于管理内核的物理内存),每个位对应一个特定大小的页面块。 因为我映射了整个4GiB地址空间,所以从逻辑上讲,第一位代表4GiB块,接下来的两位代表2GiB块,接下来的四位代表1GiB块,依此类推,直到我们只达到单个4KB块(页面大小)。 获取位的子元素非常简单,只需记录位位置、位n和:
leftNode=bitN*2
rightNode=bitN*2+1
获取任何位的父级将被计算为bitN/2。

从某种意义上说,整个位图看起来像:

bit number: [1] [2 3] [4 5 6 7] [8 9 10 11 12 13 14 15] [16 ... etc.]
holds block: 4G  2G    1G        512M                    256M  - 4KiB

我可以为每个大小相同的块映射唯一的物理地址,但由于使用此方案的方式,地址将重叠,这意味着可以返回相同的物理地址,例如,对于4KB块或16KiB块。尤其是对于2次方的位数字,这是正确的——位1、2、4、8等总是指向最左边的物理块,即地址0。位3、6、12、24等也将始终指向从地址2GiB开始的同一块,但该块可以是任何(有效)大小! 一个很好的输出示例是:

(assume address 0 is valid and isn't considered NULL for the sake of the example)
allocate(1) -- allocate 1 page, returns address 0x00000000. Valid usable range is 0-4095 (0x00000000 - 0x00001000).
allocate(524288) -- allocate 512k pages (2GiB), returns address 0x80000000. Valid usable range is 0x80000000-0xFFFFFFFF.
free((uint32_t *)0) -- free address 0. Page is reclaimed and merged with its free buddies.
allocate(16) -- allocate 16 pages, returns address 0x00000000! Same address but now with a bigger usable range of 0-65535!

正如您所看到的,在这个实现中,相同的地址可以指向任何大小的块,我想知道如何获得这个块的大小,以便我可以索引到位图中并开始合并伙伴。但我花了几个小时试图找出如何从对应于地址的位图中查找位的反向映射! 我没有问题分配任何数量的页面,我得到唯一的地址回来,但我不知道如何索引回到位图一旦我必须释放他们!
有什么办法吗?

在我看来,每个块至少需要两位信息。一位用于跟踪块是否已拆分,另一位用于跟踪块是否已分配或空闲。一种可能的编码:

00 - page is part of a larger block
01 - block has been split
10 - free block
11 - allocated block

我已经设法分配了每个条目只有1位的内存,0表示节点空闲,1表示节点被占用。如果节点及其伙伴被占用,则父节点也必须标记为已占用。在树中搜索(假设为每个节点)会在遇到的第一个被占用节点处停止。做得好,但是。。。假设系统已经运行了一段时间,发生了许多分配和释放,并且单个4KB块是当前唯一占用的块。因此,在位图中的2097151位中,正好设置了1位。位图中的第一位是0,这意味着它要么是免费的,要么是被拆分的,但除非搜索整个表以找到已设置的一位,否则您无法知道是哪一位。@IvanStanev底线,这是空间和时间之间的经典折衷。如果最小化用于跟踪分配的空间,则可以最大化执行分配和释放操作所需的时间。明智地使用更多空间将减少分配/释放所需的时间。这就是我想建议的。我的答案无论如何都不完整,事实上,关于分配的信息仍然太少,因此速度会非常缓慢。我只是在正确的方向上给了你一点提示。你是对的,在数千次分配之后,分配器确实需要更多的时间来分配条目,即使树的深度没有那么大。但是,我觉得没有一种方法可以只使用位来存储/表示映射的地址,最好将其存储在一个结构中。。。否则,您只能分配,但决不能免费@伊万斯坦诺夫听起来你的方向是对的。祝你好运!