[OS]Three Easy Pieces Chapter 16
Segmentation
1 Segmentation: Generalized Base/Bounds
传统的动态重定位会导致内存空间的浪费(整个用户地址空间可能只有一小部分真正使用,大部分是空闲的)。因此,可以使用分段的方式,将用户地址空间按照逻辑分为不同的segment,每个segment都有一对base/bound寄存器。需要注意的是,在进行地址转化的时候,必须将虚拟地址首先转化为段内偏移,然后在转换为物理地址。
2 Which Segment Are We Referring To
一种普遍的做法是,用虚拟地址的高位来索引不同的段,低位作为段内的偏移。
这种做法的缺点是限制了每个段的大小。
另外一种可能的做法是通过地址的来源来判断段。如果地址来自PC,那么肯定是代码段;如果地址来自sp,那么肯定是栈段;否则就是堆段。
3 What About The Stack
因为堆是逆向增长的,因此需要额外处理。具体地,硬件应该添加一个标记位,用来指示地址增长方向是正向的还是逆向的。
4 Support for Sharing
通过对每个segment添加保护位(可读、可写、可执行等),可以安全的在不同的进程间共享内存。
同时,MMU在进行地址转换的时候,也要确保某个进程对某块内存有正确的访问权限。
5 OS Support
段式内存也有一些问题:
- 上下文切换的时候操作系统需要负责切换所有段的base/bound寄存器
- 段增长
- 如果heap有足够的内存,
malloc
直接在heap中分配内存,然后返回相应的地址 - 如果heap没有足够的内存,
malloc
会调用sbrk
系统调用去增长heap,如果有足够的空间供增长,操作系统会更新堆段的bound寄存器。
- 如果heap有足够的内存,
- 管理空闲内存:段式内存最大的问题是会外部碎片问题。有一系列算法来管理内存(BF,WF,FF,伙伴算法等),但是都无法根本上解决外部碎片问题。
[OS]Three Easy Pieces Chapter 16
https://erlsrnby04.github.io/2024/11/10/OS-Three-Easy-Pieces-Chapter-16/