Memory management

Memory management

cat /proc/pid/maps # 查看当前进程的各段的内存加载信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#:~$sudo cat /proc/7/maps
[sudo] password for yixuan_zhang:
00200000-0025a000 r--p 00000000 00:16 562949953668040 /init
0025a000-0034f000 r-xp 00059000 00:16 562949953668040 /init
0034f000-00361000 rw-p 0014d000 00:16 562949953668040 /init
00361000-00363000 rw-p 0015e000 00:16 562949953668040 /init
00363000-0036a000 rw-p 00000000 00:00 0
020b0000-020b7000 rw-p 00000000 00:00 0 [heap]
020b7000-020b9000 rw-p 00000000 00:00 0 [heap]
7efc18300000-7efc18301000 ---p 00000000 00:00 0
7efc18301000-7efc18316000 rw-p 00000000 00:00 0
7efc18316000-7efc18317000 ---p 00000000 00:00 0
7efc18317000-7efc1832c000 rw-p 00000000 00:00 0
7ffed4d66000-7ffed4d87000 rw-p 00000000 00:00 0 [stack]
7ffed4dd8000-7ffed4ddc000 r--p 00000000 00:00 0 [vvar]
7ffed4ddc000-7ffed4ddd000 r-xp 00000000 00:00 0 [vdso]
#起始位置 终止位置 权限 偏移量 主设备号:副设备号 文件inode号 文件路径

cat /proc/pid/status # 查看当前进程状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#:~$sudo cat /proc/7/status
Name: init
Umask: 0022
State: S (sleeping)
Tgid: 7
Ngid: 0
Pid: 7
PPid: 1
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 128
Groups:
NStgid: 7
NSpid: 7
NSpgid: 7
NSsid: 7
VmPeak: 1812 kB
VmSize: 1812 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 88 kB
VmRSS: 88 kB
RssAnon: 88 kB
RssFile: 0 kB
RssShmem: 0 kB
VmData: 312 kB
VmStk: 132 kB
VmExe: 980 kB
VmLib: 4 kB
VmPTE: 40 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
CoreDumping: 0
THP_enabled: 1
Threads: 1
SigQ: 0/31282
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000010000
SigIgn: fffffffc7ff8fefe
SigCgt: 0000000000010000
CapInh: 0000000000000000
CapPrm: 000001ffffffffff
CapEff: 000001ffffffffff
CapBnd: 000001ffffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Seccomp_filters: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ffff
Cpus_allowed_list: 0-15
Mems_allowed: 1
Mems_allowed_list: 0
voluntary_ctxt_switches: 1
nonvoluntary_ctxt_switches: 0

内存管理目标

main memory

  • Main memory is central(中心) to the operation of a modern computer system.
  • Memory consists(组成) of a large array of bytes, each with its own address(每一个字节都拥有地址).
  • The CPU fetches(获取) instructions from memory according to the value of the program counter(PC). These instructions may cause additional(额外的) loading from and storing to specific(特定的) memory addresses.
  • A typical(典型的) instruction-execution cycle, for example, first fetches an instruction from memory. The instruction is then decoded(解码/译码) and may cause operands to be fetched from memory. After the instruction has been executed on the operands, results may be stored back in memory.

高速缓存

  • 高速缓存是一种存取速度比内存快,但容量比内存小的多的存储器,它可以加快访问物理内存的相对速度。

现代操作系统存在三级缓存,一级缓冲又分为指令缓存和数据缓冲,每个核心内均有二级缓存,三级缓存为所有核心公有

保护操作系统和用户进程

  • 用户进程不可以访问操作系统内存数据,以及用户进程空间之间不能互相影响
    • 通过硬件实现,因为操作系统一般不干预CPU对内存的访问
    • base register:基址寄存器,保存一个进程加载到内存空间的起始地址
    • limit register:限长寄存器,保存这个进程所占空间的长度
    • 上述两个寄存器的值只能被操作系统的特权指令加载,通过这两个寄存器可以确定一个进程的起始地址和结束地址,若访问地址不在这一区间内,操作系统将拒绝访问

