进程和线程
操作系统中核心的概念是进程:这是对正在运行程序的一个抽象。 没有进程的抽象,现代计算将不复存在。 ----《现代操作系统》第四版 机械工业出版社
(从这本书的作者中我们就可以产出作为一个学计算机专业出生的人罪域进程的理解是多么的重要,上学期学操作系统这门课的时候并没有总结,今天终于下定决心总结下了,因为实在是感觉太重要了。在描述一些重要的概念的时候我还是会借鉴书上的文字,害怕自己总结的有错。)
进程
在书中进程的定义是:
在任何多道程序设计系统中,CPU由一个进程快速切换成另一个进程,使每个进程各运行几十或者几百毫秒。严格的说,在某一个瞬间,CPU只能运行一个进程。但在一秒内,它可能运行多个进程,这样就产生并行的错觉,有时人们所说的伪并行就是指的这样情况,以此来区分多处理器系统(该系统有两或多个CPU共享同一物理内存)的真正硬件并行。人们很难对多个并行活动进行跟踪,以此经过多年的努力,操作系统的设计者开发了用于描述并行的一种概念模型(顺序进程),使得并行更容易处理。
在进程模型中,计算机上所有课运行的软件,通常也包括操作系统,被组织成若干顺序进程(sequential process),简称进程。
从概念上讲,每个进程拥有它自己的虚拟CPU。当然,实际上真正的CPU在多个进程间来回切换。
进程的定义(以前老师给我们总结)
1、进程是程序作用在一组数据上的一次执行。
2、进程是操作系统中一个可独立调度和资源分配的基本单位(不是最小而是基本单位)。
3、进程是可以和别的计算并发执行的计算。
举个例子:
进程和程序间的区别是很微妙的,但非常重要。用一个比喻可以更容易理解这一点。想象一位有一手好厨艺的计算机科学家正在为他的女儿烘制生日蛋糕。他有做生日蛋糕的食谱,厨房有所需的原料,做蛋糕的食谱就是程序(即用适当形式描述的算法),计算机科学家就是处理器(CPU),而做蛋糕的各种原料就是输入数据。进程就是厨师阅读食谱、取来各种原料以及烘制蛋糕等一系列动作的总和。
进程的状态
进程有三个基本状态:就绪状态
、运行状态
与阻塞状态
。
进程在运行的时候必处于这三个状态中的之一。
就绪状态
:进程获得必要资源,例如内存等,已经具备了执行条件,只是没有空闲的CPU,处于等待CPU的状态。在系统中,将处于就绪状态的多个进程的PCB表排成一个队列,或按照某种规则排在不同的队列中,这些队列称为就绪队列。
运行状态
:进程已经获得必要的资源及CPU,它的程序正在执行中,这时进程的状态称为执行状态。在多处理机系统中,可以有多个进程处于执行状态。在单处理机系统中,只能有一个进程处于执行状态,系统应尽量保证一个CPU上总有一个处于执行状态的进程,使CPU得到充分的利用。
阻塞状态
:进程因某等待事件发生(例如I/O请求、某些原语操作等)而处于暂停执行的状态,此时即使将CPU分配给它,它的程序也无法执行。在系统中,将处于阻塞状态的进程的PCB表排成一个队列,或因阻塞原因不同而将进程的PCB表排在不同的队列中,这些队列称为阻塞队列。
进程的状态转换
进程有四种状态变迁:
- 就绪→运行
调度程序选择这个进程 - 运行→就绪
调度程序选择另外一个进程 - 运行→阻塞
进程因为等待资源而被阻塞 - 阻塞→就绪
Linux进程有父进程、子进程, Windows的进程是平等关系。
线程
进程拥有资源,属于同一个进程的所有线程可以共享这些资源。此外,每个线程仅有较少的私用资源,如程序计数器、寄存器和栈等。
每一个线程是一个动态对象,它表示进程中的一条控制线索,执行一系列指令操作,是一个相对独立的、可被调度运行的基本单位。
线程由创建而产生,由撤消而消亡,在生命期间,线程可以处于就绪状态、执行状态和阻塞状态三个基本状态中。
这三个基本状态也像进程一样,会发生变迁,如就绪状态→执行状态,执行状态→阻塞状态,阻塞状态→就绪状态等。
不同类型的线程有着不同的属性和使用方法,三种主要的线程类型:
-
内核线程
一个内核线程可以独立工作,不需要与一个用户进程联系起来。 轻量级进程LWP
一个轻量级进程LWP是一个内核支持的用户线程,运行在用户空间。
内核线程基础上的高层抽象,因此……
每个进程可以有一个或多个轻量级进程LWP,用户进程通过轻量级进程LWP与
内核通信,每一个轻量级进程LWP都由一个单独的内核线程支持。可以被调度并且共享所属进程的地址空间和其它资源。
它们可以对I/O设备或其它资源进行系统调用,同时也能在I/O操作或资源访问时被阻塞。
除了内核堆栈和寄存器外,轻量级进程LWP也需要维护一些用户状态,主要包括用户寄存器上下文,当轻量级进程LWP被抢占CPU时这些内容必须保存下来,以便保证下次调度运行的正确进行。
-
为了节省系统开销,多个用户进程可以多路复用一个轻量级进程LWP,但是只有连接到轻量级进程LWP的进程,才能与内核通信。
-
用户线程
用户线程运行在用户空间,内核无需也无法感知它。每个用户线程仅需一个栈和程序计数器PC, 切换速度快。当一个用户线程被阻塞时, 它在停止之前选择并启动它的后继线程。
用户线程的实现是可能的,因为用户线程的上下文可以在没有内核干预的情况下被保存和恢复。每一个用户线程有自己的用户堆栈,一块用来保存用户级寄存器上下文以及如信号屏蔽等状态信息的内存区域。通过保存当前线程的堆栈和寄存器内容,以及装入新调度线程的那些堆栈和寄存器内容,可实现用户线程间的调度和上下文的切换。
内核仍然负责进程的切换,因为只有内核具有修改内存管理寄存器的权力。用户线程不是真正地可以调度的实体,内核没有保留它们的一点信息,内核只是简单地调度它们下面的进程,这些进程再使用库函数来调度它们的线程。当进程被抢占时,它们的线程也被抢占。
进程和线程的比较
在引入线程的操作系统中,不仅进程之间可以并发执行,而且属于同一个进程的多个线程之间也可以并发执行,因而使系统具有更好的并发性,可以更有效地使用系统资源和提高系统的吞吐量。
无论是传统的操作系统,还是引入线程的操作系统,进程都是拥有资源的一个独立单位,而线程仅拥有很少的一些私有资源(如程序计数器、寄存器和栈、线程表项等),但是它可以访问所属进程的所有资源。
在进程创建和进程撤消时,系统所付出的开销大于创建线程和撤消线程的开销。进程切换的开销远远大于线程切换的开销。此外,由于同一进程的多个线程具有相同的地址空间,使得它们之间的同步和通信也变得比较容易实现。
如果要学习更多的操作系统的只是,我推荐看《现代操作系统》第四版 Andrew S.Tanenbaum 和 Herbert Bos 著