Linux内存管理

简书的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结构体的指针

该结构体中包含着指向各种操作函数的指针

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,607评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,047评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,496评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,405评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,400评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,479评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,883评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,535评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,743评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,544评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,612评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,309评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,881评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,891评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,136评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,783评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,316评论 2 342

推荐阅读更多精彩内容