操作系统(四)进程同步与互斥

进程间相互作用

在一个计算机系统中存在多个进程,这些进程直接可能存在着逻辑关系,可可能不存在逻辑关系,由于他们都要共享或竞争一个计算机系统中的资源,所以不可避免的会发生相互作用。

相关进程和无关进程

  • 相关进程:在逻辑上具有某种联系的进程。即一个进程的执行不影响其他进程的执行,且与其他进程的进展无关,即他们是各自独立的,则说这些并发进程的相互之间没有关系。显示无关进程一定没有共享变量。他们都在各自的数据集合上操作。
  • 无关进程:在逻辑上没有任何联系的进程。即一个进程的执行以来其他进程的进展情况,或者一个进程的执行可能会影响其他进程的执行,则说明这些并发进程是相关的。

时间有关的错误

一个进程由于自身或外界的原因而可能被中断,且断点是不固定的。

进程执行的进度是不能由进程自身控制的,对于相关进程来说,可能有若干并发进程同时共享资源,即一个进程一次使用未结束,另一进程也开始使用,形成交替使用共享资源。

与时间有关的错误:在并发程序中共享了公共变量,是的程序的计算与并发程序执行的速度有关。

如程序A 、B共享一个变量n,A每次对n进行+1操作,B每次打印n后将n设置为0,由于A、B都以各自独立的速度向前推进,所以会产生交叉运行。所以会参生三种情况

  • A 在B的打印操作和n=0之前
  • A 在B的打印操作之后,n=0之前
  • A 在B的打印操作和n=0之后

进程的同步与互斥

进程是操作系统中可以独立运行的单位,在同一个系统中,进程之间不可避免地会产生某种联系,如竞争资源,而有些进程本就是为完成同一个作业而运行的。因此,进程之间必须相互协调,彼此之间交互信息,这就是进程之间一种简单的通信。

进程的同步

在计算机系统中,为了完成某一工作,不同进程间可能需要相互协作。

例如:进程A读取文件内容存入缓冲器,进程B从缓存器中读取并计算。他们共享缓冲器。
若A的执行速度远超B的执行速度,可能会在B还未读取结束时,将文件覆盖掉,照成记录丢失。如果B的执行速度远超A的执行速度时,又不可避免对同一记录进行加工,所以两个进程必须协调动作节奏,彼此同步。

要实现进程同步就必须实现一种机制,该机制不仅能把其他进程需要的消息发送出去,也能测试进程自己需要的信息是否到达,这种能实现进程同步的机制称为同步机制。

不同同步机制中实现的方法是不同的。

进程的互斥

在系统中,许多进程常常需要共享资源,而这些资源往往要求排他性的使用,即只为一个进程服务,因此各个进程只能互斥使用这些资源,进程间的关系就是进程的互斥。如多个进程竞争使用打印机。

进程的互斥是进程间的一种间接制约关系。

临界区

若系统中的某些资源一次只允许一个进程使用,则这类资源称为临界资源或共享变量,而在进程中访问临界资源的程序称为临界区。

如有若干程序共享某一临界区,则该临界区称为相关临界区。当一个进程在相关临界区执行时,如果不让另一进程进入相关的临界区执行,就不会形成多个进程对共享变量进行交叉访问,就可以避免出现关于时间的错误。

为保证系统中各并发程序顺利运行,对两个以上进入相关临界区的进程,必须实行互斥。系统对相关临界区的调度使用原则如下:

  • 临界区为空时,有进程请求进入临界区,则允许进入(有效利用临界资源)
  • 临界区中有一个进程时,其他要求进入临界区的进程必须等待(反应互斥的基本含义,即表示临界资源具有排他性)
  • 临界区为空时,如有多个线程同时要求进入,则只允许一个线程进入。(3是1、2的一个特殊情况)
  • 任一进程进入临界区的要求应在有限时间满足(避免进程发生忙等待)
  • 处于等待状态的进程应放弃占用处理器(避免进程发生死锁)

信号量及P、V操作

信号量

用常规的程序来实现进程之间同步、互斥关系需要复杂的算法,而且会兆成忙等待,浪费处理器资源,为此引入信号量的概念。

