简书的Markdown我真的服了,以后我会把笔记源码上传到其他地方,大家可以下载后用Typora看,我感觉这个软件不错
6个段寄存器
CS
SS
DS
ES/FS/GS
保护模式下,16位的寄存器无法存放32位的段基地址
段寄存器中存放的不是某个段的基地址,而是某个段的选择子(Selector) 段基地址存放在段描述符表中
状态和控制寄存器
标志寄存器EFLAGS
指令指针EIP
-
4个控制寄存器
CR0/1/2/3
[图片上传失败...(image-21453a-1586848946729)]
-
CR0控制寄存器
<pre mdtype="fences" cid="n694" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important;">PE(Protected Enable):用于启动保护模式
PE=1,保护模式启动
PE=0,实模式下运行
PG(Paging Enable):分页允许位
表示芯片上的分页部件是否允许工作
</pre> 实模式/保护模式通过CR0的PE位切换
通过PG启用分页机制
-
CR3页目录基址寄存器
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="txt" cid="n700" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important;">保存页目录表的物理地址,页目录表总是放在以4K字节为单位的存储器边界上
地址的低12位总为0,不起作用,即使写上内容,也不会被使用
4K</pre>
全局描述符表寄存器GDTR
指示GDT表在RAM中的位置(物理起始地址)
中断描述符表寄存器IDTR
局部描述符表寄存器LDTR
16位寄存器,保存局部描述符表LDT段的选择子
任务状态寄存器TSR
硬件及Linux的分段机制
内存地址
逻辑地址:段+偏移量组成
线性地址:32位无符号整数
物理地址
MMU通过分段单元将逻辑地址转换成线性地址
分页单元将线性地址转换成一个物理地址
段描述符
每个段由一个8个字节的段描述符来表示
指出段的32位基地址和20位段界限
段描述符表
定义所有段的情况,所有描述符表本身都占据一个字节为8的倍数的存储器空间
全局描述符表GDT
局部描述符表LDT
地址转换过程
<pre mdtype="fences" cid="n768" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">实模式(20位)
16位段寄存器只记录段基址的高16位,因此段基址必须4位对齐(末4位为0)
不采用虚拟地址空间,直接采用物理地址空间
物理地址=段寄存器值*16+段内偏移
保护模式(32位)
16位段寄存器无法直接记录段的信息,因此需要与全局描述符表GDT配合使用
GDT中记录了每个段的信息(段描述符),段寄存器只需记录段在GDT中的序号
线性地址=段基地址+段内偏移
其中,段基地址是根据段寄存器所指明的GDT中的段描述符中的信息得到
物理地址:根据页表对线性地址进行转换而得到</pre>
段选择子格式
<pre mdtype="fences" cid="n771" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">索引号
13位,指定GDT表中的相应的段描述符
TI(Table Indicator)
1位,指明段描述符在GDT(TI=0)或LDT(TI=1)中
RPL(Request Privilege Level)
2位,当相应段选择符装入到CS寄存器中时,指明CPU的当前特权级(用户/内核)</pre>
[图片上传失败...(image-ab3df6-1586848946732)]
硬件及Linux的分页机制
分页单元
<pre mdtype="fences" cid="n775" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">功能:线性地址物理地址
关键任务
把所请求的访问类型与线性地址的访问权限比较,若此次内存访问无效,则产生一个缺页异常
页(page)
将线性地址分成以固定长度为单位的组
页表(page table)
将线性地址映射到物理地址的数据结构
存放在内存中,并在启用分页单元以前由内核对之进行初始化
页框(page frame)
把所有RAM划分成以固定长度为单位的组
每个页框可以包含一页,即页框长度等于页的长度
Intel处理器中,通过设置CR0寄存器的PG标志位来启用分页单元
当PG=0时,线性地址被解释成物理地址</pre>
页=页框=4k
页表为数据结构
三级分页
-
目录:最高10位
指向适当的页表
-
页表:中间10位
指向所在页框的物理地址
-
偏移量:最低12位
决定页框内的相对位置
正在使用的页目录表的物理地址存放在CPU的CR3寄存器中
[图片上传失败...(image-f5fb0f-1586848946732)]
每个页目录项4字节,最多1024项
用高20位指出32位页表地址即可
为什么使用三级分页模式
<pre mdtype="fences" cid="n816" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">减少每个进程页表所需RAM的数量
一级页表缺陷
使用一级页表需要220个表项(每项4字节,需要4MB)
二级模式特点
每个活动进程必须有一个页目录,但不必立即为进程的所有页表分配RAM
只为进程实际使用的那些虚拟内存区请求页表来减少内存需求
页目录和页表都可以多达1024项(210)
一个页目录的寻址能力102410244096=232</pre>
线性地址到物理地址的转换步骤
<pre mdtype="fences" cid="n819" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">第一步:形成页表地址
CR3包含着页目录的起始地址,用32位线性地址的最高10位A31~A22作为页目录的页目录项的索引,将它乘以4(每项4个字节),与CR3中的页目录的起始地址相加,形成相应页表地址。
第二步:形成页面地址
从指定的地址中取出32位页目录项,它的低12位为0,这32位是页表的起始地址。用32位线性地址中的A21~A12位作为页表中的页面的索引,将它乘以4,与页表的起始地址相加,形成32位页面地址。
第三步:形成32位物理地址
将A11~A0作为相对于页面地址的偏移量,与32位页面地址相加,得到物理地址。</pre>
Linux2.6.10以后采用四级分页
页全局目录PGD
页上级目录PUD
页中间目录PMD
页表PT
<pre mdtype="fences" cid="n836" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">没有启用物理地址扩展的32位系统,使用两级页表:
将“页上级目录”位和“页中间目录”位全设置为0
启用物理地址扩展的32位系统使用三级页表:
全局目录对应X86的PDPT,取消“页上级目录”
页中间目录对应X86的页目录
页表对应X86的页表
64位系统使用三级或四级页表,取决于硬件对线性地址的划分</pre>
进程页表
<pre mdtype="fences" cid="n839" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">一个进程的线性地址空间被分成两部分
0-3G(0x00000000~0xbfffffff)
用户态和内核态都可以访问
进程在用户态执行时,产生的线性地址小于0xc0000000
3G-4G(0xc0000000~0xffffffff)
只有内核态可以访问
进程在内核态执行时,它执行的内核代码所产生的地址大于等于0xc0000000
进程的页全局目录
前768项(PAE未启用,启用时为前3项)
用来映射低于0xc0000000(PAGE_OFFSET)的线性地址,具体内容与进程相关
剩余表项(256项)
用来映射内核空间,对所有进程都一样</pre>
RAM的某些部分永久地分配给内核,用以存放内核代码以及静态数据
Linux的虚拟空间
每个进程拥有3G用户空间
内核占用最高1G作为系统空间
系统空间由所有进程共享
通过页表把虚存空间的一个地址转换为物理空间中的实际地址
页框管理
[图片上传失败...(image-c3662-1586848946731)]
每个物理页框用一个页描述符表示
struct page
所有物理页框的描述符组织在mem_map的数组中
count:页的使用引用计数器
flags:页框状态
页框分配器
页框被命名为伙伴系统
-
内核连续页框分配请求导致外碎片问题
频繁请求和释放不同大小的一组连续页框
-
解决
利用MMU把一组非连续的物理页框映射到连续的线性地址空间
伙伴系统
<pre mdtype="fences" cid="n871" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">
把所有空闲页框分组为10个块链表
每个块链表分别包含大小为1,2,4,8,16,32,64,128,256和512个连续的页框
每个块的第一个页框的物理地址是该块大小的整数倍
例如:大小为16个页框的块,其起址是16×4KB的倍数
结构为free_area_t的空闲内存管理数组free_area
与空闲内存管理数组相关的位图数组map</pre>
[图片上传失败...(image-245855-1586848946731)]
伙伴的必要条件
大小相同
物理地址连续
假定伙伴的大小为b,第一个伙伴的第一个页框的物理地址必须是
2×b×4KB的倍数
事实上伙伴是通过对大块的物理内存划分获得的
当两个伙伴都空闲时,则合并成一个更大的块
位图描述伙伴的状态
<pre mdtype="fences" cid="n915" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">一对伙伴只使用一个位表示
0:伙伴的状态一致,此时要么全空闲,要么全不(或部分)空闲
如果全空闲,必然被合并了
两种情况下,对应的块数据结构都不在此free_area_t结构中
1:伙伴的状态不一致,此时必然有一个空闲、一个不空闲
表示对应的块数据结构在此free_area_t结构的链表中</pre>
[图片上传失败...(image-6af383-1586848946731)]
三列map的值都根据物理内存那列看
[图片上传失败...(image-e64c1b-1586848946731)]
[图片上传失败...(image-20bbc-1586848946731)]
伙伴系统中块的分配与释放函数
<pre mdtype="fences" cid="n927" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">块分配函数:__rmqueue(zone, order)
根据输入参数order,在相应链表(管理区描述符地址zone)中查找连续的空闲页框
返回所分配的第一个页框对应的页描述符的地址
块释放函数:__free_pages_bulk(page, zone, order)
把释放的页框插入到伙伴系统的数据结构中,以便以后可以在分配中使用
在这里循环检查bitmap确认伙伴块是否空闲,空闲则合并成一个单独的块,并把此块加入到合适的链表中</pre>
伙伴系统举例
215=2的15次方
<pre mdtype="fences" cid="n931" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">伙伴系统的构建(假设有128MB的RAM)
128MB最多可以分成215=32768个页框,214=16384个8KB(2页)的块或213=8192个16KB(4页)的块,直至64个大小为512个页的块
free_area[0]对应的位图由16384位组成,每对伙伴(大小为1个页框)对应其中的一位
free_area[1]对应的位图由8192位组成,每对伙伴块(大小为2页)对应其中的一位
…
free_area[9]对应的位图由32位组成,每对伙伴(大小为512页)对应其中的一位</pre>
<pre mdtype="fences" cid="n932" lang="txt" class="md-fences md-end-block ty-contain-cm modeLoaded" spellcheck="false" style="box-sizing: border-box; overflow: visible; font-family: "Roboto Mono", "Source Sans Pro", Monaco, courier, monospace !important; font-size: 0.85rem; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248) !important; position: relative !important; width: inherit; border: 1px solid rgb(244, 244, 244); -webkit-font-smoothing: initial; line-height: 1.43rem; border-radius: 2px; overflow-wrap: normal; margin: 0.8rem 0px !important; padding: 0.3rem 0px !important; color: rgb(52, 73, 94); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">伙伴系统的使用(假设要请求一个大小为128个页框(0.5MB)的块
算法先free_area[7]中检查是否有空闲块(块大小为128个页框)
若没有,就到free_area[8]中找一个空闲块(块大小为256个页框)
若存在这样的块,内核就把256个页框分成两等份,一半用作满足请求,另一半插入free_area[7]中
如果在free_area[8]中也没有空闲块,就继续找free_area[9]中是否有空闲块
若有,先将512分成伙伴,一个插入free_area[8]中,另一个进一步划分成伙伴,取其一插入free_area[7]中,另一个分配出去
如果free_area[9]也没有空闲块,内存不够,返回一个错误信号</pre>
内存区管理
基于页面的分配器不能满足多种要求:
内核中大量使用各种数据结构,大小从几个字节到几十上百不等,都取整到2的幂次个页面那是完全不现实的
slab分配器
将内存区看成对象
将对象按照类型分组成不同的高速缓存
每种对象类型对应一个高速缓存
slab分配器通过伙伴系统分配页框
每个slab由一个或多个连续的页框组成,这些页框中包含已分配的对象,也包含空闲的对象
每个slab的三种状态
全满
半满
全空
分配优先级:半满》全空》项buddy系统申请页面生成一个新的slab
进程虚拟空间
Linux把进程虚拟空间分成内核区和用户区
mm_struct
- 每个进程有且只有一个mm_struct结构,描述进程的虚拟内存
vm_area_struct(线性区描述符)
描述进程的虚拟内存地址区域(线性区)
每个进程可以有多个VM area
对页错误处理有同一规则的进程虚拟内存部分,如共享库、堆栈
page描述一个物理页
[图片上传失败...(image-32bd2f-1586848946731)]
vm_offset
该区域的内容相对于文件起始位置的偏移量,或相对于共享内存首址的偏移量。
vm_next
指向下一个vm_area_struct结构体,所有vm_area_struct结构体链接成一个单向链表
链表首地址由mm_struct中成员项mmap指出
vm_ops
指向vm_operations_struct结构体的指针
该结构体中包含着指向各种操作函数的指针