操作系统原理 —— 什么是信号量,信号量如何实现进程互斥、进程同步?(十五)

news2024/11/24 6:58:27

在之前的章节中,我们提到了进程互斥,以及进程互斥实现的几种方式,那么今天我们再来讲解一种,基于 信号量 来实现进程之间的同步、互斥的方式。

用户进程可以通过使用操作性提供的一对原语来对信号量进行操作,从而很方便的实现进程互斥、进程同步。

什么是信号量

信号量 可以这么简单的来理解,它其实就是一个变量,这个变量可以是一个整数,也可以是更复杂的记录型变量,可以用一个信号量来表示系统中某种资源的数量。

比如:系统中只有一台打印机,就可以设置一个初始值为 1 的信号量。

那怎么操作这个信号量变量呢? 那么就是原语。

原语是一种特殊的程序段,这个程序段它是能够保证原子性操作的,执行只能一气呵成,不能被中断。至于为什么原语能够保证原子性,是因为开中断/关中断这两个指令来实现的。

知道原语的特性之后,那什么原语能够操作信号量呢? 那就是 wait(S) 原语和 signal(S) 原语,可以把原语理解成平时我们写代码的函数、方法,括号里面的信号量 S 其实就是调用函数、方法的时候,传入的一个参数。

wait、signal 原语简称为 P、V 操作,经常把 wait(S)、signal(S) 简称为 P(S)、V(S)。

那我们接下来看看两种不同类型的信号量。

整型信号量

上文有说到信号量其实就是一个变量,整型信号量顾名思义就是用一个整型的变量作为信号量,用来表示系统某种资源的数量。 那信号量变量和普通的变量有什么区别呢? 普通的变量可以做加减乘除运算等等,而对信号量的操作只有三种:初始化、P 操作、V 操作。

我们来写一段伪代码来解释一下,整型信号量是如何实现进程互斥的,并且有什么缺点。

现在假设有一台计算机中,只有一个打印机资源:

int s = 1; // 初始化整形信号量 s,表示当前系统中可用的打印机资源数量

void wait(int S){ // wait 原语,也就是 P 操作,相当于进入区
    while(S <= 0); // 如果资源不够,就一直循环等待
    S = S -1; // 如果资源够,则占用一个资源,
}

void signal(int S){ // sginal 原语,也就是 V 操作,相当于 退出区
    S = S + 1;// 使用完资源后,在退出区释放资源
}

上面就是对应 P、V 操作中的逻辑,现在我们有 P0、P1 进程现在都需要来使用打印机,我们来看看执行过程:

P0、P1 的执行过程都是如下:

wait(S); // 进入区,申请资源
使用打印机.. // 临界区,访问资源
signal(S) // 退出区,释放资源

假设现在 P0 先执行 P 操作,那么它是可以申请到资源的,当 P0 还是临界区中访问资源,这个时候 P1 进程也开始申请资源,但是由于资源被 P0 使用了,P1 会卡在 while 循环那一直等待,一直到 P0 执行了 V 操作释放资源,P 1才可以进入临界区。

这里要注意的是,我们要记住 P、V 操作都是原语来实现的,原语是具有原子性操作的,可以解决并发的问题,来保证进程互斥。但是缺点也很明显,没有获取到资源的进程,会一直等待,不满足 让权等待的规则。

让权等待就是当进程访问不了临界资源的时候,需要立即释放 CPU 资源,不能一直等待着。

这个问题也就是整型信号量记录型信号量最大的区别,那么接下来我们一起来看看记录型信号量是如何解决这个问题的。

记录型信号量

为了解决整型信号量的问题,记录型信号的变量就比较复杂一点,如下:

typedef struct {
    int value; // 剩余资源数
    Struct process *L; // 等待队列
} semaphore; 

相比整型信号量多了一个等待队列,这个等待队列的作用就是当进程进入不到临界区的时候,会把线程设置成阻塞状态,并且会把想要获取该资源的线程放到这个等待队列当中。

