内存是什么?有什么作用?
内存是用于存放数据的硬件。程序执行前需要先放到内存中才能被 CPU 处理。(缓和 CPU 与硬件之间的速度矛盾)
在多道程序环境下,系统中会有多个程序并发执行,也就是说会有多个程序的数据需要同时放到内存中。那么,如何区分各个程序的数据是放在什么地方的呢?
问题:如何区分各个程序的数据存放的位置
- 内存中也有一个一个的小房间,每个小房间就是一个 存储单元
- 给内存的存储单元 编号
- 如果计算机 按字节编号,则 每个存储单元大小 为 1 字节,即 8B,即 8 个二进制位
- 如果 字长为 16 位的计算机 按字编址,则 每个存储单元大小 为 1 个字,即每个字大小为 16 个二进制位
常用的数量单位
一台手机/电脑有 4GB 内存,是什么意思?
是指该内存中可以存放 42^30 各子节。如果是按字节编址的话,也就是有 420^30=2^32 个小房间。
2^10 = 1K(千)
2^20 = 1M(兆,百万)
2^30 = 1G(十亿,千兆)
指令的工作原理
对于一个写好的程序,经过编译、链接,会形成可执行文件。
可执行文件中的内容是一个个的指令(二进制),指令中的地址都是相对地址(相对于该可执行文件的地址,又称逻辑地址)。
每次真正运行的时候,需要把可执行文件装入内存中,内存会开辟一段空间专门给这个程序。
这样就会涉及到两个问题:
- 逻辑地址和物理地址的转换
- 装入方式
装入方式
绝对装入
在编译时,如果知道程序将放在内存的位置,编译程序就直接产生绝对地址的目标代码。
缺点:如果分配的内存地址发生改变,需要重新编译链接生成新的目标代码,灵活性不高
可重定位装入(静态重定位)
编译链接生成目标代码的时候,依然生成相对地址,当装入内存的时候,把所有地址都加上起始物理地址。
缺点:在装入一个作业时,必须分配其要求的全部内存空间,如果没有足够的内存,就不能够装入该作业。作业一旦装入内存,在运行期间也不可以移动,也不可以申请新的内存空间
动态运行时装入(动态重定位)
装入内存的时候,依然采用相对地址,把地址转换工作推迟到程序真正要执行时才进行。需要借用一个重定位寄存器的支持。
重定位寄存器中保存装入模块存放的 起始位置。
特点:
- 可将程序分配到 不连续 的内存空间中
- 运行某一部分代码时,装入相应的代码即可
- 便于用户共享程序段
采用动态重定位时 允许程序在内存中发生移动。
并且可将程序分配到不连续的存储区中;在程序运行前只需装入它的部分代码即可投入运行,然后在程序运行期间,根据需要动态申请分配内存;便于程序段的共享,可以向用户提供一个比存储空间大得多的地址空间。
链接方式
静态链接
在程序运行之前,先将各目标模块及它们所需的库函数连接成一个完整的可执行文件(转入模块),之后不再拆开
装入时动态链接(静态重定位)
将各目标模块装入内存时,边装入边链接的方式
运行时动态链接(动态重定位)
在执行程序中需要用到的目标模块才对它进行链接。优点:方便修改和更新,便于对目标模块的共享。