共计 2655 个字符,预计需要花费 7 分钟才能阅读完成。
1. 程序和过程的区别
首先来看一个故事:
A 平时因为工作忙,都是在公司食堂吃或者吃外卖。然而忽然有一天上班忽然灵机一动想本人做饭,于是 A 来到超市购物,他买了一些食材筹备做一份西红柿炒鸡蛋。回到家后,A 拿了出放在书架最深处的一本《家常菜食谱大全》,照着下面的办法,他就开始筹备做菜了:首先先把西红柿洗洁净切块,鸡蛋搅拌成蛋液,开锅热油 …….. 终于在 A 的不屑致力之下,一份色香味俱全的西红柿炒鸡蛋就实现了。
在上述故事中,咱们能够形象出一个简略的计算解决模型:
【程序 】就是那本食谱(存储在书架上,一种 物理 存在,用特定的形容模式论述做菜的过程和办法)
注:
驰名计算机科学家 Niklaus Wirth 提出了:程序 = 数据结构 + 算法
将食谱看成程序,它就是用图文并茂地模式(数据结构)活泼地向读者展现各个菜的做法(算法)- 【过程 】就是做菜的这一系列流动( 动静 进行的),包含了洗菜、切菜、炒菜等等
- 【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)
从上图中,咱们能够很分明地看到三种状态之间的转化过程:
- 当产生 IO 操作时,以后过程就会被阻塞直到 IO 操作实现
- 当调度器中断以后过程转而执行另一过程,原过程就会处于就绪状态
- 当调度器抉择该过程,便会从就绪态转为运行态,享受 CPU 资源
- 当 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. 为什么要引入线程的概念?
既然咱们曾经有了过程,那么为什么计算机科学家还要搞出一个线程的概念呢?
- 在零碎中多利用将同时进行,常常会一直切换状态,通过将一个过程切分成多个线程,达到 准并行【quasi-parallel】,程序模型将更简略(这些线程 <u> 共享地址空间和数据资源 </u>,这些能力正是多过程无奈做到的(地址空间不同))
- 更加轻量级。比起过程,更加容易(疾速)创立和销毁(在一些零碎中,比过程创立快 10-100 倍)
- 性能体现更好。当有大量计算和 I / O 解决时,线程有能力让这些流动交叠,晋升程序的速度
- 对多核处理器更有用。
【注】
因为 过程 是资源的拥有者,所以在创立、撤销、切换操作中须要较大的时空开销,限度了并发水平的进一步提高。
为 缩小过程切换的开销 ,把过程作为 资源分配单位 和调度单位 这两个属性 <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》
操作系统_清华大学(向勇、陈渝)