学习笔记:计算机组成原理Ch10.多进程
先说一下进程的概念:process就是一个程序分离出来的运行步骤,这里要重点说明的是进程的有序性
那如果这个进程运行了一半,另外程序的进程想运行呢?
这就是interrupt,在之前有讲过,就是A存档,B运行,B存档,A读档
这里的读档存档,我们称为转交状态。
下面介绍threads:
在program里,分享Memory的轻量化的(lightweight)进程,称为线程。
主要概念介绍完,我们先来看一个程序:

这是一个记录雨量的系统,放一个桶,当桶里的满了之后,触发操作,v+1,并且把水倒掉
右边是一个打电话的操作,当打电话后,得知此时的v,并且把v写成0
很明显,这两个函数分享了同一个变量v
那么有意思的事情就来了:

如上的时间轴,虽然桶已经集满,并且马上要改写v时,电话来了,此时计数就是错误的,这就是进程管理出现了问题,如何解决这样的问题呢?
我们称这样的情况是Critical Section:
试想下面的场景,两个道路都有车要来,那么应该怎么设置红绿灯使得车有序通过呢?

第一种方法:
Boolean Reservation
设置一个布尔数free,有人通过,此时的free为false,反之则为true。
这是一种相当笨的方法,那么如果出现两个车一同来呢?
第二种方法:
Turn Indicator
设置两个布尔数,pturn,qturn
你一辆我一辆的通行
这样就会出现一个问题,如果两条路的车辆数不同呢?
就会出现Deadlock
第三种方法:
Double Reservation
设置布尔数,pneed、qneed,就像新式人行道红绿灯一样,要过马路先按一下,红绿灯知道你有过马路的需求了,才会开放让你通行
这个方法的问题是,两边都同时按下按钮,该怎么办?
于是综合以上问题,出现了Decker Algorithm:
通俗来讲,就是把第二种和第三种方法融合了,如果两边都有需求,就先验证一下是谁的turn

但是如上图所示,每一次看需求之后,都要执行一次while看是谁的turn,这大大的消耗了cpu的运算时间,所以大部分情况不予采用。
上面说的是在软件层面解决,下面我们看看在硬件层面怎么解决:
首先,如果只有一个处理器存在的化,非常简单,只需要设置一个程序区域,在区域内不能interrupt就可以。
之后,如果有很多不同的处理器呢?一般采用,Test & Set bit
和上文的Free一样,设置一个free布尔数,当有人看时,这个变成false,防止其他人访问
在这里我们介绍了Free,其实还有更高阶的方法,也就是Semaphore:
他的结构如下图所示:

这个代码内嵌到了操作系统里,也就是每个程序运行时,都要运行上面的代码:
先wait(),看看此时的s是不是小于0,如果小于零,他就一直do{},等等
如果大于0了,他就运行一下,让s-1,指的是,有一个人正在操作了
运行完了,再加回来1
这是一个非常聪明的设想
假设家里有十个光盘机,每个都要刻录光盘,就会出现如下情况:

每个光盘机被启用后,就会使得writers -1
使用完了,再加回来
这实现了线程的管理,同样的道理,他也能实现同步:

两个程序,有一个程序运行的太快了,就先运行到了synch,发现是0,得等待另外一个程序把synch变成1,再继续运行;
我们发现,再wait()函数中,do while语句是空缺,实际上还可以干点事情:

比如把这个进程加入等待名单呀。
说到等待名单,就要看看process的三种state了:
我们可以把进程排队买菜
分别是
pending:我在排着队,队伍非常顺利的在走
active:我和菜店老板在交涉买菜的事情
blocked:菜地老板出去上厕所去了,留我在等待

同样的,既然wait里面可以加,signal就可以把人从等待名单里拿出来:

所以进程管理就讲完了,我们再回头看,之前提到了一个名词,Deadlock,这是什么意思呢?
想到了一个很好的比方:
程序员实习都要有实习经验才能入职,那只有参加程序员实习才能获得实习经验
这就是一个死局(deadlock)
我们可以用表格来表示:
两个进程都需要两种资源:

当然合理的分配资源呢,就能双方都到达100%
如果进入了图中红色的区域,且双方都不让资源,就发生了死局Deadlock
这个区域就叫做:deadlock zone
这个区域是怎么画出来的呢,我们下面介绍Banker Algorithm:
先从P1来看,P1有了资源R1之后,P2就无法运行,P2有了R3资源之后,P3就无法运行,P3有了R2资源之后,P1就无法运行,这就构成了一个闭环,这三个家伙之间就可以连成Deadlock Zone:

好,那如何避免出现Deadlock,有那么几种方法:
第一种方法:
一个人一个人的走:

第二种方法:
一个资源一个资源的走

第三种方法:
通过banker algorithm,算出来deadlock zone,避开走:

那如果走进了这个区域,该如何改正呢?
这就要提到备份了,在进程分配资源之前备份好进程的状态
遇到Deadlock之后用Banker Algorithm算出来,到底是哪条资源出现了问题,
然后恢复到之前备份好的状态,避免再进入那个区域就可以。