我们一起来看下具体的逻辑,我们还是用伪代码的方式讲解:

void wait(semaphore S){
    S.value --;
    
    if(S.value < 0){
        block(S.L); // 把进程设置阻塞状态,并且把进程挂载到等待队列中
    } 
}

void signal(semaphore S){
    S.value ++;
    
    if(S.value <= 0){
        weakup(S.L); // 从等待队列中唤醒一个进程
    } 
}

对信号量 S 的一次 P操作,就意味着进程请求一个单位的该类资源,因此需要执行 S.value-- ,表示资源数量 -1,当 S.value < 0 的时候,表示该类资源已经分配完成,因此该进程调用 block 原语进行自我阻塞,从运行态转换为阻塞态,主动放弃 CPU 执行权,并且放入到 S.L 的等待队列中。 这样就能解决整型信号量的让权等待问题。

当使用完临界资源之后,对信号量 S 进行一个 V 操作,释放一个单位的该类资源,因此需要执行 S.value++,表示该类资源数量 +1,如果 +1 之后 S.value 的数量还是 <= 0,表示还有进程正在等待该类资源的释放,因此需要调用 wakeup 原语唤醒等待队列中的一个进程,从阻塞态转换为就绪态。

使用信号量实现进程互斥

使用信号量实现互斥的方式其实上面也简单说过了,那么我们再来总结一下,

在上文也有提到,信号量可以代表一种临界资源的数量,那么在操作系统里面有那么多资源,我们需要对不同的临界资源设置不同的互斥信号量。

比如说还是以打印机的资源为例子:我们先设置一个打印机资源的信号量,代码如下:

semaphore mutex = 1 ; // 定义一个信号量

p1(){

p(mutex) // 申请资源
临界区代码...
v(mutex) // 释放资源

}

p2(){

p(mutex) // 申请资源
临界区代码...
v(mutex) // 释放资源

}

以上面的代码为例子,当 p1 先执行代码,获取了临界资源,在这个时候 p2 申请资源是会被阻塞起来的,一直阻塞到 p1 释放了资源,p2 才可以接着继续运行,这样就能实现进程互斥。

这里需要注意的是,P、V 操作必须成对出现,如果缺少 P 操作就不能保证临界区资源互斥访问,缺少 V 操作会导致资源永远不被释放,等待进程永远不会被唤醒。

那么接下来,我们再来看看信号量如何做同步操作。

使用信号量实现进程同步

同步其实也很好实现实现,我们在初始化信号量的时候,初始化的值要是为 0,然后先执行 V 操作,后执行 P 操作,这样就能实现进程同步。 我们还是来看个代码例子:

semaphore s = 0 ; // 定义一个信号量,初始化为0

p1(){

代码1
代码2
v(s) 
代码3

}

p2(){

p(s) 
代码4
代码5
代码6

}

假设现在我们要实现:代码4一定要在代码2后面执行,保证执行顺序,我们来观察一下上面这段代码:

假设我们现在是 P2 先开始执行,但是由于 s 初始化是0,所以 p2 在执行 P 操作的时候,会被阻塞,一直等到 P1 执行了 V 操作,P2 才可以被唤醒执行,这样就能保证 代码4 一定是在 代码2 后面执行的。

我们只要记住:前 V 后 P 的操作,就能使用信号量实现进程同步。

本章总结

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/540405.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言基础知识:C语言中的指针

目录 1、为什么需要指针? 2、指针是什么&#xff1f; 3、指针与变量的关系 4、指针的分类 5、指针的用法 6、指针的运算 7、野指针 8、指针使用时的注意事项 同C语言中其他变量一样&#xff0c;把指针也可以看成是一种变量。不过&#xff0c;这种变量专门存储地址值。…

vscode链接远程服务器开发c++项目