信号量:一种特殊的变量,表面形式是一个整型变量附加一个队列。而且只能被特殊操作使用(P、V操作,二者都是原语)。是由进程互斥的关键含义抽象而来。信号量是被保护的量,只有P、V操作和信号量初始化操作才可访问和改变它的值。

P、V操作

P(S){
	S = S -1;
}
S<0时,该进程进入等待状态,然后将该进程的PCB插入响应的S信号量等待队列末尾,
知道有其他进程在S上执行V操作为止。

V(S){
	S = S +1;
}
S<=0时,释放S信号量队列中等待的一个进程,将其改为就绪状态,并将其插入就绪队列。

信号量与P、V操作的物理含义

P操作和V操作都是对信号量S进行的。

信号量S表示某类可用的临界资源。

  • S>0时,S的大小表示可用临界资源的数目。
  • S<0时,表示没有可分配的资源,S的绝对值为排在S信号量的等待队列进程中的数目

每进行一个P操作,表示请求的进程分配到了一个资源,每进行一次V操作,意味着进程释放了一个资源。

用P、V操作实现进程之间的互斥

假设进程A、B竞争进入临界区:

A:
P(S)
临界区操作
V(S)

B:
P(S)
临界区操作
V(S)

S的初始值为1

用P、V操作实现进程之间的同步

A:
把信息送入缓冲区;
V(S1)
P(S2)

B:

P(S1)
把信息从缓冲区取走;
V(S2)

S1、S2的初始值为0

信号量及P、V操作小结

P、V操作虽然在逻辑上完整,但也具有明显缺点:由于P、V操作每次只能进行加1或减1操作,当进程同时使用多个资源时,需进行多次P操作和V操作,这不仅增加了程序的复杂性,也降低了通信效率。致使进程之间需要相互等待很长的时间,甚至可能导致死锁的发生

P、V操作必须成对出现,当为互斥操作时,他们处于同一进程,处于同步操作时,处于不同进程。

经典的进程同步问题

简单生产者—消费者问题

  • 一个生产者进程 P
  • 一个缓冲区
  • 一个消费者进程Q

设置信号量empty,表示空缓冲区数量,初始值为1
设置信号量full,指示满缓冲区数量,初始值为0

同步解决方案:

P{
	P(empty)
	生产一个商品,送入缓冲区
	V(full)
}

Q{
	P(full)
	从缓冲区取出
	V(full)
	消费产品
}

多个生产者—消费者问题

有多个生成者进程P1、P2、P3、P4
有多个消费者进程S1、S2、S3、S4
缓冲池k有多个缓冲区构成的圆环组成。

同步问题:

  • 生产者不可往满了的缓冲区中存放商品,设置信号量empty,初始值为k,指示空闲缓冲区数量
  • 消费者不可从空的缓冲区取商品,设置信号量full,初始值为0,指示满缓冲区数量

互斥问题:

  • 设不能从空缓冲区区,亦不能向满缓冲区存,置信息量mutex,初始值为1,用于实现临界区(环形缓冲池)的互斥
P{
	生产商品
	P(empty)
	P(mutex)
	送入缓冲区
	V(mutex)
	V(full)
}

Q{
	P(full)
	P(mutex)
	从缓冲区取出产品
	V(empty)
	V(empty)
	消费产品
}

读者—写者问题

计算机系统中,一个数据对象是可供若干进程共享的。

问题描述:

  • 多个进程可同时读取文件F
  • 任何进程对文件进行写时,其他进程不可进行读或写
  • 有进程读文件时不允许其他进程去写

设值read_count(0)记录当前读者的个数,是一个共享变量。
设置信号量mutex(1),用于read_count互斥使用,再设置信号量write(1)用于写者之间互斥。

读者:
{
	// 互斥操作,同一时间只有一个进程可操作
	P(mutex)
		read_count = read_count + 1
		// 只有当前读者一人,可进行写操作
		if(read_count =1){
			p(write)
		}
	V(mutex)
	读文件
	P(mutex)
		read_count = read_count - 1
		if(read_count =1){
			v(write)
		}
	V(mutex)
}

写者
{
	P(write)
	写文件
	V(write)
}

