内存使用与分段
内存使用方式:将程序放到内存中,PC指向开始地址
重定位
程序中的地址往往是指相对地址,需要结合基地址才能找到程序真实位置
重定位时机:
- 编译时
- 载入时
- 运行时
编译时重定位
在编译过程中已经确认哪块内存空闲,并且之后该内存块也不会出现大的变化,适合硬系统
特点:只能放在内存空间的固定位置,比较僵硬
载入时重定位
在程序载入内存时,发现空闲内存,完成重定位
特点:更灵活一些,但是在程序执行过程中给将出现停滞,一旦载入后内存无法移动
运行时重定位
交换
交换是一种将阻塞、睡眠的进程所利用的内存空间,交换至磁盘,以提高内存利用率的思想
每次交换相当于一次重定位,此时程序载入后内存的位置并非一成不变(前两种方法不满足交换思想)
运行时重定位
运行每条指令时完成重定位,每执行一条指令都需要通过基地址和逻辑地址,算出最终的物理地址
其中,基地址在进程的PCB中
特点:
- 灵活方便
- 满足交换的思想(内存利用率高)
整体过程
- 载入程序至内存
- 从PCB取出基地址
- 将基地址与偏移地址相加(硬件支持(MMU),需要高效执行),得到物理地址
- 取址执行
程序分段
根据每个程序段的特点,将程序分成若*分,每部分加载至内存的不同位置
需要维护一个段表,里边存储基地址,定位具体指令/数据的过程如下:
- 得到段号
- 根据段号查段表,获得相应的基地址
- 利用基地址+段内偏移找到对应的指令/数据
MOV [es:bx],ax
为什么分段?
想象一个场景:假如程序没分段存入内存,由于栈不断增长,此时栈满了,怎么办?
需要在内存中开辟一个更大的内存空间,重新把每个部分都放至新的内存空间中,既效率低下,同时内存也有可能没有那么大的连续空间
GDT&LDT
操作系统启动程序中也有类似的段表,它叫GDT
普通进程的段表,叫LDT