计算机系统009 - 操做系统之进程

上一篇计算机系统008 - 操做系统概况中讲到,计算机操做系统发展的两个主要方向是提升CPU使用率,以及下降响应时长。这二者在微观调度方法一级来看是相互违背的,但从宏观调度策略来说,仍是能够作出折中的利弊权衡。固然,并不是全部计算机系统都追求所谓的平衡,不少时候特定领域的系统更重视高实时响应,而有的场景只须要尽量利用CPU计算能力便可。 数据结构

方向决定方法,对于进程的理解,就从这两个目标开始。 多线程

1. 进程

进程这个概念突然跳出来,略显突兀,但是不少资料上就这么天然地放在这里。为了更好地理解进程概念的由来,这里先对照计算机系统发展史来讲明一下。 异步

1.1 进程的由来

最先的时候,也就是单处理器时期,系统要执行一个计算任务的步骤是将整个程序加载到内存中,而后由CPU逐条读取并执行指令。程序包括代码指令和预约的数据,指令执行期间,确定会产生一些计算结果,部分为临时使用。因此天然而言,寄存器中应当保存一部分临时值,举个例子,加法器执行一个加法运算,寄存器中就须要存储CF进位信息。那么总的来说,一个程序运行后,至少会包含以下信息: 模块化

  • 程序代码
  • 数据集
  • 运行时信息

这个时期中计算机系统的计算时间主要经过预定或批处理系统监控获取,所存在的最大问题是CPU和I/O运行速率量级相差太大,CPU的速率远远高过I/O速率,致使一旦执行到I/O指令时,系统中CPU资源就处于闲置状态,而指令每次执行,又至少会涉及到一次内存地址的访问。也就是说,系统运行期间,CPU资源被大量浪费post

为了提高CPU资源使用率,下降计算成本,可行的主要方法是加载更多的程序到内存中,一旦某个程序要执行I/O操做,就切换到其余程序运行。固然这里可以切换的前提是,I/O具体操做由其余单元进行控制,只需少许CPU执行先后准备、收尾工做便可,典型的有DMA直接内存访问。既然涉及到程序切换,那就势必要对一个运行中程序的全部相关信息进行统一管理,这样才能以该单位进行切换避免出错,而这里,这个单位就叫作进程。 操作系统

1.2 进程状态

前面讲了将内存中运行中的程序也就是进程进行切换,来达到提高CPU利用率的目的。既然有切换,也就意味着至少有运行、非运行两种状态。在该粒度控制下,CPU能够在多个程序间进行切换,避开I/O操做的闲置指令周期,提高总体使用率。 线程

然而上面的调度只是粗粒度的,任什么时候候,要想作出更精确的决定,就必须基于更多的有效信息。对于操做系统来说,要想更精确地在不一样进程间切换CPU,就必须掌握更多进程的有效信息,而增长信息的第一步,就是下降粒度,细化进程状态的分类。例如对于非运行状态而言,它难以对新建立的进程和处于I/O等待过程当中的进程作区分,这样一来,将处于I/O等待过程当中的从新运行就纯属对CPU资源的浪费行为。 设计

在上述两种状态的基础上,现代操做系统一般会区分为以下几种状态:
指针

  • 新建态
  • 就绪态
  • 挂起态(可选)
    添加挂起态的根本缘由是每多加载一个进程进入内存空间就多了一个选择,就能够更大程度地避开I/O等待,有效利用CPU资源。但因为物理内存有限,致使能加载入内存的进程数量也有限。为了拥有更多可选择进程,就经过将一部分处于I/O等待过程当中的进程从内存空间写出到磁盘空间,当须要从新调度被写出进程时,再从磁盘空间从新读取。
    固然也存在其余方法去下降一个进程所需的物理内存,如基于页交换硬件支持,来实现只加载进程的必要信息而非所有内容来实现下降内存占用。这一部分会再后面的内存管理进一步介绍。 cdn

    • 阻塞/挂起态
    • 就绪/挂起态
  • 阻塞/等待态
    进程在某些事件发生前不能继续执行,如I/O操做完成事件。
  • 运行态
  • 退出态

1.3 进程调度

以下图所示,内存(虚拟内存)中进程总体构成以下。进程状态属于进程运行时信息中的一部分,现代操做系统中比较通用的运行时状态信息是一个称为进程控制块PCB(Process Control Block)的结构体。

PCB中主要含有三类信息:

  • 进程标识信息
    表示信息主要指标识符,包括进程ID(PID)、父进程ID、用户ID(UID)

  • 进程状态信息
    包括用户可见寄存器、控制和状态寄存器、栈指针三个子类型数据,一般CPU设计中存在一组称为程序状态字PSW(Program Status Word)的寄存器,它包含条件码和其余状态信息。

    以Intel X86为例:

  • 进程控制信息
    包括调度和状态信息(如优先级、事件等)、数据结构、进程间通讯、进程特权、存储管理、资源的全部权和使用状况等。

