进程的状态、转换、控制:

先引入一个原语概念,这个在书上是一小句话

进程控制用的程序是原语,运行在内核态上,通过关、开中断两条特权指令实现屏蔽中断

以此来实现“一气呵成”的运行状态

原语的执行是必须一次性完成的,否则就会导致较为严重的错误

且开、关中断也必须是特权指令,否则用户态可以调用那么随便用一下就可以把系统干崩

更多是为了安全性考虑


然后再来谈进程的控制、转换

这里把进程的控制一起拿过来讲,其实就是因为进程的控制和状态的转换一一对应

进程的控制需要实现的就是各状态之间的切换,书上还有更详细的介绍

此外说下,实际上统考那么多年,总体的题目也是围绕状态转变在出题的,要详细知道

对于各个状态之间的转变需要很熟悉,同时也要对引发转变的事件有一定的积累

书上对这一批的事件实际上描述的非常之多,在41、42、43页均分别有一定的篇章

所以,抓住重点看


先来说创建态:

这里就不再赘述书上已经有的东西了,稍微提几个复习要点

申请空白PCB失败以后并不是意味着这个进程就被删除、取消创建,而是陷入Unused状态

后续如果有机会依旧会调用fork函数重新实现创建进程

注,PCB是存在于内存中的,所以一般调用失败就是内存已经满了

分配资源也是有可能失败的,失败了就进入创建态,等待后续有机会了再分配

引起创建的事情这里仅列举了部分,应该是会有一些共性的,可以总结下


再说终止态:

就是稍微提一句这个子进程,其实有些情况子进程还是不完全杀掉的,这个注意下即可

主要还是看后面引起终止的事件里面

正常结束是一个主动性的请求终止,这个书上并没有写,但是要补充到

第二个异常就是一般所说的异常,尤其是特指操作系统已经没办法处理的严重异常

只能杀掉

第三个也要和中断区分开,这个是杀,而不是中断,是直接给你杀了


再说阻塞和唤醒:

阻塞态是指代,当前因为缺失除CPU资源外的一些资源,就算CPU空闲下来也不能处理你

必须要等到这个资源已经得到了,然后再让CPU处理

阻塞是一个主动性行为,只有运行的进程才会主动使自己变成阻塞态,休眠态

主要就是要注意需要保存其PCB信息,同时最终是一定要去唤醒的

这个应该能和就绪态区分吧?如果有一个因为时间线满了导致下台那么肯定不是阻塞态

阻塞态,特指因为除CPU资源外缺失导致的陷入,就像开了QQ结果不输密码一样

阻塞了也是要唤醒的,如果一直没有唤醒那么就是一直休眠,约等于占用内存不干活

有待勘误:

其实后面还是值得说道一个的,挂起和阻塞并不是一个同样的概念

阻塞是进程/线程等待一个资源/事件的状态,是主动的,缺失资源导致的

而挂起实际上是因为这个进程、线程暂时不用或者说很久不用了,即使可以用也暂时放弃

其可能拥有一切可以运行的资源甚至包括CPU资源机会,但其被CPU暂时放弃了分配

操作系统本就在电脑中,所以没必要完全隔离开专业课知识和一般的电脑知识


运行态转就绪态也是一个被迫的事情,往往是因为时间片已经用完了,或者被挤下去了

就绪态转运行态一般就是被选中了放到CPU运行,简单来说就是你被选中了


原语的干活应该不太可能会考察,但多少还是要清楚原语在干什么

否则到时候一考这个事件内包含哪些动作,直接五分暴毙


这个一般不会怎么考,但还是说下吧,书上只有一小段,不太重要

一种是分为多个队列,根据状态的不同分为多个队列,阻塞也可以用阻塞的原因分队列

索引表也类似,也可以根据不同的状态分索引表,书上也有


进程通信:

要注意通信模式都是由操作系统提供的,进程之间无法直接通信

因为各自的内存单元都是隔开的,所以必须需要操作系统来提供一系列的“支持”

共享存储时,操作系统需要提供存储空间和互斥的工具,具体怎么互斥由用户去实现

所以其实共享存储也是需要操作系统支持的,毕竟需要依赖其提供工具和内存

其中可以细分高级、低级两种通信模式

消息传递,以前面的知识来说就是各个服务器之间的通信需要依赖于微内核提供方法

分为直接送信和间接送信模式,书上的例子还是很形象的

注意下这个方案的优点,因为毕竟是目前最广泛应用的进程通信机制

管道

这边其实是PPT上面总结的更加优秀,书上还有对这个功能的具体细化,这个不多说了

主要是要知道这个实际上也是一个文件而已,无非是不能“无限拓展”的文件


