进程间通信--信号量【Linux操作系统】

文章目录

  • 并发编程相关基础概念
  • 信号量
    • 深刻理解信号量
      • 使用共享资源的方式
      • 分块使用共享资源的方式会出现的问题
      • 举例子理解信号量的第二个特性---预定
      • 信号量要成为计数器面临的问题
    • 信号量相关操作接口--POSIX
      • 库函数:sem_init
      • 库函数:sem_destroy
      • 库函数:sem_wait
      • 库函数:sem_post
    • 信号量相关操作接口--systemV
      • 系统调用:semget
      • 系统调用:semop

并发编程相关基础概念

在这里插入图片描述

保护共享内存的本质就是:
对访问共享内存的代码(临界区)进行限制

信号量

信号量和其他进程间通信的作用不太一样,它主要是用来实现进程(线程)间同步互斥的

信号量(进程)的生命周期也和共享内存一样:随内核
所以
①要么由进程使用系统调用释放信号量
②要么操作系统重启



深刻理解信号量

信号量本质是一个对资源进行预定的计数器



使用共享资源的方式

访问临界资源的时候,有两种访问方式:

  • 1.一次直接使用一整个临界资源
    比如
    我们之前对管道的使用,从来就没有考虑过写入位置和读取位置在哪的问题
    只是直接从管道读取,直接向管道写入,是直接以一整个管道为单位进行使用

    • 此时出于对共享资源的保护的互斥性,一次就只能一个进程访问这个管道
  • 2.把一个临界资源分成多个分区,让不同进程可以使用不同分区
    这样的好处是:

    • 1.可以在不违反保护共享资源特性的情况下,一个共享资源可以被多个进程同时使用(并发使用)
    • 2.申请一块共享资源非常繁琐,所以如果多个进程想两两通信
      可以只申请一块共享资源,再把它分区给所有进程使用
    • 只申请一块共享资源也可以减少使用系统调用


分块使用共享资源的方式会出现的问题

分块使用共享资源虽然可以做到一块共享资源,多个进程并发使用
但是一种方法了解决一个问题,必然又会出现新的问题
这个新的问题就是:
共享资源的分区个数<进程个数怎么办?

例如
我们把一个共享资源分成了16个区,但是同时来了30个进程要访问共享资源怎么办?
在这里插入图片描述

此时再怎么分配,也不可能让所有进程同时使用这个共享资源=
只能先分配16个进程,等一些进程使用丸了,再让剩下的进程进来用
如何做到这一点呢?
使用计数器!!!

  1. 让计数器等于分区数,这样一个进程要使用共享资源前,都先判断一下const是否>0
    如果是就是还有分区空着,可以给它,再count--
    如果不是,就让进程阻塞等待

  2. 同理,如果有一个进程退出了临界区,就会有一个分区空出来,count++

所以本质上共享资源使用方法1和2其实是一样的,因为整体使用时不就是分区个数只有1个吗?



举例子理解信号量的第二个特性—预定

我们生活中,不管是看电影还是坐高铁,都要买票,因为它们的名额都是需要竞争的资源
买票的本质就是:对资源进行预定
就是买到票了,我就算不去,那个资源也是属于我的

而且票的个数也有限,因为资源的个数有限,不能出现两个人用同一个资源的情况,所以票又何尝不是一个计数器呢?

我们上面所说的进程竞争使用共享资源的分区,本质也是如此
只要一个进程抢到了计数器的名额,共享资源中就一定有一个分区会给它

所以信号量的本质是和票一样,是对资源进行预定的计数器

所以
人们抢高铁座位,其实是抢票
进程抢共享资源的分区,其实是抢计数器(信号量)名额

所以共享资源分区,最重要的不是分配,而是对计数器(信号量)的正确使用

对共享资源整体使用的时候,计数器count不是等于0就是等于1
此时称这个计数器为:二元信号量或者锁