而所谓的各类状态进程队列,实际上都是以链表形式管理各进程PCB数据结构。

至此咱们知道,进程由代码、数据、栈、运行时信息组成,进程概念的提出主要是便于调度管理,其中所包含的运行时信息能够为调度方法提供有效信息。而调度自己又是经过在处于不一样状态的进程间切换以避开I/O等待,从而达到提升CPU利用率的目的。

2. 线程

上一节中咱们从整个操做系统的角度来讨论了进程概念的由来和必要性,同时也提到,在具有更多有效信息的基础上,更小粒度的控制能够达到更加精确的调度结果,从而充分利用CPU。那么对于每个进程而言,是否有方法能够达成更精细的控制?

答案就是线程。

2.1 线程概念

突然又跳出来一个名词,线程。从字面来看,也看不出什么,只好记住一个概念,线程是对进程进行更小粒度的细分。对于单处理器单核系统来说,每次只能运行一个进程,即便进行了更小粒度的细分,也并不能在总体上加快进程运行速度,甚至有可能因为频繁切换而引入更多的消耗。 但考虑实际应用中,每一个程序代码中可能存在对于多个硬件部件的操做,如一部分进行内部数据计算、一部分负责文件读写、一部分负责显示刷新,最后一部分负责与用户交互

这里的用户交互使用了粗体进行强调,的确,单CPU单核状况下,只能经过不断切换进程内部执行的指令来提供良好的交互响应。例如,对程序代码进行两个部分的划分,一个部分负责文件读写,一部分负责与用户交互。每一个部分以一个线程形式运行,经过将CPU在进程内部的两个线程间切换,达到执行慢I/O操做的同时,也能插入执行用户交互代码。这样一来,在有限的硬件资源状况下,也必定程度下降了平均响应时长

对于单核来说,可能见效通常,可是对于多处理器多核来说,将每个线程分配各同一CPU种的多核后,那就是并行执行多个线程,总体所需时长也将降低。从用户的角度来说,一样是下降了程序执行所需平均时长

因此综合来看,线程在单核系统上中能够有效下降平均响应时长,在多核系统上,经过并行,能够有效下降总体时长。为了达成精确调度,与进程同样,线程也应该维护运行时信息。一般多线程技术适用于以下使用场景:

  • 前台和后台工做
  • 异步处理
  • 提升执行速度
  • 模块化程序结构

2.2 与进程关系


如上图所示,一个进程中至少含有一个线程(也称为主线程),固然也能够根据程序特性选择使用多线程技术。存在多个线程时,线程间相互共享进程用户地址空间。

什么意思?换句话就是说,假如内存是整个街道,那么进程就是一套套房子,每套房子相互之间共享道路等资源,就像进程在操做系统中共享总线同样。若是进程是房子,那么线程就是房子中的房间,各有各的户型。房间之间相互共享房子内公共资源,如厨房、卫生间等,固然每一个房间自己也存在必定内部资源,仅供本身使用。

若是房子建立了,那么确定至少会建立一个房间。若是房子销毁了,那么内部全部房间也天然被销毁。

2.3 线程支持级别

线程的实现上分为用户级(ULT, User Level Thread)和内核级(KLT, Kernel Level Thread)两种。

  • 用户级
    线程管理全部工做在应用程序内完成,内核意识不到线程的存在。即应用程序自己拥有绝对自主权,它能够根据程序特色自由使用线程管理策略,同时,也避免了因为某些操做系统内核不支持多线程而没法使用线程技术。
    但因为内核未进行支持,内核仍以进程为单位对程序进行调度。所以在线程中调用操做系统API时,一旦发生阻塞,则整个进程都将被阻塞。

  • 内核级
    对应的有,内核级线程中线程管理工做所有由内核完成,应用程序只须要提交任务为线程便可。与用户级线程相比,内核掌握了更多线程相关信息,能够将同一个进程调度到不一样处理器中,某一个线程的阻塞也再也不会阻塞整个进程。
    但因为应用程序进程仍处于用户模式,而线程处于内核模式,所以再讲控制从一个线程传送到同一个进程的另外一个线程时,须要进行状态切换。

因为各有优劣,某些操做系统就混合使用了用户级、内核级线程,在混合方法中,线程在用户空间中建立、调度,但也能够托管一部分给内核调度。经过在程序级别与硬件进行匹配,达到最合适的效果。

3. 总结

本篇主要从提升CPU利用率和下降平均响应时长两个角度来分析了进程、线程概念的由来和必要性,它们均只是内存中的调度单位,建立进程或线程的目的是便于进行下一步的并行执行,也就是在分配给多个CPU或多核或是单核上,按照必定策略调度执行。下一篇中将从并行设计开始提及,看看切换过程当中要注意哪些事项。

相关文章
相关标签/搜索