[其他ST产品]

一文搞定Linux内存管理原理(转)

[复制链接]
455|60
手机看帖
扫描二维码
随时随地手机跟帖
shjuturt|  楼主 | 2022-7-27 14:26 | 显示全部楼层 |阅读模式
本帖最后由 shjuturt 于 2022-7-27 14:42 编辑

虚拟地址、物理地址、逻辑地址、线性地址


虚拟地址又叫线性地址。linux没有采用分段机制,所以逻辑地址和虚拟地址(线性地址)(在用户态,内核态逻辑地址专指下文说的线性偏移前的地址)是一个概念。物理地址自不必提。内核的虚拟地址和物理地址,大部分只差一个线性偏移量。用户空间的虚拟地址和物理地址则采用了多级页表进行映射,但仍称之为线性地址。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:28 | 显示全部楼层
DMA/HIGH_MEM/NROMAL 分区


在x86结构中,Linux内核虚拟地址空间划分0~3G为用户空间,3~4G为内核空间(注意,内核可以使用的线性地址只有1G)。内核虚拟空间(3G~4G)又划分为三种类型的区:


ZONE_DMA 3G之后起始的16MB
ZONE_NORMAL 16MB~896MB
ZONE_HIGHMEM 896MB ~1G

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:28 | 显示全部楼层
由于内核的虚拟和物理地址只差一个偏移量:物理地址 = 逻辑地址 – 0xC0000000。所以如果1G内核空间完全用来线性映射,显然物理内存也只能访问到1G区间,这显然是不合理的。HIGHMEM就是为了解决这个问题,专门开辟的一块不必线性映射,可以灵活定制映射,以便访问1G以上物理内存的区域。从网上扣来一图,

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:29 | 显示全部楼层
8392262e248d4989a9.png

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:29 | 显示全部楼层
高端内存的划分,又如下图, 8064262e248eea6c42.png

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:30 | 显示全部楼层
内核直接映射空间 PAGE_OFFSET~VMALLOC_START,kmalloc和__get_free_page()分配的是这里的页面。二者是借助slab分配器,直接分配物理页再转换为逻辑地址(物理地址连续)。适合分配小段内存。此区域 包含了内核镜像、物理页框表mem_map等资源。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:30 | 显示全部楼层
内核动态映射空间 VMALLOC_START~VMALLOC_END,被vmalloc用到,可表示的空间大。
内核永久映射空间 PKMAP_BASE ~ FIXADDR_START,kmap
内核临时映射空间 FIXADDR_START~FIXADDR_TOP,kmap_atomic

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:31 | 显示全部楼层
伙伴算法和slab分配器


伙伴Buddy算法解决了外部碎片问题.内核在每个zone区管理着可用的页面,按2的幂级(order)大小排成链表队列,存放在free_area数组。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:34 | 显示全部楼层
5045362e2496469405.png

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:36 | 显示全部楼层
具体buddy管理基于位图,其分配回收页面的算法描述如下,


buddy算法举例描述:


假设我们的系统内存只有16个页面RAM。因为RAM只有16个页面,我们只需用四个级别(orders)的伙伴位图(因为最大连续内存大小为16个页面),如下图所示。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:36 | 显示全部楼层
2773662e24a914bba2.png

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:38 | 显示全部楼层
7698662e24aa5d652d.png

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:49 | 显示全部楼层
order(0)bimap有8个bit位(页面最多16个页面,所以16/2) order(1)bimap有4个bit位(order(0)bimap有8个bit位,所以8/2); 也就是order(1)第一块由两个页框page1 与page2组成与order(1)第2块由两个页框page3 与page4组成,这两个块之间有一个bit位 order(2)bimap有2个bit位(order(1)bimap有4个bit位,所以4/2) order(3)bimap有1个bit位(order(2)bimap有4个bit位,所以2/2) 在order(0),第一个bit表示开始的2个页面,第二个bit表示接下来的2个页面,以此类推。因为页面4已分配,而页面5空闲,故第三个bit为1。 同样在order(1)中,bit3是1的原因是一个伙伴完全空闲(页面8和9),和它对应的伙伴(页面10和11)却并非如此,故以后回收页面时,可以合并。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:49 | 显示全部楼层
分配过程


当我们需要order(1)的空闲页面块时,则执行以下步骤:


1、初始空闲链表为: order(0): 5, 10 order(1): 8 [8,9] order(2): 12 [12,13,14,15] order(3): 2、从上面空闲链表中,我们可以看出,order(1)链表上,有一个空闲的页面块,把它分配给用户,并从该链表中删除。 3、当我们再需要一个order(1)的块时,同样我们从order(1)空闲链表上开始扫描。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:51 | 显示全部楼层
4、若在order(1)上没有空闲页面块,那么我们就到更高的级别(order)上找,order(2)。 5、此时(order(1)上没有空闲页面块)有一个空闲页面块,该块是从页面12开始。该页面块被分割成两个稍微小一些order(1)的页面块,[12,13]和[14,15]。[14,15]页面块加到order(1)空闲链表中,同时[12,13]页面块返回给用户。 6、最终空闲链表为: order(0): 5, 10 order(1): 14 [14,15] order(2): order(3):

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:52 | 显示全部楼层
回收过程


当我们回收页面11(order 0)时,则执行以下步骤:

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:53 | 显示全部楼层
1、找到在order(0)伙伴位图中代表页面11的位,计算使用下面公示: index = page_idx >> (order + 1) = 11 >> (0 + 1) = 5 2、检查上面一步计算位图中相应bit的值。若该bit值为1,则和我们临近的,有一个空闲伙伴。Bit5的值为1(注意是从bit0开始的,Bit5即为第6bit),因为它的伙伴页面10是空闲的。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:54 | 显示全部楼层
3、现在我们重新设置该bit的值为0,因为此时两个伙伴(页面10和页面11)完全空闲。

4、我们将页面10,从order(0)空闲链表中摘除。

5、此时,我们对2个空闲页面(页面10和11,order(1))进行进一步操作。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:55 | 显示全部楼层
6、新的空闲页面是从页面10开始的,于是我们在order(1)的伙伴位图中找到它的索引,看是否有空闲的伙伴,以进一步进行合并操作。使用第一步中的计算公司,我们得到bit 2(第3位)。

7、Bit 2(order(1)位图)同样也是1,因为它的伙伴页面块(页面8和9)是空闲的。

8、重新设置bit2(order(1)位图)的值,然后在order(1)链表中删除该空闲页面块。

使用特权

评论回复
shjuturt|  楼主 | 2022-7-28 16:56 | 显示全部楼层
9、现在我们合并成了4页面大小(从页面8开始)的空闲块,从而进入另外的级别。在order(2)中找到伙伴位图对应的bit值,是bit1,且值为1,需进一步合并(原因同上)。


10、从oder(2)链表中摘除空闲页面块(从页面12开始),进而将该页面块和前面合并得到的页面块进一步合并。现在我们得到从页面8开始,大小为8个页面的空闲页面块。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

30

主题

154

帖子

0

粉丝