虚拟内存是一种抽象,它为每个进程提供了其专有使用主内存的错觉。每个进程都具有相同的内存统一视图,称为虚拟地址空间。
在linux中,地址空间的最上部分保留给操作系统中所有进程通用的代码和数据。地址空间的下半部分保存用户进程定义的代码和数据。
每个进程看到的虚拟地址空间由许多定义明确的区域组成每个区域都有特定的用途。
- 程序代码和数据。对于所有进程,代码都从相应的固定地址开始,然后是与全局c变量相对应的数据位置。代码和数据区域直接从可执行对象文件的内容(在本例中为hello可执行文件)初始化。
- 堆。代码和数据区域紧随运行时堆之后。与代码和数据区域不同,代码和数据区域在进程开始运行之后便会固定大小,而由于调用了C标准库历程,堆在运行时会动态扩展和收缩作为malloc和free。
- 共享库。在地址空间的中间附近是一个区域,用于保存C标准库和数学库等共享库的代码和数据。共享库的概念是一个功能强大但有些困难的概念。
- 栈。用户虚拟地址空间的顶部是用编译器用来实现函数调用的用户堆栈。就像堆一样,用户堆栈在程序执行期间动态地扩展和收缩。特别是,每次我们调用函数,栈会增长。每次我们从函数返回时,它都会收缩。
- kernel虚拟内存。地址空间的顶部区域是为kernel保留的。不允许应用程序读取或写入此区域的内容或直接调用kernel代码中定义的函数。相反,他们必须调用kernel来执行这些操作。
为了使虚拟内存正常工作,需要在硬件和操作系统软件之间进行复杂的交互,包括处理器生成的每个地址的硬件转换。基本的思想是将进程的虚拟内存的内容存储在磁盘上,然后使用主内存作为磁盘的缓存。