首先,所有应用程序对于硬件的所有操作都必须通过操作系统来完成。
我们可以把操作系统理解为在硬件和应用程序之间插入的一层软件
操作系统由两个基本功能:(1)防止硬件被关注的应用程序滥用.(2)向应用程序提供简单一致的机制来控制复杂而又通常大不相同的硬件设备。操作系统通过几个基本的抽象概念(进程,虚拟内存和文件)来实现这几个功能,在本文中只讨论虚拟内存.
文件是对I/O设备的抽象表示,虚拟内存是对主存和磁盘I/O设备的抽象表示,进程是对处理器,主存和I/O设备的抽象表示.虚拟内存在Linux一般展现形式是swap分区.
虚拟内存是一个抽象概念,它为每一个进程都提供了一个假象,即每个进程都是独占的使用主存,每个进程看到的内存都是一值的,称之为虚拟地址空间,
虚拟内存是一种内存管理的技术,使得应用程序认为他拥有连续可用的内存,实际上,他是被分割为多个物理碎片的,
需要的时候进行数据交换.
物理地址可以按照帧来组织,并且分配给进程的物理帧也可以不连续
,这时候需要MMU(内存管理单元)将逻辑页映射到内存的物理页帧上.
虚拟内存是对程序存储器的抽象。在Linux中,地址空间最上面是保留给操作系统中的代码和数据的,这对于所有进程来说都是一个样子。地址空间的底部区域存放用户进程定义的代码和数据.图中的地址是从下往上增大的.
每个进程看到的虚拟地址空建由大量的区构成
我们在这里简单了解一下,我们将从最低的地址开始,逐步向上进行介绍
- 程序的代码和数据。对于所有的进程来说,代码时从同一固定的地址开始的,紧接着是C全局变量相对应的数据位置。代码和数据区是直接按照可执行目标文件的内容初始化的.
- 堆。代码和数据区之后进随着的是运行时的堆.代码和数据区在进程一开始运行的时候就指定了大小.而堆是可以在运行的时候动态的扩展和收缩的.
- 共享库.大约在地址空间的中间部分有一块是用来存放像C标准库和数学库这样的共享库的代码和数据的区域.栈.位与用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用.和堆一样.用户栈在程序的执行过程中是可以进行动态的收缩和扩展,当我们调用一个标准库函数的时候,用户栈会进行增长,当一个函数返回时候,栈就会收缩.
- 内核虚拟内存.地址空间顶部的区域是为内核保留的.不允许应用程序来读取这个区域的内容或者直接调用内核代码定义的函数.他们必须通过内核调用来执行这些操作
虚拟内存的好处:
- 为每个进程提供了独立的地址空间,保护每个进程的地址空间独立,不会被其他进程破坏
- 读写内存的安全性,对于物理内存本身不存在限制访问,任何地址都可以进行读写,操作系统要求不同的页面具有不同的访问权限.
- 使用更多的内存
补充一些小知识:
- 虚拟内存是Windows 为作为内存使用的一部分硬盘空间。虚拟内存在硬盘上其实就是为一个硕大无比的文件,文件名是PageFile.Sys,通常状态下是看不到的。必须关闭资源管理器对系统文件的保护功能才能看到这个文件。虚拟内存有时候也被称为是“页面文件”就是从这个文件的文件名中来的。
- 虚拟存储器是由硬件和操作系统自动实现存储信息调度和管理的。它的工作过程包括6个步骤:
①中央处理器访问主存的逻辑地址分解成组号a和组内地址b,并对组号a进行地址变换,即将逻辑组号a作为索引,查地址变换表,以确定该组信息是否存放在主存内。
②如该组号已在主存内,则转而执行④;如果该组号不在主存内,则检查主存中是否有空闲区,如果没有,便将某个暂时不用的组调出送往辅存,以便将这组信息调入主存。
③从辅存读出所要的组,并送到主存空闲区,然后将那个空闲的物理组号a和逻辑组号a登录在地址变换表中。
④从地址变换表读出与逻辑组号a对应的物理组号a。
⑤从物理组号a和组内字节地址b得到物理地址。
⑥根据物理地址从主存中存取必要的信息。