mirror of
https://github.com/gatieme/LDD-LinuxDeviceDrivers.git
synced 2026-08-19 01:22:36 +08:00
...
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
服务器体系与共享存储器架构
|
||||
=======
|
||||
|
||||
| 日期 | 内核版本 | 架构| 作者 | GitHub| CSDN |
|
||||
| ------- |:-------:|:-------:|:-------:|:-------:|:-------:|
|
||||
| 2016-06-14 | [Linux-4.7](http://lxr.free-electrons.com/source/?v=4.7) | X86 & arm | [gatieme](http://blog.csdn.net/gatieme) | [LinuxDeviceDrivers](https://github.com/gatieme/LDD-LinuxDeviceDrivers) | [Linux内存管理](http://blog.csdn.net/gatieme/article/category/6225543) |
|
||||
|
||||
|
||||
|
||||
|
||||
在内核初始化完成之后, 内存管理的责任就由伙伴系统来承担. 伙伴系统基于一种相对简单然而令人吃惊的强大算法.
|
||||
|
||||
Linux内核使用二进制伙伴算法来管理和分配物理内存页面, 该算法由Knowlton设计, 后来Knuth又进行了更深刻的描述.
|
||||
|
||||
伙伴系统是一个结合了2的方幂个分配器和空闲缓冲区合并计技术的内存分配方案, 其基本思想很简单. 内存被分成含有很多页面的大块, 每一块都是2个页面大小的方幂. 如果找不到想要的块, 一个大块会被分成两部分, 这两部分彼此就成为伙伴. 其中一半被用来分配, 而另一半则空闲. 这些块在以后分配的过程中会继续被二分直至产生一个所需大小的块. 当一个块被最终释放时, 其伙伴将被检测出来, 如果伙伴也空闲则合并两者.
|
||||
|
||||
* 内核如何记住哪些内存块是空闲的
|
||||
|
||||
* 分配空闲页面的方法
|
||||
|
||||
* 影响分配器行为的众多标识位
|
||||
|
||||
* 内存碎片的问题和分配器如何处理碎片
|
||||
|
||||
|
||||
#1 高端内存与内核映射
|
||||
-------
|
||||
|
||||
|
||||
尽管`vmalloc`函数族可用于从高端内存域向内核映射页帧(这些在内核空间中通常是无法直接看到的), 但这并不是这些函数的实际用途.
|
||||
|
||||
重要的是强调以下事实 : 内核提供了其他函数用于将`ZONE_HIGHMEM`页帧显式映射到内核空间, 这些函数与vmalloc机制无关. 因此, 这就造成了混乱.
|
||||
|
||||
|
||||
#2 持久内核映射
|
||||
-------
|
||||
|
||||
如果需要将高端页帧长期映射(作为持久映射)到内核地址空间中, 必须使用kmap函数. 需要映射的页用指向page的指针指定,作为该函数的参数。该函数在有必要时创建一个映射(即,如果该页确实是高端页), 并返回数据的地址.
|
||||
|
||||
如果没有启用高端支持, 该函数的任务就比较简单. 在这种情况下, 所有页都可以直接访问, 因此只需要返回页的地址, 无需显式创建一个映射.
|
||||
|
||||
如果确实存在高端页, 情况会比较复杂. 类似于vmalloc, 内核首先必须建立高端页和所映射到的地址之间的关联. 还必须在虚拟地址空间中分配一个区域以映射页帧, 最后, 内核必须记录该虚拟区域的哪些部分在使用中, 哪些仍然是空闲的.
|
||||
|
||||
|
||||
|
||||
##2.1 数据结构
|
||||
-------
|
||||
|
||||
核在IA-32平台上在`vmalloc`区域之后分配了一个区域, 从`PKMAP_BASE`到`FIXADDR_START`. 该区域用于持久映射. 不同体系结构使用的方案是类似的.
|
||||
|
||||
```cpp
|
||||
// http://lxr.free-electrons.com/source/mm/highmem.c?v=4.7#L126
|
||||
static int pkmap_count[LAST_PKMAP];
|
||||
```
|
||||
`pkmap_count`(在[mm/highmem.c?v=4.7, line 126](http://lxr.free-electrons.com/source/mm/highmem.c?v=4.7#L126)定义)是一容量为`LAST_PKMAP`的整数数组, 其中每个元素都对
|
||||
应于一个持久映射页。它实际上是被映射页的一个使用计数器,语义不太常见。该计数器计算了内核
|
||||
使用该页的次数加1。如果计数器值为2,则内核中只有一处使用该映射页。计数器值为5表示有4处使
|
||||
用。一般地说,计数器值为n代表内核中有n-1处使用该页。
|
||||
和通常的使用计数器一样,0意味着相关的页没有使用。计数器值1有特殊语义。这表示该位置关
|
||||
联的页已经映射,但由于CPU的TLB没有更新而无法使用,此时访问该页,或者失败,或者会访问到
|
||||
一个不正确的地址。
|
||||
内核利用下列数据结构,来建立物理内存页的page实例与其在虚似内存区中位置之间的关联:
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 68 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
Reference in New Issue
Block a user