因为要在linux环境下开发c应用&#xff0c;需要一个比较好用的远程工具。之前做深度学习的时候一直用vscode链接服务器写python&#xff0c;感觉用起来很舒服。 vscode下载安装这些就略过了&#xff0c;从插件安装和配置文件开始介绍 参考文章&#xff1a;https://zhuanlan.zh…

如何做一份精致的性能测试报告?

相比于普通的功能测试&#xff0c;性能测试对测试工程师的技能要求更高&#xff0c;一般来说&#xff0c;也只有中高级测试工程师才会有机会做性能测试。 对于题主关心的问题&#xff0c;我拆分出下面三个部分来做解答&#xff1a; 1、性能测试报告的目的 2、性能测试过程中的关…

【算法分析与设计报告】快递终端送货配送系统、基因序列比较、地图染色、文章查重系统、果园篱笆问题(附源码)

一、快递终端送货分配问题 问题描述 假设某快递终端投递站&#xff0c;服务n个小区&#xff0c;小区与快递点之间有道路相连&#xff0c;如下图&#xff0c;边上的权值表示距离。 图1-1 小区快递点图 现在设有m包裹&#xff0c;每个包裹都有自己的目的地及总量。 假设送货员一…

IPB072N15N3G-ASEMI代理英飞凌高压MOS管IPB072N15N3G

编辑&#xff1a;ll IPB072N15N3G-ASEMI代理英飞凌高压MOS管IPB072N15N3G 型号&#xff1a;IPB072N15N3G 品牌&#xff1a;英飞凌 封装&#xff1a;TO-263 最大漏源电流&#xff1a;31A 漏源击穿电压&#xff1a;600V RDS&#xff08;ON&#xff09;Max&#xff1a;99mΩ…

第四届“中国法研杯”司法人工智能挑战赛-刑期预测赛道三等奖方案

一、前言 本文将回顾第四届“中国法研杯”司法人工智能挑战赛-刑期预测算法赛道比赛。使用多任务预训练、然后进行微调的形式最终在比赛中取得了三等奖的成绩。 二、任务介绍 主办方在第一届“中国法研杯”比赛上提出了刑期预测任务&#xff0c;本届将针对往届刑期预测准确率…

《终身成长》笔记六——称赞努力的过程,也将其与结果关联

目录 经典摘录 成为好父母好老师 成长型思维模式的真伪 第一种错误理解&#xff1a;很多人将他们身上某些他们喜欢的优点称作“成长型思维模式” 第二种错误理解&#xff1a;很多人认为成长型思维模式只关乎努力&#xff0c;特别是去夸奖别人的努力 第三种错误理解&#xff…

基于树莓派4B的智能家居

基于树莓派4B的智能家居 前言C语言的简单工厂模式工厂模式介绍类和对象工厂模式的优缺点优点缺点 智能家居框架产品工厂卫生间灯设备二楼灯设备餐厅灯设备客厅灯设备泳池灯设备风扇设备锁设备警报器设备地震监测设备火灾监测设备温湿度检测设备 指令工厂语音控制设备server控制…

如何创建样本手册?

第一步&#xff1a;提前研究和规划 首先明确目标客户群体在其中扮演的角色。 谁会穿你的衣服&#xff1f;您品牌的潜在客户是谁&#xff1f;他们的愿望是什么&#xff1f;他们会被什么打动&#xff1f;设置客户角色至关重要&#xff0c;因为它将决定样本手册的基调&#xff0…

Simulink 自动代码生成电机控制:模型仿真速度的优化

目录 方法一 Simulationmode 方法二 多核并行 方法三 Performance Advisor 总结 方法一 Simulationmode 执行下面的指令获取Simulink仿真实时&#xff0c;这里以霍尔FOC的模型为例&#xff0c;在切换模式为Accelerator时不能使用调用子模型的形式&#xff0c;需要把子模型复制…

map的forEach区别

map的forEach区别 先总结下&#xff1a; map和forEach区别是&#xff1a; 1.map有返回值而且必须return返回一个数组才行 ; 而forEach没有返回值可直接打印结果&#xff1b; 即&#xff1a;forEach()方法不会返回执行结果&#xff0c;而是undefined。也就是说&#xff0c;forEa…

