操作系统有两个基本功能:防止硬件被失控的应用程序滥用;为应用程序低级设备方面提供简单的抽象。比如进程是对处理器、主存和I/O设备的抽象表示,文件是对I/O设备的抽象表示,虚拟存储器是对主存和磁盘I/O设备的抽象表示。
一、进程
进程是操作系统对运行程序的一种抽象,在一个系统上可以同时运行多个进程,每个进程都好像独占使用硬件。我们称为并发运行,实际上是一个进程指令和另一个进程指令是交替执行的。操作系统实现这种交替执行的机制称为上下文切换。
操作系统保存进程运行所需的所有状态信息。这种状态,也就是上下文,包括许多信息,比如PC和寄存器文件的当前值,以及主存的内容。在任何时刻,系统上都只有一个进程正在运行。当操作系统决定从当前进程转移控制权到某个新进程,它就会进行上下文切换,即保存当前进程的上下文,恢复新进程的上下文,然后将控制权转移到新进程。
实现进程这个抽象概念需要低级硬件和操作系统软件的紧密合作。
二、线程
尽管通常我们认为一个进程只有一个的控制流,但在现代系统中,一个进程实际可以由多个称为线程的执行单元组成,每个线程都运行在进程上下文中,并共享同样的代码和全局数据。
由于网络服务器对并行处理要求,线程称为越来越重要的编程模型,因为多线程之间比多进程之间更容易共享数据,也因为线程一般都比进程更高效。
三、虚拟存储器
虚拟储存器是一个抽象概念,为每个进程提供了一个假象,每个进程都独占使用主存。每个进程都看到的存储器都是一致的,称为虚拟地址空间。在Linux中,最上面的四分之一的地址空间是预留给操作系统中的代码和数据的,这对所有进程都一样。底部的四分之三的地址空间是用来存放用户进程定义的代码和数据。
- 程序代码和数据。代码是从同一固定地址开始,紧接着是和C全局变量相对应的数据区。代码和数据区是由可执行目标文件直接初始化的
- 堆。代码和数据区紧接着是运行时堆。代码和数据区是在进程一旦开始时就被指定了大小。如果调用malloc和free这样的C标准库函数,堆可在运行时动态地扩展和收缩。
- 共享库。在地址空间的中间附近是一块用来存放像C标准库和数学库这样的共享库的代码和数据区域
- 栈。位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。每次调用一个函数,栈会增长,。每次从函数返回,栈会收缩。
- 内核虚拟存储器。内核是操作系统总是在驻留在存储器中的部分,地址空间1/4部位是为内核预留。应用程序不允许读写这个区域的内容或直接调用内核代码定义的函数