逻辑地址和物理地址

地址空间和地址转换

  • 逻辑地址:面向程序的地址,总是从0开始编址,每 一条指令的逻辑地址就是与第1条指令之间的相对偏移,因此逻辑地址也叫相对地址或虚拟地址。
  • 物理地址:内存单元看到的实际地址,也称为绝对地址
  • 所有逻辑地址的集合称为逻辑地址空间,这些逻辑地址对应的所有物理地址集合称为物理地址空间。
  • 地址转换:由逻辑地址转换成物理地址。

内存管理单元MMU

程序在编译时以及加载时均采用逻辑地址(加载时不计算地址,在运行时计算真实地址),只有在运行时才使用真实地址

  • Memory-Management Unit完成逻辑地址到物理地址运行时的转换工作。
  • 在加载时将加载首地址存放在,重定位寄存器(relocation register)或基址寄存器

这解决了进程内存无法移动的问题,只需要将进程对应的重定位寄存器中的修改即可修改进程的加载位置

contiguous(连续的) memory allocation

define

  • In contiguous memory allocation, each process is contained in a single section of memory that is contiguous(相近的) to the section containing the next process.
  • 进程内部地址是连续的,进程与进程间是连续的

FIXED-SIZED PARTITION 固定大小分区

  • Memory is divided(划分) to several(数个) fixed-sized(固定大小的) partitions(分区). Each partition may contain exactly(恰好) one process.

存在一张内存分区表,用于查看分区是否被占用

当 P1所占用的内存为 6K 那么P1 将加载到 编号为 1 的分区中,此时 1号 分区的 occuiped 将变为 1 表示已经占用,这意味为 1号 分区将不允许有其他进程占用,剩余的 2k 将会浪费掉。浪费掉的空间被称为碎片。这是一种非常早期的分区方案。

Variable partition 可变分区

  • In the variable-partition scheme, the operating system(方案) keeps two tables indicating(表明) which parts of memory are available and which are occupied.(这两张表指的是占用表和空闲表)
  • Initially(初始时), all memory is available for user processes and is considered(看作) one large block of available memory, a hole.
  • Eventually,(最终) as you will see, memory contains a set of holes of various sizes(不同大小)

由于进程的加载与释放这势必会导致内存中出现一系列的孔洞,当相邻两个进程都释放时,所形成的孔洞将合并为一个孔洞

动态存储分配问题

  • 首次适应 分配首个足够大的孔,效率最高
  • 最佳适应 分配最小的足够大的孔,浪费最小
  • 最坏适应 分配最大的孔,产生的剩余孔更可能 被再利用

首次分配和最佳分配在执行时间和利用空间方面都好于最坏适应,首次适应的效率优于最佳适应

地址转换和保护

  • 两种连续分配方案的地址转换方式是相似的: 物理地址 = 基址 + 逻辑地址
  • 地址保护策略:与限长limit(寄存器)进行比较

CPU在每次依靠MMU内存映射单元计算逻辑地址时,逻辑地址均要与 [0,limit] 范围进行比较(因为都要加基地址故省去),若在这个范围内则进行地址转换(访问物理地址),否则不进行地址转换(抛出异常)

碎片

  • Fragmentation: some little pieces of memory hardly to be used.
    • internal fragmentation(内部碎片):针对固定分区来说,就是进程占用的固定分区的内存所导致有剩余内存,这部分内存被称为碎片
    • external fragmentation(外部碎片):针对可变分区来说,当所剩孔洞足够小,小到不支持进程分配,那么部分内存被称为碎片
  • 碎片的解决方法:compaction(压缩,紧凑),只有运行时地址转换才可以执行compaction,compaction的开销较大

现代操作系统已经不采用这种内存管理的方案了

参考:https://www.bilibili.com/video/BV1bf4y147PZ/