深入理解操作系统[4]:进程的并发执行

1. 几个关键词

原子操作: 是由一个或多个指令序列实现的函数或动作,其特点是不允许被打断,所有动作要么全做,要么全不做。

临界资源: 指打印机,磁带机,表格 。一次只允许一个进程使用的共享资源(互斥方式);
临界区: 指在每个进程中访问临界资源的程序代码(进程必须互斥的进入临界区)。
死锁: 多个进程的每个进程都在等待其他进程完成而不能继续执行。且互不相让已占用的资源。
活锁: 多个进程为响应其他进程种的变化而持续改变自己状态但不做有用的工作。
互斥: 一个进程在临界区访问共享资源时,其他进程不能进入临界区。
饥饿: 一个进程被无限期的忽略不被执行。


并发执行的问题
由于进程的相对执行速度不可预测,因而
  1. 全局资源的共享很危险。多个进程都对同一全局变量读写,后果时很麻烦的。
  2. 操作系统很难对资源进行最优分配。比如被占用I/O的进程被阻塞。
  3. 定位程序设计的错误很困难。因为结果的不确定性和不可再现性。


2. 进程的交互关系

  竞争(互斥)
    --进程间不知道对方的存在;
    --个进程的结果与另一个进程无关;
    --进程的执行时间可能受影响。
  通过共享合作(同步)
    --进程间间接知道对方的存在,比如共享对象;
    --一个进程的结果可能取决于从另一进程得来的信息;
    --进程的执行时间可能会受影响。
  通过通信合作(同步)
    --进程间直接知道对方的存在,比如通信原语。
    --一个进程的结果可能取决于从另一进程得来的信息;
    --进程的执行时间可能会受影响。


实施互斥的要求
  1. 强制互斥,一次只允许一个进程进入临界区;
  2. 非临界区进程不能干涉临界区进程;
  3. 不能发生死锁和饥饿;
  4. 任何有需要的进程可以立即进入空的临界区;
  5. 对相关进程的执行速度和处理器数量无要求;
  6. 驻留在临界区的进程要被限制时间。


实现互斥的方法
  1. 软件办法:让并发执行的进程承担责任,不需要程序设计语言或者操作系统来支持。
  2. 硬件支持的办法:如中断禁用,专用机器指令。
  3. 操作系统和程序设计语言级别的支持。


对临界资源的访问

在这里插入图片描述

同步机制

为实现进程互斥地进入自已的临界区,所有同步机制都应遵循下述四条准则:
1 空闲让进;
2 忙则等待;
3 有限等待;
4 让权等待(进程不能进入自己的临界区时释放处理器)。

3. 信号量

信号量是一种数据结构。信号量的值与相应资源的使用情况有关,仅由P(wait,申请) V(signal,释放)操作(原子操作)改变。
二元信号量是值只取0和1的信号量。
互斥量 类似二元信号量,区别在于加锁(置0)和解锁(置1)必须为一个进程完成。


基本原理
  多个进程通过信号进行合作,可以强迫一个进程在某个位置停止,直到它接收到一个特殊的信号。使用信号量执行semSignal(s)发送信号;使用semWait(s)接收信号;若相应的信号仍未发送,则阻塞进程直到发送完为止。


整型信号量,记录型信号量,AND型信号量

信号量-整型信号量

在这里插入图片描述

缺点:只要信号量S<=0 ,就不断的测试,不满足让权等待。


信号量-记录型信号量

  除了需要一个用于代表资源数目的整型变量 value 外,增加一个进程链表指针 L,用于链接所有等待进程。Value表示某类资源的数目 >=0时表示系统可用的资源数量,<0时其绝对值表示已经阻塞的进程数量。如果 S.value 的初值为 1,表示只允许一个进程访问临界资源,此时的信号量转化为互斥信号量,用于进程互斥。当 S.value<0 时,表示该类资源已分配完毕,因此进程应调用 block 原语,进行自我阻塞,放弃处理机,并插入到信号量链表S.L 中。可见,该机制遵循了“让权等待”准则。此时 S.value 的绝对值表示在该信号量链表中已阻塞进程的数目。

Wait和 Signal操作

在这里插入图片描述


信号量-AND型信号量

将进程在整个运行过程需要的所有资源,一次性全部分配给进程,待进程用完后一起释放。

在这里插入图片描述
在这里插入图片描述


信号量实现互斥

在这里插入图片描述

wait(mutex); 进入区
critical section 临界区
signal(mutex);退出区
remainder seetion 剩余区


生产者消费者问题

制约关系
1-不允许从空缓冲区中取;
2-不允许往满缓冲区中放。

定义

在这里插入图片描述

PV操作

在这里插入图片描述

在这里插入图片描述

P操作的顺序不能颠倒,先之行对资源信号量的P操作,在执行对互斥信号量的P操作,否则可能导致死锁。


4. 管程

管程是一种编程语言结构,封装了变量,访问过程和初始化代码。它提供的功能和信号量相同但是更易于控制。管程由一个或多个过程,一个初始化序列和局部数组构成。有以下特点:
  1. 局部数据变量只能被管程的过程访问,任何外部过程不能访问;
  2. 一个进程通过调用管程的一个过程进入管程;
  3. 只有一个进程在管程中执行,调用管程的任何其他进程都需等待管程可用时才能进入。