管程

管程的提出

采用信号量即P、V同步机制来编写并发程序,对于共享变量及信号量变量的操作将被分散于各个进程中,缺点如下:

  • 程序易读性差
  • 程序不利于修改和维护
  • 正确性难以保证

为了更易于编写正确的程序,产生了另一种高级同步机制,即管程

管程的概念及组成

一个管程由过程、变量、数据结构组成的一个集合,他们组成一个特殊的模块。

进程可在任何需要的时候调用管程中的过程,但他们不能在管程之外声明的过程中直接访问管程内的数据结构。

管程由四部分组成:

  • 管程名称
  • 共享数据的说明
  • 对数据进行操作的一组过程
  • 共享数据赋初值的语句
    管程可保证共享程序的互斥允许,即任意时刻只能有一个进程在管程内活动。该性能由管程本身实现的。

管程的三个主要特性:

  • 模块化,一个管程是一个基本程序单位,可以单独编译。
  • 抽象数据类型,是一种特殊的数据类型,不仅包含数据,还包含对数据操作的代码
  • 信息隐蔽,外部无法得知管程内部功能的具体实现。管程内的共享变量在管程外是不可见的。

管程中的条件变量

条件变量:因为管程同时时间只可运行一个进程,所以需要一种办法来使其余进程被阻塞。

  • wait:会使调用进程自身堵塞,并将另一个等待在管程外的进程调入管程。
  • signal:可以唤醒正在睡眠的伙伴进程。
    条件变量不是计数器,不管是否成功(比如并没有等待进程),信号都会永久消失。

进程通信

一个进程在运行过程中,可能会需要与其他进程进行信息交互。因此需要引入新的通信原语,解决大量信息交换问题。

解决大量信息通信的三种方案:

  • 共享内存
  • 消息机制
  • 通过共享文件通信(管道通信)

不仅要保证相互制约的进程之间正确的关系,还要同时实现进程之间的信息交换。

共享内存

在相互通信的进程之间设置一个公共内存区,一组进程向该内存中写,另一组进程从公共内存中读,通过这种方式实现两组进程间的信息交换。

问题:

  • 怎样提供共享内存
  • 公共内存中的读写互斥问题

操作系统一般只提供要共享的内存空间,而处理进程间在公共内存的互斥关系有开发人员承担。

消息机制

消息机制是用于进程间通信的高级通信原语之一。至于具体的实现,是一种具体的消息传递机制。

消息缓冲通信

基本思想是:根据生产者-消费者原理,利用内存中公用消息缓冲区(临界区)实现进程间的信息交换。

消息缓冲机制包含下列内容:

  1. 消息缓冲区是一种数据结构
    • 消息长度
    • 消息正文
    • 发送者
    • 消息队列指针
  2. 消息队列首指针 m_q,一般存在PCB中
  3. 互斥信号量 m_mutex(1),用于互斥消息队列,在PCB中设置
  4. 同步信号量 m_syn(0),用于消息计数,在PCB中设置
  5. 发生消息原语send(receiver a)
  6. 接收消息原语receive(a)
信箱通信

为了实现进程间的通信,可设置一个信息机构:信箱,以发送信件以及接收回答信件为进程间通信的基本方式。

当一个进程希望与另一个进程通信时,就创建一个链接两个进程的信箱,发送进程把消息投入信箱,接收进程可以在任何时刻取走信件。

信箱由两部分组成

  • 信箱说明
    • 可存信件数
    • 已有信件数
    • 可存信件的指针
  • 信箱体

为实现信箱通信,必须提供响应的原语。如创建信箱原语,撤销信箱原语,发送信件原语,读取信件原语等

管道通信

所谓管道通信就是连接两个进程之间的一个打开的共享文件,专用于进程之间通信。(类似于消息队列)
发送进程源源不断地从管道一端写入数据,接收进程在需要时从管道另一端读取数据,每次写入或读取的数据信息长度是可变的。显然,管道通信的基础是文件系统

管道机制中的同步与互斥机制都是由操作系统自动进行,对用户是透明的。

管道痛惜具有传送数据量大的优点,但是通信速度较慢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值