【操作系统】 - 进程管理 - 4

本文深入探讨了进程间通信(IPC)的基本概念,包括进程间通信的必要性和常见方式,如信号量、消息传递和管道通信。同时,文章详细解析了进程互斥和同步问题,介绍了基于信号量的解决方案,以及经典IPC问题如生产者-消费者问题、哲学家就餐问题和读写者问题的解决思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【操作系统】 - 进程管理 - 4


1 进程间通信与同步

2 经典的ipc问题

3 进程调度


2.3 进程间通信与同步

进程间通信(InterProcess Communication IPC): 进程之间的信息交流与协调。

并发进程之间的两种关系

  1. 相互独立:进程之间没有任何关联关系(直接的或间接的), 仅有cpu

竞争关系。无需通信,由进程调度器来协调

  1. 相互关联:进程之间存在着某种关联关系(直接或间接),需要相互通信。

例如:共享内存变量/共享软硬件资源/数据传递/协调工作等

 

需要考虑的问题:

  1. 进程间如何通信呢,如何来相互传递信息呢?
  2. 当两个或多个进程在访问共享资源时,如何确保它们不会相互妨碍—

进程互斥问题;

  1. 当进程之间存在着某种依存关系时,如何来调整它们运行的先后顺序 – 进程同步问题
  2. 生活中的例子:教室座位/打饭窗口/一组同学做大作业

 

 

进程间通信方式

低级通信:只能传递状态和整数值(控制信息)

  • 信号量
  • 信号

高级通信:能够传递任意数量的数据

  • 共享内存
  • 消息传递
  • 管道

 

共享内存:

绝大多数现代的操作系统都提高了相应的方法,来让各个进程共享它们地址空间当中的某些部分,即共享内存。在共享内存中,可以任意读写和使用任意的数据结构

一组进程向共享内存中写,另一组进程从共享内存中读,通过这种方式实现两组

进程间的信息交换。

消息传递

消息:由若干数据位组成。

消息传递:进程之间通过发送和接收消息来交换信息

消息机制由操作系统来维护,包括定义寻址方式,认证协议,消息的大小等。一般提供两个操作:

  • Send() 发送一条消息
  • Receive () 接收一条消息

如果两个进程P和Q想要进行通信,它们需要

  • 在两者之间建立一个通信链路
  • 使用Send()和Receive()交换信息

管道

管道通信由unix首创,由于其有效性,后来的一些系统相继引入了管道技术

管道通信以文件系统为基础,所谓管道即连接两个进程之间的一个打开的共享

文件,专用于进程之间的数据通信;

发送进程从管道的一端写入数据流,接收进程从管道的另一端按先进先出的顺序读出数据流

管道的读写操作即为文件操作fwrite / fread, 数据流的长度和格式没有限制

 

2.3.2 进程的互斥

进程互斥的产生原因:

进程宏观上并发执行,依靠时钟中断来实现微观上轮流执行;

访问共享资源

两个

两个或多个进程对同一共享数据同时进行读写操作,而最后的结果是不可预测的,它取决于各个进程具体运行情况。

在同一时刻,只允许一个进程访问该共享数据,即如果当前已有一个进程正在使用该数据

那么,其他进程暂时不能访问。这就是互斥的概念。

 

竞争状态问题的抽象描述

把一个进程在运行过程中所做的事情分为两类:

进程内部的计算或其他的一些事情,肯定不会导致竞争状态的出现;

对共享内存或共享文件的访问,可能会导致竞争状态的出现。我们把完成这类失去的那段程序称为“临界区”,把需要互斥访问的共享资源 称为“临界资源”

如果我们能设计出某种方法,使得任何两个进程都不会同时出现在临界区中,就可以避免竞争状态的出现。

 

实现互斥访问的四个条件

1 任何两个进程都不能同时进入临界区

2 不能事先假定cpu的个数和运行速度

3 当一个进程运行在它的临界区外面时,不能妨碍其他的进程进入临界区

4 任何一个进程进入临界区的要求应该在有限时间内得到满足。

 

2.3.3 基于关闭中断的互斥实现

当一个进程进入临界区后,关闭所有的中断;当它退出临界区时,再打开中断。

进程的切换是由中断引发的,关闭中断后,cpu不会被分配给其他进程,其他进程无法执行

操作系统内核经常使用这种方法来更新内部的数据结构(变量,链表等)

问题:

如果进程在临界区中执行大量的计算,结果会如何?忙等

这种方法能否用于用户进程?不适用

这种方法能否用在多cpu的系统中?不可以

 

2.3.4 基于繁忙等待的互斥实现

方法1. 加锁标志位

Lock的初始值为0,当一个进程想进入临界区时,先查看lock的值,若为1,说明已有进程在临界区内,只好循环等待。等它变成0,才可进入。每个进程的操作类似。例如,

图书馆借书。

缺点:可能出现针对lock的竞争状态问题。

 

方法2 强制轮流法

基本思想:每个进程严格的按照轮流的顺序来进入临界区。

优点:保证在任何时刻最多只有一个进程在临界区

缺点:违反了互斥访问四条件中的第三个条件。

方法3 Peterson方法:当一个进程想进入临界区时,先调用enter_region函数,判断

是否能安全进入,不能的话等待;当它从临界区退出后需要调用leave_region函数,

允许它进入临界区。两个函数的参数均为进程号。

Peterson算法解决了互斥访问的问题,而且克服了强制轮流法的缺点,可以完全

正常的工作。

 

TSL指令