信号量要成为计数器面临的问题

  • 1.如何让不同进程看到计数器(信号量)呢?
    让信号量作为共享资源!!!

  • 2.信号量本身就是共享资源,它去包含其他的共享资源,那谁来保护它呢?
    比如两个进程同时看见信号量还剩一个,它们同时去抢,同时抢到手,count同时=0
    这不就卡bug了吗?

信号量本质是一个对共享资源进行预定的计数器
计数器的操作无非就是++和–
只要让这两个操作都具有不可中断的原子性不就可以了吗?
所以操作系统为信号量专门定义了具有两个原子性的操作
即P操作[++]和V操作[–]



信号量相关操作接口–POSIX

使用信号量接口之前,需要定义一个信号量对象(sem_t类型)

库函数:sem_init

  • 头文件:semaphore.h

  • 参数表:

    • 1.sem_t*sem
      要初始化的信号量的地址

    • 2.int pshared
      1.如果是pshared是0,则表示线程间信号量
      2.如果是pshared非0,则表示进程间信号量

    • 3.unsigned int val
      即:信号量这个计数器的初始值,也就是把共享资源分成几份/共享资源的个数

  • 作用:
    初始化对应的信号量


库函数:sem_destroy

  • 头文件:semaphore.h

  • 参数表:
    sem_t*sem:要销毁的信号量的地址

  • 作用:
    销毁对应的信号量


库函数:sem_wait

  • 头文件:semaphore.h

  • 参数表:
    sem_t*sem:对应的信号量的地址

  • 作用:
    申请信号量,P操作,信号量–
    (申请信号量失败【即信号量减到0】,线程/进程会被阻塞)


库函数:sem_post

  • 头文件:semaphore.h

  • 参数表:
    sem_t*sem:对应的信号量的地址

  • 作用:
    释放信号量,V操作,信号量++



信号量相关操作接口–systemV

如果有多个共享内存要分区使用,那么就需要多个信号量

所以操作系统提供信号量,是以信号量集合的方式提供的
即:申请信号量的时候,申请的是一个/多个信号量


