进程同步

Linux下进程通信的八种方法:管道(pipe),命名管道(FIFO),内存映射(mapped memeory),消息队列(message queue),共享内存(shared memory),信号量(semaphore),信号(signal),套接字(Socket)


临界区是每个进程中访问临界资源的那段代码称,每次只准许一个进程进入临界区,进入后不允许其他进程进入。不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。它可以作为线程间通信方式而不能作为进程间通信方式,因为进程间内存是相互隔离的

临界区问题(线程同步)

  • 假设某个系统有n个进程。每个进程有一个代码段称为临界区
  • 在该区中,进程可能改变共同变量,更新一个表,写一个文件等
  • 当一个进程进入临界区,没有其他进程可被允许在临界区内执行
  • 每个进程必须请求允许进入其临界区,实现这一请求的代码段称为进入区
  • 临界区之后可有退出区
  • 其他代码称为剩余区
  • 在这里插入图片描述
  • 临界区问题的解答,必须满足以下三项要求:
  • 互斥:如果进程Pi 在其临界区内执行,那么其他进程都能不在其临界区内执行
  • 前进:?只能那些不在剩余区内执行的进程可参加选择
  • 有限等待:从一个进程做出进入临界区的请求,到该请求允许为止,其他进程允许进入其临界区的次数有上限

软件算法

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


即任何进程在进入临界区之前必须得到锁,离开时释放锁
在这里插入图片描述


信号量

  • 对信号量的修改必须不可分的执行,即当一个进程修改信号量时,不能有其他进程同时修改同一信号量的值

用法

  • 控制访问具有若干个实例的某种资源。该信号量初始化为可用资源的数量
  • 当每个进程需要使用资源时,对信号进行减计数
  • 当进程释放资源时,需要对该信号量执行加计数
  • 当信号量计数为0时,再需求该资源的进程就阻塞,直到计数大于0

缺点

  • 忙等待
  • 当进程位于其临界区内时,任何其他试图进入其临界区的进程都必须在其进入代码中连续的循环
  • 忙等待浪费了CPU的时钟,可本来可以为其他进程所使用
  • 这种类型的信号量也成为自旋锁
  • 为了克服忙等
  • 当一进程执行wait()操作时,发现信号量不为正,则它必须等待
  • 然而,该进程不是忙等,而是阻塞自己
  • 阻塞操作将一个进程放入到与信号量相关的等待队列中,并将该进程的状态切换成等待
  • 调度程序,以选择另一个进程来执行
  • 该进程的重新执行,通过wakeup()操作来进行
  • 该操作将进程从等待切换到就绪状态

  • 等待进程的链表可以利用进程控制块PCB中的一个连接域来加以轻松实现

经典同步问题

哲学家进餐问题

  • 描述:五个哲学家,五只筷子。
  • 解决方案:
  • 1.只有两双筷子都可用时,才允许拿起
  • 2.奇数先拿左侧筷子,偶数先拿右侧

管程

  • 定义:是由局部于自己的若干公共变量机器说明和所有访问这些公共变量的过程所组成的软件组成

引入管程的原因:

  • 信号量机制的缺点: 进程自备同步操作,大量分散在各个进程中,不易管理,易发生死锁
  • 管程特点: 封装了同步,对进程隐蔽了同步细节,简化了同步功能的调用界面
  • 目的:
  • 把分散在各进程中的临界区集中起来进行管理
  • 防止进程有意或无意的违法同步操作
  • 便于用高级语言来书写程序

  • 组成部分
  • 局部于管程的共享变量
  • 对数据结构进行操作的一组过程
  • 对局部于管程的数据进程初始化的语句
  • 管程的属性
  • 共享性:管程可悲系统范围内的进程互斥访问,属于共享资源
  • 安全性:管程的局部变量只能由管程的过程访问
  • 互斥性:多个进程对管程的访问是互斥的。任一时刻,管程中只能有一个活跃进程
  • 封装性:管程内的数据结构是私有的,只能在管程内使用,管程内的过程也只能使用管程内的数据结构

原子事务

意思,回退就是原子事务?
还是说,不能被中断的操作,是原子事物?

  • 执行单个逻辑功能的一组指令或操作称为事务
  • 由于被终止的事务可能已经改变了它所访问的数据,被终止的程序必须对其所修改的数据不产生任何影响,以便确保原子特性
  • 因此被中止的事务所访问的数据状态恢复到事务开始执行之前。

  • 基于日志的恢复
  • 先记日志后操作
  • 事务名称:执行写操作事务的唯一名字
  • 数据项名称:所写数据项的唯一名称
  • 旧值:
  • 新值:
  • 检查点
  • 由于基于日志的回溯需要检查全部的日志,耗时
  • 检查点就等于是,将日志的记录以检查点为界,切分开了
  • 回溯时,只需要回溯到对应检查点即可