加锁标志为的缺点在于可能出现针对共享变量lock的竞争状态。例如:

当进程0执行完循环判断语句后,被时钟中断打断,从而可能使多个进程

同时进入临界区。

能不能把查询lock变量与修改lock变量的这两个操作捆绑在一起,使它们不会被打断?这

就是硬件上的TSL(Test and Set Lock)指令

使用LOCK来作为加锁标志位,协调各个进程对共享资源的访问;

当LOCK为0时,任何进程均可使用TSL指令把它设置为非0,进而访问共享资源

当LOCK为非0时,循环等待;

在退出临界区时, 把LOCK设置为0

 

以上的各种方法,都是基于繁忙等待(busy waiting)

的策略,都可归纳为一种形式:当一个进程想要进入它的临界区时,首先检查一下是否允许它进入,若允许,就直接进入了;若不允许,就在那里循环的等待,一直等到运行

它进入

缺点:

  1. 浪费cpu时间
  2. 可能导致预料之外的结果(如:一个第优先级进程位于临界区中,这时有一个高优先级的进程也试图进入临界区)

一个低优先级的进程正在临界区中

另一个高优先级的进程就绪了

调度器把cpu分配给高优先级的进程

该进程也想进入临界区

高优先级进程将会循环等待,等待低优先级进程退出临界区

低优先级进程无法获得CPU,无法离开临界区

 

现有的进程互斥问题形式:两个或多个进程都想进入各自的临界区,但在任何时刻,只允许一个进程进入临界区

新的进程互斥问题形式:两个或多个进程都想进入各自的临界区,但在任何时刻,只允许N个进程同时进入临界区(N >= 1)

2.3.4 信号量

1965年由著名的荷兰计算机科学家Dijkstra提出,其基本思想是用一种新的变量类型来记录当前可用资源的数量。

有两种实现方式:

  1. semaphre的取值必须大于或等于0, 0表示当前已没有空闲资源,而正数表示当前空闲资源的数量
  2. semaphre的取值可正可负,负数的绝对值表示正在等待进入临界区的进程个数
  3. 信号量是由操作系统来维护的,用户进程只能通过初始化和两个标准原语】

(P, V原语)来访问。

初始化可指定一个非负整数,即空闲资源总数。

P, V原语包含有进程的阻塞和唤醒机制,因此在进程等待进入临界区时不会浪费cpu时间

P原语:P是荷兰语Proberen(测试)的首字母。申请一个空闲资源(把信号量减1),

若成功,则退出,若失败,则该进程被阻塞

V原语: V是荷兰语Verhogen(增加)的首字母。释放一个被占用的资源(把

信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之

 

2.3.5 进程的同步

进程间的同步是指多个进程中发生的事件存在某种时序关系,因此在各个进程之间

必须协同合作,互相配合,使各个进程按一定的速度执行,以完成某一项任务

同步: 合作

互斥: 竞争

只考虑基于信号量的同步问题

2.4 经典的ipc问题

1 生产者 – 消费者问题

2 哲学家就餐问题

3 读写者问题

用信号量来解决,主要问题:

如何选择信号量,如何安排P, V原语的顺序

 

1 生产者 – 消费者问题

问题描述:

两个进程(生产者和消费者)共享一个共有的,固定大小的缓冲区,生产者

不断地制造产品,并把它放入缓冲区,而消费者不断的把产品取出来,并使用它,要求这两个进程互相协调,正确的完成各自的工作

问题分析:

对于生产者进程:制造一个产品,当要送入缓冲区时,要检查缓冲区是否有空位,若是,才可将产品送入缓冲区,并在必要时通知消费者,否则等待

对于消费者进程:当它去取产品时,先要检查缓冲区中是否有产品可取,若有,则取走一个,并在必要时通知生产者,否则等待

这种相互等待,并通知信息就是典型的进程同步。

同时,缓冲区是一个临界资源,因此,各个进程在使用缓冲区的时候,还有一个互斥问题

 

哲学家就餐问题

1965年,由Dijkstra提出并解决,后来逐渐成为该领域的一个经典问题,或者说,是一块试金石,用来实验新的进程同步方法的优劣。

每个哲学家的动作只有两种:进餐和思考。当一个哲学家感到饥饿时,他试图去获取他左边和右边的两把叉子(一次取一把,顺序无关),然后才能开始进餐。吃完以后,他需要把两把叉子放回原处,然后继续思考

问题是:如何保证哲学家梦的动作有序进行?

 

  1. 必须有一个数据结构,来描述每个哲学家的当前状态
  2. 该数据结构是一个临界资源,各个哲学家对它的访问应该互斥的进行
  1. 进程互斥
  2. 3 一个哲学家吃饱后,可能要唤醒它的左邻右舍,两者之间存在着同步关系 – 进程同步

读写者问题

问题描述

在一个航空订票系统当中,有很多个竞争的进程想要访问(读,写)系统的数据库

访问规则是:在任何时候,可以允许多个进程同时来读,但如果有一个进程想要更新(写)

)该数据库,则其他的任何进程都不能访问,包括读者和写者,问题是:

怎样来编程实现读者和写者

问题分析:

任何时候“写者”最多只允许一个,而读者可以有多个

“读 – 写”是互斥的

“写 – 写”是互斥的

“读 – 读”是允许的

对于基于读者优先策略的方法,只要有一个读者处于活动状态,后来的读者都会被接纳。

如果读者源源不断的出现的话,那么写者就终止处于阻塞状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值