5. 消息传递

  为实施互斥,进程之间需要同步;为实现合作,进程之间需要交换信息。而通过消息传递方法实现信息交换可以在分布式系统,共享内存的多处理器系统和单处理器系统实现。


寻址的方式
 1. 直接寻址
  Send(Receiver,message) //发送一个消息给接收进程
  Receive(Sender,message)

 2. 间接寻址
  --私用信箱
    用户进程建立,作为该进程的一部分;
    拥有者由权读消息,其他用户只能发;
    单向通信链路;
    进程结束时信箱也消失;
  --公用信箱
    操作系统创建;
    提供给系统中所有;
    核准进程既可以发也可以收;
    双向链路;
    系统运行期间始终存在;
  --共享信箱
    某进程创建,创建时提供共享进程的名字;
    信箱的拥有者和共享者都有权读发送给自己的消息。


信箱通信时,发/收进程的关系
  1. 一对一:建立一条专用通信链路
  2. 多对一:C/S
  3. 一对多:广播
  4. 多对多:建立一种公用信箱,多个进程可以用


6. 读者-写者问题

存在一个多进程共享的数据区,有些进程只从中读取数据,有些进程只往其中写数据。且:
  1. 任意读进程可同时访问;
  2. 一次只有一个写进程可以写入;
  3. 如果一个写进程正在写,则禁止任何进程读。

.
.
.
.
.
.


桃花仙人种桃树,又摘桃花换酒钱_

参与评论 您还未登录,请先 登录 后发表或查看评论
1. 实验目 1) 加深对进程概念理解,明确进程和程序区别。 2) 进一步认识并发执行实质。 3) 分析进程争用资源现象,学习解决进程互斥方法。 4) 学习解决进程同步方法。 5) 了解Linux系统中进程通信基本原理。   进程操作系统中最重要概念,贯穿始终,也学习现代操作系统关键。通过本次实验,要求理解进程实质和进程管理机制。在Linux系统下实现进程从创建到终止全过程,从中体会进程创建过程、父进程和子进程之间关系、进程状态变化、进程之间互斥、同步机制、进程调度原理和以管道为代表进程通信方式实现。 2. 内容及要求:   这一个设计型实验,要求自行编制程序。   使用系统调用pipe()建立一条管道,两个子进程分别向管道写一句话:   Child process1 is sending a message!   Child process2 is sending a message!   父进程从管道读出来自两个子进程信息,显示在屏幕上。   要求: 1) 父进程先接收子进程1发来消息,然后再接收子进程2发来消息。 2) 实现管道互斥使用,当一个子进程正在对管道进行写操作时,另一子进程必须等待。使用系统调用lockf(fd[1],1,0)实现对管道加锁操作,用lockf(fd[1],0,0)解除对管道锁定。 3) 实现父子进程同步,当子进程把数据写入管道后,便去睡眠等待;当父进程试图从一空管道中读取数据时,也应等待,直到子进程将数据写入管道后,才将其唤醒。 3.相关系统调用 1) fork() 用于创一个子进程。 格式:int fork(); 返回值:在子进程中返回0;在父进程中返回所创建进程ID值;当返回-1时,创建失败。 2) wait() 常用来控制父进程与子进程同步。 在父进程中调用wait(),则父进程被阻塞,进入等待队列,等待子进程结束。当子进程结束时,父进程从wait()返回继续执行原来程序。 返回值:大于0时,为子进程ID值;等于-1时,调用失败。 3) exit() 进程结束时最常调用。 格式:void exit( int status); 其中,status为进程结束状态。 4) pipe() 用于创建一个管道 格式:pipe(int fd); 其中fd一个由两个数组元素fd[0]和fd[1]组成整型数组,fd[0]管道读端口,用于从管道读出数据,fd[1] 管道写端口,用于向管道写入数据。 返回值:0 调用成功;-1 调用失败。 5) sleep() 调用进程睡眠若干时间,之后唤醒。 格式:sleep(int t); 其中t为睡眠时间。 6) lockf() 用于对互斥资源加锁和解锁。在本实验中,该调用格式为: lockf(fd[1],1,0);/* 表示对管道写入端口加锁。 lockf(fd[1],0,0);/* 表示对管道写入端口解锁。 7) write(fd[1],String,Length) 将字符串String内容写入管道写入口。 8) read(fd[0],String,Length) 从管道读入口读出信息放入字符串String中。 4.程序流程 父进程: 1) 创建管道; 2) 创建子进程1; 3) 创建子进程2; 4) 等待从管道中读出子进程1写入数据,并显示在屏幕上; 5) 等待从管道中读出子进程2写入数据,并显示在屏幕上; 6) 退出。 子进程: 1) 将管道写入口加锁; 2) 将信息“Child process n is sending message!”输入到变量OutPipe中,n=1,2; 3) 将OutPipe中信息写入管道; 4) 睡眠等待; 5) 将管道写入口解锁; 6) 退出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:创作都市 设计师:CSDN官方博客 返回首页

打赏作者

小龙狗

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值