Linux进程间通信方式

1.管道( pipe ):
  • 管道(通常指无名管道)是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2.有名管道 (named pipe(FIFO)) :
  • 有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
3.信号量( semophore ) :
  • 信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
4.消息队列( message queue ) :
  • 消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
5.共享内存( shared memory ) :
  • 共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。
6.套接字( socket ) :
  • 套解字也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同机器间的进程通信。
7.信号 ( sinal ) :
  • 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
8.内存映射

线程同步

1.临界区
2. 互斥量
3.信号量
4. 事件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验题目: 生产者与消费者(综合性实验) 实验环境: C语言编译器 实验内容: ① 由用户指定要产生的进程及其类别,存入进入就绪队列。    ② 调度程序从就绪队列中提取一个就绪进程运行。如果申请的资源被阻塞则进入相应的等待队列,调度程序调度就绪队列中的下一个进程进程运行结束时,会检查对应的等待队列,激活队列中的进程进入就绪队列。运行结束的进程进入over链表。重复这一过程直至就绪队列为空。    ③ 程序询问是否要继续?如果要转直①开始执行,否则退出程序。 实验目的: 通过实验模拟生产者与消费者之间的关系,了解并掌握他们之间的关系及其原理。由此增加对进程同步的问题的了解。 实验要求: 每个进程有一个进程控制块(PCB)表示。进程控制块可以包含如下信息:进程类型标号、进程系统号、进程状态、进程产品(字符)、进程链指针等等。 系统开辟了一个缓冲区,大小由buffersize指定。 程序中有三个链队列,一个链表。一个就绪队列(ready),两个等待队列:生产者等待队列(producer);消费者队列(consumer)。一个链表(over),用于收集已经运行结束的进程 本程序通过函数模拟信号量的操作。 参考书目: 1)徐甲同等编,计算机操作系统教程,西安电子科技大学出版社 2)Andrew S. Tanenbaum著,陈向群,马红兵译. 现代操作系统(第2版). 机械工业出版社 3)Abranham Silberschatz, Peter Baer Galvin, Greg Gagne著. 郑扣根译. 操作系统概念(第2版). 高等教育出版社 4)张尧学编著. 计算机操作系统教程(第2版)习题解答与实验指导. 清华大学出版社 实验报告要求: (1) 每位同学交一份电子版本的实验报告,上传到202.204.125.21服务器中。 (2) 文件名格式为班级、学号加上个人姓名,例如: 电子04-1-040824101**.doc   表示电子04-1班学号为040824101号的**同学的实验报告。 (3) 实验报告内容的开始处要列出实验的目的,实验环境、实验内容等的说明,报告中要附上程序代码,并对实验过程进行说明。 基本数据结构: PCB* readyhead=NULL, * readytail=NULL; // 就绪队列 PCB* consumerhead=NULL, * consumertail=NULL; // 消费者队列 PCB* producerhead=NULL, * producertail=NULL; // 生产者队列 over=(PCB*)malloc(sizeof(PCB)); // over链表 int productnum=0; //产品数量 int full=0, empty=buffersize; // semaphore char buffer[buffersize]; // 缓冲区 int bufferpoint=0; // 缓冲区指针 struct pcb { /* 定义进程控制块PCB */ int flag; // flag=1 denote producer; flag=2 denote consumer; int numlabel; char product; char state; struct pcb * processlink; …… }; processproc( )--- 给PCB分配内存。产生相应的的进程:输入1为生产者进程;输入2为消费者进程,并把这些进程放入就绪队列中。 waitempty( )--- 如果缓冲区满,该进程进入生产者等待队列;linkqueue(exe,&producertail); // 把就绪队列里的进程放入生产者队列的尾部 void signalempty() bool waitfull() void signalfull() void producerrun() void comsuerrun() void main() { processproc(); element=hasElement(readyhead); while(element){ exe=getq(readyhead,&readytail); printf("进程%d申请运行,它是一个",exe->numlabel); exe->flag==1? printf("生产者\n"):printf("消费者\n"); if(exe->flag==1) producerrun();

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值