后面就是来讲进程、程序、线程这一系列概念:


程序与进程之间的关系:

执行一条命令或运行一个应用程序时 一对一

进程在执行过程中可以加在执行不同的程序 一对多(对“程序”并没有严格的定义

以不同的参数或数据多次执行同一个程序 多对一

并发地执行不同的应用程序 多对多


在教材、王道里面,基本可以把进程理解为一个正在干的事情

在CPU一个时间片里面大概率是干不完事情的,所以需要一个PCB去记录做到哪了

后面如果要再干的时候只需要把相应的现场都恢复,然后继续干下去就行了

进程其实并不只包括上述所说的PCB(即一个存在内存中的数据块,唯一标识)

还有其运行所占据的资源,包括数据段、代码段等,不能孤立看待

这一个的详细解释在课后习题27题有比较详细的解释


线程实际上是对进程的进一步细化、颗粒度降低的过程

例如一个进程对应干完第一件事,干完第二件事,干完第三件事,可以分为多个事件看

把刀磨一下,把猪带过来,就可以是不冲突的两件事,放在一个进程

那么每个事情在不冲突的情况下就完全可以并发运行为多个不同的线程

其实进程在做的也是这样一件事,在更大的宏观尺度上完成一些不同的事就是不同进程

例如一天可以分为,杀猪、吃饭、睡觉,每个对应一个进程,每个进程又可以进一步细分

杀猪就已经举例在上面了,每一个细分的进程就是一个线程

引出线程的目的最主要就是提高并行性,同时不需要再度分配资源,减少切换成本

线程可以共享一个进程中的资源,相互的切换几乎不需要任何成本

而一旦是进程之间相互切换,这个成本就很高,需要重新分配内存、保存断点、现场等

降低了颗粒度的同时,也降低了切换进程的概率,因为最终变成了以进程为调度的单位

从一大堆里面选出不同进程的线程,例如A有500个线程,B有100个线程

那么切换的概率实际上就只有1/6而已,而原先切换进程的概率在50%,是概率问题

线程切换如果还需要给其分配资源那么就等于没有分线程,资源分配是进程的事


此外补充下,进程映像实际上指代的就是某一时刻的进程切片,是一个静态的“状态”

进程本身是动态的,一直在向前推进的,但肯定不是连续的,受时间片的切分影响

另外说下“异步性”,这个在前后面会学习

操作系统要解决的就是这个问题,就是保证每次运行的结果都是一样的


线程的特点、优点、比较,以及和进程相互对应的结构部分就不说了,书上可以对比着看

其实就是对应书上的45-46页,这一块并没有太细看,细节还是有一些的


重点说下线程实现方式和线程模型:

多用户线程对应一个内核进程,也被称为用户级线程

这个是非常古老的过去还不支持真正的线程并发的时代的产物,现在基本被淘汰

实际上依旧是一个进程为单位的运行状态

在内核看来只会是一个进程,在用户看来是多个线程,是被线程库给搞出来的多个

其缺点也很明显,就是因为其本质上是一个进程,所以只能分配一个核的资源

那么一个进程对应的多个用户线程一旦有一个被阻塞,那么全都被阻塞,只能干等着

优点书上有写,但个人觉得本质上还是要了解其构造

内核级线程、组合线程:

这里开始就真正进入“线程并发”的时代,真正以线程为调度单位,由内核完成调度

一个进程的线程阻塞了,那么可以切换到这个程序的别的线程运行,也可以切换到别的进程的线程运行

然后再是对组合线程的进一步细分:

多对一:

多个用户级线程对应一个内核线程,这个就退化成古老的用户级线程了

一对一:

一个用户线程对应一个内核线程,也就是可以完全实现线程调度的状态

这个的缺点很明显,因为一个进程可能会产生一大堆的内核线程,导致资源占用巨大

同时因为内核进程需要陷入核心态运行,所以也会导致大量的资源开销在切换态上

并且切换线程的时候需要从用户态到核心态的切换,即使是同一个进程内

简单来说就是内核进程需要得到内核的支持才能运行,所以才需要频繁切换

多对多:

在第二种模式上的改版,尽可能减少了上面的缺点情况,还保留了优点


注:

对于某个核心线程而言其最多只能分到一个核的资源

有些核也支持多内核线程,但那种多线程并不是真正的多线程,本质还是抢资源模式

相对应的,一个内核线程对应的多个线程最多也就只能被分到那么一个核的资源

同时还需提下的,就是一个进程至少会有一个线程的存在

补充:

同一线程间的通信几乎不需要OS的支撑

定义:一组进程,如果它们单独不能正常进行,但并发可以进行,称这种现象为进程合作