vue 在线聊天实战范例(含选择发送表情、图片、视频、音频,自定义右键快捷菜单,一键复制,左右聊天气泡)

最终效果 完整代码 index.vue <template><div class"page"><div class"leftBox"><h1>访客</h1><div class"chatBox"><div class"chatRecordBox"><div v-for"(item, index) in cha…

DBCO-COOH分子量:305.3,CAS:1353016-70-2,二苯基环辛炔-羧基;类似有DBCO-NH2、SH、MAL、NHS等等

中文名称&#xff1a;二苯基环辛炔-羧基 英文名称&#xff1a;DBCO-acid 英文别称&#xff1a;DBCO-COOH cas: 1353016-70-2 分子式&#xff1a;C19H15NO3 分子量&#xff1a;305.3 DBCO-COOH是DBCO 衍生化的常用构件&#xff0c;在EDC、DCC和HATU等活化剂存在下&#xf…

linux kernel menuconfig kconfig makefile

概述 menuconfig是Linux平台用于管理代码工程、模块及功能的实用工具。 menuconfig的使用方式通常是在编译系统之前在系统源代码根目录下执行make menuconfig命令从而打开一个图形化配置界面&#xff0c;再通过对各项的值按需配置从而达到影响系统编译结果的目的。 Nuttx的me…

Spring Boot 数据库操作Druid和HikariDataSource

目录 Spring Boot 数据库操作 应用实例-需求 创建测试数据库和表 进行数据库开发&#xff0c; 在pom.xml 引入data-jdbc starter 参考官方文档 需要在pom.xml 指定导入数据库驱动 在application.yml 配置操作数据源的信息 创建bean\Furn.java 测试结果 整合Druid 到…

六、easyUI中的window(窗口)组件

1.window&#xff08;窗口&#xff09;组件的概述 窗口控件是一个浮动和可拖拽的面板&#xff0c;它可以用作应用程序窗口。默认情况下&#xff0c;窗口可以移动&#xff0c;调整大小和关闭。它的内容也可以被定义为静态HTML或要么通过Ajax动态加载 2.window&#xff08;窗口&…

MySQL-备份+日志:介质故障与数据库恢复

MySQL-备份日志&#xff1a;介质故障与数据库恢复 第1关&#xff1a;备份与恢复任务描述相关知识MySQL的恢复机制MySQL的备份与恢复工具编程要求代码参考 第2关 备份日志&#xff1a;介质故障的发生与数据库的恢复任务描述相关知识编程要求测试说明代码参考 第1关&#xff1a;备…

《分布式微服务电商源码》-项目简介

1.常见的电商模式 市面上有 5 种常见的电商模式 B2B、B2C、C2B、C2C、O2O 1.1.B2B 模式 B2B(Business to Business)&#xff0c;是指商家和商家建立的商业关系&#xff0c;如阿里巴巴. 1.2.B2C 模式 B2C(Business to Consumer) 就是我们经常看到的供应商直接把商品买个用户&a…

057:cesium设置纯颜色材质

第057个 点击查看专栏目录 本示例的目的是介绍如何在vue+cesium中设置纯颜色的材质,颜色的表达方式可以参考这篇文章 Cesium七种方法设置颜色 直接复制下面的 vue+cesium源代码,操作2分钟即可运行实现效果. 文章目录 示例效果配置方式示例源代码(共87行)相关API参考:专…

用友BIP新零售产品发布,与零售企业共创新未来

随着数智化时代的到来&#xff0c;零售企业不断面临着更多的挑战和机遇。为了满足消费者多元化的需求&#xff0c;零售企业需要采用多种方式来提高竞争力&#xff0c;如多渠道销售、线上线下融合、数智化运营、个性化营销和无缝化体验等。用友BIP新零售为零售企业提供了数智化转…