系统调用:semget

  • 头文件:
    sys/types.hsys/ipc.hsys/sem.h

  • 返回值:int类型
    ①成功,返回用户(进程)使用的信号量集合标识符合条件
    ②失败,返回-1

  • 参数表:

    • key_t key:内核中唯一标识一个信号量集合(key的获取和使用方法于共享内存的key一模一样,使用ftok获取

    • int nsems:信号量集合中的信号量个数

    • int semflag:位图标志位
      也和共享内存的一模一样
      IPC_CREAT:单独使用的话如果对应的共享内存不存在,就创建。存在就返回shmid
      该选项主要给获取共享内存的进程使用
      IPC_EXCL:不能单独使用
      但是
      IPC_CREAT | IPC_EXCL
      如果对应的共享内存不存在,就创建并在页表建立映射关系
      存在就报错
      该选项主要给创建共享内存的进程使用

  • 作用:创建(获取)一个信号量集合


系统调用:semop

  • 头文件:
    sys/types.hsys/ipc.hsys/sem.h

  • 参数表:

    • int semid:进程使用的信号量集合唯一标识

    • struct sembuf*p:指向一个struct sembuf的数组的起始地址
      struct sembuf
      {
      int sem_num//信号量集合的下标
      short sem_op//-1表示–,1表示++
      short sem_flaf//一般不管,设置为0
      }
      semop这样设计是为了,可以同时对一个信号量集合中的多个信号量进行PV操作或者对信号量集合进行整体操作

    • ③int nsops :参数②指向的数组的元素个数

  • 作用:对一个信号量集合中的一个/多个信号量进行PV操作

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

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

相关文章

谢赛宁团队提出 BLIP3-o:融合自回归与扩散模型的统一多模态架构,开创CLIP特征驱动的图像理解与生成新范式

BLIP3-o 是一个统一的多模态模型&#xff0c;它将自回归模型的推理和指令遵循优势与扩散模型的生成能力相结合。与之前扩散 VAE 特征或原始像素的研究不同&#xff0c;BLIP3-o 扩散了语义丰富的CLIP 图像特征&#xff0c;从而为图像理解和生成构建了强大而高效的架构。 此外还…

HarmonyOs开发之——— ArkWeb 实战指南

HarmonyOs开发之——— ArkWeb 实战指南 谢谢关注!! 前言:上一篇文章主要介绍HarmonyOs开发之———合理使用动画与转场:CSDN 博客链接 一、ArkWeb 组件基础与生命周期管理 1.1 Web 组件核心能力概述 ArkWeb 的Web组件支持加载本地或在线网页,提供完整的生命周期回调体…

黑马程序员C++2024版笔记 第0章 C++入门

1.C代码的基础结构 以hello_world代码为例&#xff1a; 预处理指令 #include<iostream> using namespace std; 代码前2行是预处理指令&#xff0c;即代码编译前的准备工作。&#xff08;编译是将源代码转化为可执行程序.exe文件的过程&#xff09; 主函数 主函数是…

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(22):复习

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(22):复习 1、前言(1)情况说明(2)工程师的信仰2、知识点(1)复习(2)復習3、单词(1)日语(2)日语片假名单词4、对话练习5、单词辨析记录6、总结1、前言 (1)情况说明 自己在今年,在日本留学中,目前在语言学校,…

Docker配置SRS服务器 ,ffmpeg使用rtmp协议推流+vlc拉流

目录 演示视频 前期配置 Docker配置 ffmpeg配置 vlc配置 下载并运行 SRS 服务 推拉流流程实现 演示视频 2025-05-18 21-48-01 前期配置 Docker配置 运行 SRS 建议使用 Docker 配置 Docker 请移步&#xff1a; 一篇就够&#xff01;Windows上Docker Desktop安装 汉化完整指…

Redis——缓存雪崩、击穿、穿透

缓存雪崩 大量缓存数据在同一时间过期或者Redis故障宕机时&#xff0c;若此时有大量请求&#xff0c;都会直接访问到数据库&#xff0c;导致数据库压力倍增甚至宕机。 大量数据同时过期解决方案&#xff1a; 1、均匀设置过期时间&#xff1a; 设置过期时间的时候可以追加一…

开源GPU架构RISC-V VCIX的深度学习潜力测试:从RTL仿真到MNIST实战

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;H卡级别算力&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生专属优惠。 一、开篇&#xff1a;AI芯片架构演变的三重挑战 &#xff08;引述TPUv4采用RISC-V的行业案…

字符串相乘(43)

43. 字符串相乘 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:string multiply(string num1, string num2) {string res "0";for (int i 0; i < num2.size(); i) {string str multiplyOneNum(num1, num2[num2.size() -…

mathematics-2024《Graph Convolutional Network for Image Restoration: A Survey》

推荐深蓝学院的《深度神经网络加速&#xff1a;cuDNN 与 TensorRT》&#xff0c;课程面向就业&#xff0c;细致讲解CUDA运算的理论支撑与实践&#xff0c;学完可以系统化掌握CUDA基础编程知识以及TensorRT实战&#xff0c;并且能够利用GPU开发高性能、高并发的软件系统&#xf…

[LevelDB]LevelDB版本管理的黑魔法-为什么能在不锁表的情况下管理数据?

文章摘要 LevelDB的日志管理系统是怎么通过双链表来进行数据管理为什么LevelDB能够在不锁表的情况下进行日志新增 适用人群: 对版本管理机制有开发诉求&#xff0c;并且希望参考LevelDB的版本开发机制。数据库相关从业者的专业人士。计算机狂热爱好者&#xff0c;对计算机的…

【C++进阶篇】C++容器完全指南:掌握set和map的使用,提升编码效率

C容器的实践与应用&#xff1a;轻松掌握set、map与multimap的区别与用法 一. 序列式容器与关联式容器1.1 序列式容器 (Sequential Containers)1.2 关联式容器 (Associative Containers) 二. set系列使用2.1 set的构造和迭代器2.2 set的增删查2.2.1 插入2.2.2 查找2.2.3 删除 2.…

2_Spring【IOC容器中获取组件Bean】

Spring中IOC容器中获取组件Bean 实体类 //接口 public interface TestDemo {public void doSomething(); } // 实现类 public class HappyComponent implements TestDemo {public void doSomething() {System.out.println("HappyComponent is doing something...")…

安卓开饭-ScrollView内嵌套了多个RecyclerView,只想与其中一个RecyclerView有联动

在 Android 开发中&#xff0c;将 RecyclerView 嵌套在 ScrollView 内通常会导致性能问题和滚动冲突&#xff0c;应尽量避免这种设计。以下是原因和替代方案&#xff1a; 为什么不推荐 RecyclerView ScrollView&#xff1f;​​ 性能损耗​ RecyclerView 本身已自带高效回收复…

HTTP 请求中 Content-Type 头部

HTTP 请求中 Content-Type 头部可以设置的各种不同的传输格式。multipart/form-data 只是其中一种,主要用于传输包含文件的数据。 以下是一些常见的 HTTP 请求体的 Content-Type 及其用途: 常见的数据传输格式 (Content-Type) 列表: application/json: 描述: 用于传输 JSO…

【U-boot 命令使用】

文章目录 1 查询有哪些命令2 信息查询命令dbinfo - 查看板子信息printenv- 输出环境变量信息version - 输出uboot版本信息 3 环境变量操作命令修改环境变量新建环境变量删除环境变量 4 内存操作命令md命令nm命令mm命令mv命令cp命令cmp命令 5 网络操作命令与网络有关的环境变量p…

初学者如何用 Python 写第一个爬虫?

初学者如何用 Python 写第一个爬虫&#xff1f; 一、爬虫的基本概念 &#xff08;一&#xff09;爬虫的定义 爬虫&#xff0c;英文名为 Web Crawler&#xff0c;也被叫做网络蜘蛛、网络机器人。想象一下&#xff0c;有一个勤劳的小蜘蛛&#xff0c;在互联网这个巨大的蜘蛛网中…

IDE/IoT/搭建物联网(LiteOS)集成开发环境,基于 VSCode + IoT Link 插件

文章目录 概述IDE安装安装旧版本VSCode安装插件安装问题和解决手动安装SDK包手动下载依赖工具 IoTLink配置IoTLink Home用户设置-工具链-编译器用户设置-工具链-构建器用户设置-工具链-烧录器用户设置-SDK管理工程设置-SDK配置工程设置-编译器工程设置-调试器 创建工程Demo 源码…

深度剖析:Dify+Sanic+Vue+ECharts 搭建 Text2SQL 项目 sanic-web 的 Debug 实战

目录 项目背景介绍sanic-web Dify\_service handle\_think\_tag报错NoneType问题描述debug Dify调用不成功&#xff0c;一直转圈圈问题描述debug 前端markdown格式只显示前5页问题描述debug1. 修改代码2.重新构建1.1.3镜像3.更新sanic-web/docker/docker-compose.yaml4. 重新部…

理想AI Talk第二季-重点信息总结

一、TL&#xff1b;DR 理想为什么要做自己的基模&#xff1a;座舱家庭等特殊VLM场景&#xff0c;deepseek/openai没有解决理想的基模参数量&#xff1a;服务端-300B&#xff0c;VLencoder-32B/3.6B&#xff0c;日常工作使用-300B&#xff0c;VLA-4B为什么自动驾驶可以达成&…

TensorRT

TensorRT 下载 TensorRT 7.1.3.4 TAR压缩包&#xff0c;解压到安装目录&#xff1a; tar xzvf TensorRT-7.1.3.4.Ubuntu-16.04.x86_64-gnu.cuda-11.0.cudnn8.0.tar.gz 添加 TensorRT lib 到环境变量&#xff1a; gedit ~/.bashrc # 添加 export LD_LIBRARY_PATH$LD_LIBRARY_PAT…