1. 程序和进程的区别

首先来看一个故事:

在上述故事中,我们可以抽象出一个简单的计算处理模型:

  • 程序】就是那本食谱(存储在书架上,一种物理存在,用特定的描述形式阐述做菜的过程和方法)

  • 进程】就是做菜的这一系列活动(动态进行的),包括了洗菜、切菜、炒菜等等
  • CPU】就是A本人,他是所有操作的执行者
  • 数据】就是西红柿炒鸡蛋的各种原材料,包括了西红柿、鸡蛋...(将一系列数据经由CPU处理变成不同的数据)

2. 进程

2.1 进程的状态

进程就是程序关于某个数据集上的一系列活动
进程有三个状态,分别是:

  • 运行态【running】(actually using the CPU at that instant)
  • 就绪态【ready】(runnable; temporarily stopped to let another process run)
  • 阻塞态【blocked】(unable to run until some external event happens)


从上图中,我们可以很清楚地看到三种状态之间的转化过程:

  1. 当发生IO操作时,当前进程就会被阻塞直到IO操作完成
  2. 当调度器中断当前进程转而执行另一进程,原进程就会处于就绪状态
  3. 当调度器选择该进程,便会从就绪态转为运行态,享用CPU资源
  4. 当IO完成后,被阻塞的进程就会转为就绪态,等待操作系统的调度

2.2 进程上下文切换

当进程与进程间因中断(interrupt)或系统调用(system call)时会发生上下文切换

  • 正在执行的进程P0由于终端或者系统调用将cpu的使用权交还给os
  • os保存P0的PCB信息,并重新从内存中载入P1进程的pcb内容,并执行P1
  • P1执行后,由中断或者系统调用由交还使用权给os(调度器scheduler / 调度者scheduler)
  • 再回过头来执行P0(载入P0的PCB信息)

上下文切换的代价其实是很高的,需要大量的处理器时间(因此通常使用汇编完成),有时候1秒内可能执行上千次的上下文切换【CONTEXT SWITCH】

即便现代计算机正在逐渐降低上下文切换所占用的CPU时间,但那也仅是在CPU时钟周期降低,处理速度加快的情况下,而不是提升了上下文切换的效率

3. 为什么要引入线程的概念?

既然我们已经有了进程,那么为什么计算机科学家还要搞出一个线程的概念呢?

  1. 在系统中多应用将同时进行,经常会不断切换状态,通过将一个进程切分成多个线程,达到准并行【quasi-parallel】,程序模型将更简单(这些线程<u>共享地址空间和数据资源</u>,这些能力正是多进程无法做到的(地址空间不同))
  2. 更加轻量级。比起进程,更加容易(快速)创建和销毁(在一些系统中,比进程创建快10-100倍
  3. 性能表现更好。当有大量计算和I/O处理时,线程有能力让这些活动交叠,提升程序的速度
  4. 对多核处理器更有用。

【注】
由于进程是资源的拥有者,所以在创建、撤销、切换操作中需要较大的时空开销,限制了并发程度的进一步提高。

减少进程切换的开销,把进程作为资源分配单位调度单位这两个属性<u>分开处理</u>,即进程还是作为资源分配的基本单位,但是不作为调度的基本单位(很少调度或切换),把调度执行与切换的责任交给“线程”

这样做的好处不但可以提高系统的并发度,还能适应新的对称多处理机(SMP)环境的运行,充分发挥其性能

3.1 线程的一些缺陷

线程虽然运行速度很快,但并不是十分完美的
主要是在安全性方面的问题:我们知道,进程内的各个线程之间是共享数据和地址空间的,如果其中一个线程出现了错误(比如错误改写了某个变量),其他线程也会跟着出现问题,导致最终整个进程的错误

因此,我们说现在对于进程和线程的使用也是分场合的,不是一味的追求线程

  • 高性能计算领域(如天气预报、水利、空气动力学等等),这一类需要追求高性能计算,同时程序并不容易出错,就适合使用线程
  • 而例如浏览器这种应用,由于浏览器页面的操作由用户执行,有时候会考量到数据安全,因此推荐使用进程,一个进程打开一个网页

3.2 线程的实现

3.2.1 用户空间实现


在用户空间建立线程库,提供一组管理线程的过程由

运行时系统【run-time system】来完成线程的管理工作

内核管理的还是进程,内核不知道线程的存在

线程切换不需要陷入内核

如Unix、Linux

切换速度快一进程只有一个线程运行在处理器上
调度算法可以有应用程序设定若一个进程的某个线程调用了阻塞的系统调用,那么该进程的所有线程也将会被阻塞,页面失效也会有同样的问题
用户级线程可以运行在任何操作系统,包括不支持线程操作系统

3.2.2 内核空间实现


内核管理所有的线程管理,创建,撤销与调度**,并向应用程序提供API

内核维护进程和线程上下文

线程的切换需要内核支持

以线程为基础进行调度

由内核调度,当有多个处理器时,一个进程的多个线程可以在多个处理器上同时执行由内核进行创建,撤销,调度,系统开销更大
一个进程的某个线程阻塞不会引起其他线程的阻塞,页面失效同理

3.3.3 混合实现


线程创建在——用户空间

线程调度在——内核空间

4. 进程和线程之间拥有资源的关系?

【进程】是资源分配的单位——————【线程】是CPU调度的单位

线程 又称为“轻量级进程”【lightweight processes】

它(同一进程的所有线程)共享进程的地址空间,同时还有自己特有的一些信息:


每个线程共享进程的信息如上图左侧所示

,每个线程也有自己专属的 <u>PC、寄存器、栈、状态信息</u>

(因为每个线程可能去调用不同的步骤,

因此线程之间都有各自的栈、PC、寄存器,这样防止执行时发生异常)

【注】

  • 进程内的多个线程是共存的
  • 相互将信息共享,甚至一个线程创建删除另一个线程都是可能的
  • 虽然进程之间有上下级关系,但线程间没有(所有线程是平等的

5. 参考资料

《现代操作系统》
《Operating Systems》
操作系统_清华大学(向勇、陈渝)

03-05 23:41