From 6930fc8738d9511d06623bc4df4167a0007d8a97 Mon Sep 17 00:00:00 2001 From: Didnelpsun <2675350965@qq.com> Date: Sun, 23 Oct 2022 22:48:55 +0800 Subject: [PATCH] Update 1-process-management.md --- Operate-System/1-process-management.md | 40 ++++++++++++-------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/Operate-System/1-process-management.md b/Operate-System/1-process-management.md index 0247457..0022f6d 100644 --- a/Operate-System/1-process-management.md +++ b/Operate-System/1-process-management.md @@ -735,13 +735,13 @@ remainder section;// ⑧ + 若$P_1$先上处理机运行,则会一直卡在⑤,无法使用临界资源。 + 直到$P_1$的时间片用完,发生调度,切换$P_0$上处理机运行。 + 而代码①不会卡住$P_0$,$P_0$可以正常访问临界区,在$P_0$访问临界区期间即时切换回$P_1$,$P_1$依然会卡在⑤。 -+ 只有$P_0$在退出区将`turn`改为1后,$P_1$才能进入临界区。 ++ 只有$P_0$在退出区将`turn`改为$1$后,$P_1$才能进入临界区。 + 因此,该算法可以实现同一时刻最多只允许一个进程访问临界。 缺点: + `turn`表示当前允许进入临界区的进程号,而只有当前允许进入临界区的进程在访问了临界区之后,才会修改`turn`的值。 -+ 也就是说,对于临界区的访问,一定是按$P_0\rightarrow P1\rightarrow P0\rightarrow P1\rightarrow\cdots$这样轮流访问。 ++ 也就是说,对于临界区的访问,一定是按$P_0\rightarrow P_1\rightarrow P_0\rightarrow P_1\rightarrow\cdots$这样轮流访问。 + 如果一个进程一直不访问临界区,那么临界资源会被这个进程一直占用。 + 违背了空闲让进的原则。 @@ -1183,7 +1183,7 @@ $PV$操作题目分析步骤: 3. 设置信号量。设置需要的信号量,并根据题目条件确定信号量初值。 4. 互斥信号量初值一般为$1$,同步信号量的初始值要看对应资源的初始值是多少。 -#### 生产者消费者问题 +#### 单生产者单消费者多资源问题 + 系统中有一组生产者进程和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区中取出一个产品并使用。(这里的“产品”理解为某种数据) + 生产者、消费者共享一个初始为空、大小为$n$的缓冲区。 @@ -1245,9 +1245,9 @@ consumer() { + 生产者消费者问题是一个互斥、同步的综合问题。 + 对于初学者来说最难的是发现题目中隐含的两对同步关系。 -+ 有时候是消费者需要等待生产者生产,有时候是生产者要等待消费者消费,这是两个不同的“一前一后问题”,因此也需要设置两个同步信号量。前生产者$V$后消费者$P$的关系就是`full`,前消费者$V$后生产者者$P$的关系就是`empty`。 ++ 有时候是消费者需要等待生产者生产,有时候是生产者要等待消费者消费,这是两个不同的“一前一后问题”,因此也需要设置两个同步信号量。前生产者$V$后消费者$P$的关系就是`full`,前消费者$V$后生产者$P$的关系就是`empty`。 -#### 多生产者多消费者问题 +#### 多生产者多消费者指定单资源问题 桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。用$PV$操作实现上述过程。 @@ -1322,11 +1322,12 @@ son(){ } ``` -`P(plate/apple/orange)`和`V(plate/apple/orange)`实现了同步,而`P(mutex)`和`V(mutex)`实现互斥。 +`P(plate/apple/orange)`和`V(plate/apple/orange)`实现了同步使用盘子/苹果/橘子,而`P(mutex)`和`V(mutex)`实现互斥使用盘子。 如果不使用互斥量会怎么样? -+ 刚开始,儿子、女儿进程即使上处理机运行也会被阻塞($apple$和$orange$刚开始都是$0$,所以被阻塞)。如果刚开始是父亲进程先上处理机运行,则父亲`P(plate)`,可以访问盘子→母亲`P(plate)`,阻塞等待盘子→父亲放入苹果`V(apple)`→女儿进程被唤醒,其他进程即使运行也都会阻塞,暂时不可能访问临界资源(盘子)→女儿`P(apple)`,访问盘子,`V(plate)`,等待盘子的母亲进程被唤醒→母亲进程访问盘子(其他进程暂时都无法进入临界区)。 ++ 刚开始,儿子、女儿进程即使上处理机运行也会被阻塞($apple$和$orange$刚开始都是$0$,所以被阻塞)。 ++ 如果刚开始是父亲进程先上处理机运行,则父亲`P(plate)`,可以访问盘子→母亲`P(plate)`,阻塞等待盘子→父亲放入苹果`V(apple)`→女儿进程被唤醒,其他进程即使运行也都会阻塞,暂时不可能访问临界资源(盘子)→女儿`P(apple)`,访问盘子,`V(plate)`,等待盘子的母亲进程被唤醒→母亲进程访问盘子(其他进程暂时都无法进入临界区)→后续操作。 + 即使不设置专门的互斥信号量`mutex`,也不会出现多个进程同时访问盘子的现象。 + 原因在于本题中的缓冲区大小为`1`,在任何时刻,`apple`、`orange`、`plate`三个同步信号量中最多只有一个是$1$。因此在任何时刻,最多只有一个进程的$P$操作不会被阻塞,并顺利地进入临界区,此时互斥关系全部变成同步关系。 + 而如果缓冲区大于$1$,则父母两个可以同时访问临界区,可能导致数据覆盖,所以必须使用互斥信号量。 @@ -1337,8 +1338,8 @@ son(){ + 比如,如果从单个进程行为的角度来考虑的话,我们会有以下结论: + 如果盘子里装有苹果,那么一定要女儿取走苹果后父亲或母亲才能再放入水果,如果盘子里装有橘子,那么一定要儿子取走橘子后父亲或母亲才能再放入水果。 + 这么看是否就意味着要设置四个同步信号量分别实现这四个“一前一后”的关系了? -+ 正确的分析方法应该从“事件”的角度来考虑,我们可以把上述四对“进程行为的前后关系”抽象为一对“事件的前后关系”。 -+ 盘子变空事件→放入水果事件。“盘子变空事件”既可由儿子引发,也可由女儿引发;“放水果事件"既可能是父亲执行,也可能是母亲执行。这样的话,就可以用一个同步信号量解决问题了。 ++ 正确的分析方法应该从“事件”的角度来考虑,我们可以把上述四对“进程行为的前后关系”抽象为一对“事件的前后关系”。将苹果和橘子都归为水果,而互斥的是盘子而不是不同的水果,同步的是先盘子再水果。 ++ 盘子变空事件→放入水果事件。“盘子变空事件”既可由儿子引发,也可由女儿引发;“放水果事件"既可能是父亲执行,也可能是母亲执行。这样的话,就可以用一个同步信号量解决问题了。 #### 读者写者问题 @@ -1349,17 +1350,14 @@ son(){ 3. 任一写者在完成写操作之前不允许其他读者或写者工作写。 4. 写者执行写操作前,应让已有的读者和写者全部退出。 -具有两类进程:写进程、读进程。 +关系分析: -互斥关系:写进程-写进程、写进程-读进程。读进程与读进程不存在互斥问题。 - -写者进程和任何进程都互斥,设置一个互斥信号量`rw`,在写者访问共享文件前后分别执行$P$、$V$操作。 - -读者进程和写者进程也要互斥,因此读者访问共享文件前后也要对`rw`执行$P$、$V$操作。 - -如果所有读者进程在访问共享文件之前都执行$P(rw)$操作,那么会导致各个读进程之间也无法同时访问文件。所以读者写者问题的核心思想――怎么处理该读者共享的问题呢?即读同步。 - -`P(rw)`和`V(rw)`其实就是对共享文件的“加锁”和“解锁”。既然各个读进程需要同时访问,而读进程与写进程又必须互斥访问,那么我们可以让第一个访问文件的读进程“加锁”,让最后一个访问完文件的读进程“解锁”。可以设置一个整数变量`count`来记录当前有几个读进程在访问文件,这个也需要保持读进程互斥,避免多个读进程同时操作导致计数错误。 ++ 具有两类进程:写进程、读进程。 ++ 互斥关系:写进程-写进程、写进程-读进程。 + + 读进程与读进程不存在互斥问题。写者进程和任何进程都互斥,设置一个互斥信号量`rw`,在写者访问共享文件前后分别执行$P$、$V$操作。 + + 读者进程和写者进程也要互斥,因此读者访问共享文件前后也要对`rw`执行$P$、$V$操作。 ++ 如果所有读者进程在访问共享文件之前都执行$P(rw)$操作,那么会导致各个读进程之间也无法同时访问文件。所以读者写者问题的核心思想――怎么处理该读者共享的问题呢?即读同步。 ++ `P(rw)`和`V(rw)`其实就是对共享文件的“加锁”和“解锁”。既然各个读进程需要同时访问,而读进程与写进程又必须互斥访问,那么我们可以让第一个访问文件的读进程“加锁”,让最后一个访问完文件的读进程“解锁”。可以设置一个整数变量`count`来记录当前有几个读进程在访问文件,这个也需要保持读进程互斥,避免多个读进程同时操作导致计数错误。 ```cpp // 用于实现对文件的互斥访问。表示当前是否有进程在访问共享文件,1代表空闲 @@ -1451,7 +1449,7 @@ reader() { + 最后,还要认真体会我们是如何解决“写进程饥饿”问题的。 + 绝大多数的考研$PV$操作大题都可以用之前介绍的几种生产者消费者问题的思想来解决,如果遇到更复杂的问题,可以想想能否用读者写者问题的这几个思想来解决。 -#### 哲学家进餐问题 +#### 资源抢占问题 一张圆桌上坐着$5$名哲学家,每两个哲学家之间的桌上摆一根筷子,桌子的中间是一碗米饭。哲学家们倾注毕生的精力用于思考和进餐,哲学家在思考时,并不影响他人。只有当哲学家饥饿时,才试图拿起左、右两根筷子(一根一根地拿起)。如果筷子已在他人手上,则需等待。饥饿的哲学家只有同时拿起两根筷子才可以开始进餐,当进餐完毕后,放下筷子继续思考。 @@ -1492,7 +1490,7 @@ Pi() { + 这些进程之间只存在互斥关系,但是与之前接触到的互斥关系不同的是,每个进程都需要同时持有两个临界资源,因此就有“死锁”问题的隐患。 + 如果在考试中遇到了一个进程需要同时持有多个临界资源的情况,应该参考哲学家问题的思想,分析题中给出的进程之间是否会发生循环等待,是否会发生死锁。 -#### 抽烟者问题 +#### 单生产者多消费者单指定资源问题 假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停地卷烟并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要有三种材料:烟草、纸和胶水。三个抽烟者中,第一个拥有烟草、第二个拥有纸、第三个拥有胶水。供应者进程无限地提供三种材料,供应者每次将两种材料放桌子上,拥有剩下那种材料的抽烟者卷一根烟并抽掉它,并给供应者进程一个信号告诉完成了,供应者就会放另外两种材料再桌上,这个过程一直重复(让三个抽烟者轮流地抽烟)。