当前位置: 首页 > news >正文

14-6-进程间通信-信号量

前面学习了pipe,fifo,共享内存,信号。

本章将讲述信号量。

一、什么是信号量/信号量集?

1.什么是信号量

        信号量是一个计数器。信号量用于实现进程间的同步和互斥。而可以取多个正整数的信号量被称为通用信号量。

        对信号量的使用场景的解读

        房间:临界资源(操作系统中的多个进程,他们共享各种资源,然而很多资源1次只能供1个进程使用。这种1次仅允许1个进程使用的资源称为临界资源。)

        钥匙:信号量

        只有拿到钥匙才能进入房间(如果进程A正在访问临界资源,则不允许进程B访问临界资源)。

2.什么是信号量集

linux中的信号量不止一个,有很多个。

二、P操作和V操作

p操作:取钥匙

V操作:放回钥匙

三、相关API

1.semget-----创建信号量

通过semget 来创建信号量或获取一个已有的信号量,

函数原型:#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);参数:key 信号量的关键字,可以通过ftok() 创建,详细看 进程间通信——消息队列nsems 信号量的数目(比如1代表信号量集合中有1个信号量)。如果是创建新的信号量,必须要指定nsems。如果是引用现有的信号量,nsems指定为0。shmflg 有两个选项,IPC_CREAT 表示内核中没有此信号量则创建它。IPC_EXCL 当和IPC_CREAT一起使用时,如果信号量已经存在,则返回错误。返回值:
成功返回标识符,否则返回-1。通过errno和perror函数可以查看错误信息。注意:
通过nsems 可以看出,创建一个信号量,里面可能包含多个信号量值。该信号量就相当于一个集合。该值表明有多少个共享资源单位可供共享应用。下面semctl 也是通过nsems 中的某一个进行操作。
如果nsems 设为1,该信号量又被称为二元信号量(binary semaphore)

2.semctl------初始化信号量

这个函数可以有3个参数或者4个参数

       #include <sys/types.h>#include <sys/ipc.h>#include <sys/sem.h>int semctl(int semid, int semnum, int cmd, ...);@semid:信号量数组标识@semnum:要操作的信号量数组的信号量下标(比如:0代表操作第0个信号量)(该下表和数组下标一致,比如有1个信号量,则下表为0,有2个信号量则下表为1)@cmd:IPC_STAT 查询此信号量数组的数据存入arg.buf(buf为struct semid_ds结构体指针)IPC_RMID 删除指定semid的信号量数组GETVAL 获取信号量的当前值,SETVAL 设置信号量的值,初始化要用的命令
————————————————
版权声明:本文为CSDN博主「abist」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/abist/article/details/117606809This  function  has  three  or  four arguments, depending on cmd.  Whenthere are four, the fourth has the type union semun.  The calling  pro‐gram must define this union as follows:当使用4个参数时,要定义下面的联合体union semun {int              val;    /* 钥匙的数量 */struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */unsigned short  *array;  /* Array for GETALL, SETALL */struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */};

3.semop---信号量的操作

int  semop(int  semid,struct sembuf  *sops,size_t nsops);函数的参数 
参数semid 为信号量集的标识符;
参数 sops 指向进行操作的结构体数组的首地址;
参数 nsops 指出将要进行操作的信号的个数。返回值
semop 函数调用成功返回 0,失败返回 -1。sembuf 结构体对应一个特定信号的操作。
该结构定义在 linux/sem.h,如下所示:
struct  sembuf{unsigned short   sem_num;      //信号在信号集中的索引,0代表第一个信号,1代表第二个信号  short            sem_op;      //操作类型short            sem_flg;    //操作标志
};
sem_num标识信号量集中的第几个信号量,0表示第1个,1表示第2个,nsems - 1表示最后一个。sem_op标识对信号量的所进行的操作类型。对信号量的操作有三种类型:sem_op > 0,对该信号量执行挂出操作,挂出的值由sem_op决定,系统会把sem_op的值加到该信号量的当前值semval(参考文章开头关于每个信号量结构的定义)上。如果sem_flag指定了SEM_UNDO(还原)标志,那么相应信号量的semadj值会减掉sem_op的值。下面会说明semadj的含义。sem_op < 0,对该信号量执行等待操作,当信号量的当前值semval >= -sem_op时,semval减掉sem_op的绝对值,为该线程分配对应数目的资源。如果指定SEM_UNDO,相应信号量的semadj就加上sem_op的绝对值。    当semval < -sem_op时,相应信号量的semncnt就加1,调用线程被阻塞,直到semval >= -sem_op,当此条件满足时,调用线程被唤醒,执行相应的分配操作,然后semncnt减去1。sem_op = 0,表示调用者希望semval变为0。如果为0则立即返回,如果不为0,相应信号量的semzcnt加1,调用调用线程被阻塞。sem_flag:信号量操作的属性标志,如果为0,表示正常操作,如果为IPC_WAIT,使对信号量的操作时非阻塞的。即指定了该标志,调用线程在信号量的值不满足条件的情况下不会被阻塞,而是直接返回-1,并将errno设置为EAGAIN。如果为SEM_UNDO,那么将维护进程对信号量的调整值,以便进程结束时恢复信号量的状态。下面解释一下与单个信号量相关的几个值:
semval:信号量的当前值,在文章开头信号量的结构中已提到。
semncnt:等待semval变为大于当前值的线程数。在文章开头信号量的结构中已提到。
semzcnt:等待semval变为0的线程数。在文章开头信号量的结构中已提到。
semadj:指定信号量针对某个特定进程的调整值。只有sembuf结构的sem_flag指定为SEM_UNDO后,semadj才会随着sem_op而更新。讲简单一点:对某个进程,在指定SEM_UNDO后,对信号量semval值的修改都会反应到semadj上,当该进程终止的时候,内核会根据semadj的值,重新恢复信号量之前的值。

4.P操作(取钥匙)

自定义

要利用semop()来实现void PGetKey(int id)//id是semget()的返回值
{struct sembuf set;//该结构定义在 linux/sem.hset.sem_num = 0;//这是下标,0代表第1个信号;set.sem_op = -1;//是指对钥匙数量减1;set.sem_flag = SEM_UNDO;//配置为SEM_UNDO当进程终止时,自动取消对该钥匙的操作semop(id,&set,1);
}

5.V操作(放回钥匙)

自定义

要利用semop()来实现void VputbackKey(int id)//id是semget()的返回值
{struct sembuf set;//该结构定义在 linux/sem.hset.sem_num = 0;//这是下标,0代表第1个信号;set.sem_op = 1;//是指对钥匙数量加1;set.sem_flag = SEM_UNDO;//配置为SEM_UNDO当进程终止时,自动取消对该钥匙的操作semop(id,&set,1);
}

四、实验

实验要求:

最初状态:没有钥匙。

创建子进程后,

        让父进程取钥匙(由于钥匙的数量为0,所以父进程取钥匙的动作被阻塞),使用结束(访问临界资源)后打印“father process”,放回钥匙。

        让子进程放钥匙,然后打印“child process”。

(由于最初父进程会被阻塞,所以程序运行结果是先打印"child process"后打印“father process")

思路分析

(1)生成键值

(2)创建信号量

(3)初始化信号量:定义联合体-->钥匙的个数置为0--->使用semctl初始化信号量

(4)创建子进程

(5)判断父子进程

                --->在父进程里:取钥匙,打印“father  process”,放回钥匙。

                ---->在子进程里:放钥匙,打印“child process"

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>union semun {int              val;    /* Value for SETVAL */struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */unsigned short  *array;  /* Array for GETALL, SETALL */struct seminfo  *__buf;  /* Buffer for IPC_INFO(Linux-specific) */};void VputbackKey(int id)//id是semget()的返回值
{struct sembuf set;//该结构定义在 linux/sem.hset.sem_num = 0;//这是下标,0代表第1个信号;set.sem_op = 1;//是指对钥匙数量加1;set.sem_flg = SEM_UNDO;//配置为SEM_UNDO当进程终止时,自动取消对该钥匙的操作semop(id,&set,1);printf("put back key\n");
}void PGetKey(int id)//id是semget()的返回值
{struct sembuf set;//该结构定义在 linux/sem.hset.sem_num = 0;//这是下标,0代表第1个信号;set.sem_op = -1;//是指对钥匙数量减1;set.sem_flg = SEM_UNDO;//配置为SEM_UNDO当进程终止时,自动取消对该钥匙的操作semop(id,&set,1);printf("get key\n");
}int main()
{key_t key;int semid;key = ftok(".",2);semid = semget(key,1,IPC_CREAT|0666);union semun initsem;initsem.val = 0;semctl(semid,0,SETVAL,initsem);int pid = fork();if(pid > 0){PGetKey(semid);printf("father process\n");VputbackKey(semid);}else if(pid == 0){VputbackKey(semid);printf("child process\n");}else{printf("fork error\n");}return 0;
}

五、如何销毁钥匙

semctl(semid,0,IPCIPC_RMID);//3个参数

相关文章:

14-6-进程间通信-信号量

前面学习了pipe,fifo,共享内存&#xff0c;信号。 本章将讲述信号量。 一、什么是信号量/信号量集&#xff1f; 1.什么是信号量 信号量是一个计数器。信号量用于实现进程间的同步和互斥。而可以取多个正整数的信号量被称为通用信号量。 对信号量的使用场景的解读 房间&#…...

《中国教育报》投稿邮箱编辑部征稿

《中国教育报》国家教育部主管&#xff0c;中国教育报刊社主办的以教育新闻为主的全国性日报。是迄今为止中国最具权威和最有影响力的教育新闻媒体。中国教育报刊社是中华人民共和国教育部直属的新闻出版机构。2018年获得第三届全国“百强报纸”。2019年入选“新媒体影响力指数…...

Photoshop如何使用绘画和图像修饰之实例演示?

文章目录 0.引言1.给图像添加渐变色效果2.快速创建一副素描画3.清除图像中多余的景物4.快速融合两张图像5.调整图像光影6.人像面部瑕疵修除7.美化眼睛 0.引言 因科研等多场景需要进行绘图处理&#xff0c;笔者对PS进行了学习&#xff0c;本文通过《Photoshop2021入门教程》及其…...

【C++】布隆过滤器

文章目录 布隆过滤器提出布隆过滤器概念布隆过滤器应用场景设计思路:布隆过滤器的插入布隆过滤器的查找布隆过滤器删除BloomFilter.h布隆过滤器优点布隆过滤器缺陷 布隆过滤器提出 我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经…...

功能齐全的 ESP32 智能手表,具有多个表盘、心率传感器硬件设计

相关设计资料下载ESP32 智能手表带心率、指南针设计资料(包含Arduino源码+原理图+Gerber+3D文件).zip 介绍 我们调查了智能手表项目的不同方面,并学会了集成和测试每个单独的部分。在本文中,我们将使用所学知识,结合使用硬件和软件组件,从头开始创建我们自己的智能手表。在…...

微服务不是本地部署的最佳选择,不妨试试模块化单体

微服务仅适用于成熟产品 关于从头开始使用微服务&#xff0c;马丁・福勒&#xff08;Martin Fowler&#xff09;总结道&#xff1a; 1. 几乎所有成功的微服务都是从一个过于庞大而不得不拆分的单体应用开始的。 2. 几乎所有从头开始以微服务构建的系统&#xff0c;最后都会因…...

解读Toolformer

【引子】读论文Toolformer: Language Models Can Teach Themselves to Use Tools&#xff0c;https://arxiv.org/pdf/2302.04761.pdf&#xff0c;再阅读了几篇关于Toolformer的网络热文&#xff0c;于是“无知者无畏”&#xff0c;开始自不量力地试图解读Toolformer。 大语言模…...

FCOS3D Fully Convolutional One-Stage Monocular 3D Object Detection 论文学习

论文地址&#xff1a;Fully Convolutional One-Stage Monocular 3D Object Detection Github地址&#xff1a;Fully Convolutional One-Stage Monocular 3D Object Detection 1. 解决了什么问题&#xff1f; 单目 3D 目标检测由于成本很低&#xff0c;对于自动驾驶任务非常重…...

Xpath学习笔记

Xpath原理&#xff1a;先将HTML文档转为XML文档&#xff0c;再用xpath查找HTML节点或元素 什么是xml&#xff1f; 1、xml指可扩展标记语言 2、xml是一种标记原因&#xff0c;类似于html 3、xml的设计宗旨是传输数据&#xff0c;而非显示数据 4、xml标签需要我们自己自定义 5、x…...

网络编程之 Socket 套接字(使用数据报套接字和流套接字分别实现一个小程序(附源码))

文章目录 1. 什么是网络编程2. 网络编程中的基本概念1&#xff09;发送端和接收端2&#xff09;请求和响应3&#xff09;客户端和服务端4&#xff09;常见的客户端服务端模型 3. Socket 套接字1&#xff09;Socket 的分类2&#xff09;Java 数据报套接字通信模型3&#xff09;J…...

What Are Docker Image Layers?

Docker images consist of multiple layers that collectively provide the content you see in your containers. But what actually is a layer, and how does it differ from a complete image? In this article you’ll learn how to distinguish these two concepts and…...

范数详解-torch.linalg.norm计算实例

文章目录 二范数F范数核范数无穷范数L1范数L2范数 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 范数是一种数学概念&#xff0c;可以将向量或矩阵映射到非负实数上&#xff0c;通常被…...

postgresdb备份脚本

以下是一个简单的postgresdb备份脚本示例&#xff1a; 复制 #!/bin/bash # 设置备份目录和文件名 BACKUP_DIR/path/to/backup BACKUP_FILEdb_backup_$(date %F_%H-%M-%S).sql # 设置数据库连接参数 DB_HOSTlocalhost DB_PORT5432 DB_NAMEmydatabase DB_USERmyusername DB_PA…...

MATLAB程序员投简历的技巧解析,如何写出有亮点的简历

如果你想在简历中展示你的项目经验&#xff0c;一定要有亮点。一个导出的 Excel 文件过大导致浏览器卡顿的例子就是一个很好的亮点。你可以在简历中写明这个例子。如果面试官问起&#xff0c;可以用浏览器的原理来解释。浏览器内核可以简单地分为以下 5 个线程&#xff1a;GUI …...

颜色空间转换RGB-YCbCr

颜色空间 颜色空间&#xff08;Color Space&#xff09;是描述颜色的一种方式&#xff0c;它是一个由数学模型表示的三维空间&#xff0c;通常用于将数字表示的颜色转换成可见的颜色。颜色空间的不同取决于所选的坐标轴和原点&#xff0c;以及用于表示颜色的色彩模型。在计算机…...

年薪40万程序员辞职炒股,把一年工资亏光了,得了抑郁症,太惨了

年薪40万的程序员辞职全职炒股 把一年的工资亏光了 得了抑郁症 刚才在网上看了一篇文章 是一位北京的一位在互联网 大厂上班的程序员 在去年就是股市行情比较好的时候 他买了30多万股票 结果连续三个月都赚钱 然后呢 他是就把每天就996这种工作就辞掉了 然后在家全是炒股 感觉炒…...

10分钟如何轻松掌握JMeter使用方法?

目录 引言 安装jmeter HTTP信息头管理器 JMeter断言 HTTP请求默认值来代替所有的域名与端口 JSON提取器来替换变量 结语 引言 想要了解网站或应用程序的性能极限&#xff0c;JMeter是一个不可或缺的工具。但是&#xff0c;对于初学者来说&#xff0c;该如何上手使用JMe…...

[NLP]如何训练自己的大型语言模型

简介 大型语言模型&#xff0c;如OpenAI的GPT-4或Google的PaLM&#xff0c;已经席卷了人工智能领域。然而&#xff0c;大多数公司目前没有能力训练这些模型&#xff0c;并且完全依赖于只有少数几家大型科技公司提供技术支持。 在Replit&#xff0c;我们投入了大量资源来建立从…...

LeetCode1047. 删除字符串中的所有相邻重复项

1047. 删除字符串中的所有相邻重复项 给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&#xff0c;直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一…...

3。数据结构(3)

嵌入式软件开发第三部分&#xff0c;各类常用的数据结构及扩展&#xff0c;良好的数据结构选择是保证程序稳定运行的关键&#xff0c;&#xff08;1&#xff09;部分包括数组&#xff0c;链表&#xff0c;栈&#xff0c;队列。&#xff08;2&#xff09;部分包括树&#xff0c;…...

QT停靠窗口QDockWidget类

QT停靠窗口QDockWidget类 QDockWidget类简介函数和方法讲解 QDockWidget类简介 QDockWidget 类提供了一个部件&#xff0c;它可以停靠在 QMainWindow 内或作为桌面上的顶级窗口浮动。 QDockWidget 提供了停靠窗口部件的概念&#xff0c;也称为工具面板或实用程序窗口。 停靠窗…...

【LeetCode】139. 单词拆分

139. 单词拆分&#xff08;中等&#xff09; 思路 首先将大问题分解成小问题&#xff1a; 前 i 个字符的子串&#xff0c;能否分解成单词&#xff1b;剩余子串&#xff0c;是否为单个单词&#xff1b; 动态规划的四个步骤&#xff1a; 确定 dp 数组以及下标的含义 dp[i] 表示 s…...

【三维重建】NeRF原理+代码讲解

文章目录 一、技术原理1.概览2.基于神经辐射场&#xff08;Neural Radiance Field&#xff09;的体素渲染算法3.体素渲染算法4.位置信息编码&#xff08;Positional encoding&#xff09;5.多层级体素采样 二、代码讲解1.数据读入2.创建nerf1.计算焦距focal与其他设置2.get_emb…...

IntelliJ IDEA 社区版2021.3配置SpringBoot项目详细教程及错误解决方法

目录 一、SpringBoot的定义 二、Spring Boot 优点 三、创建一个springboot的项目 四、使用IDEA创建SpringBoot失败案例 一、SpringBoot的定义 Spring 的诞⽣是为了简化 Java 程序的开发的&#xff0c;⽽ Spring Boot 的诞⽣是为了简化 Spring 程序开发的。 Spring Boot 翻…...

Qt中QDebug的使用

QDebug类为调试信息(debugging information)提供输出流。它的声明在<QDebug>中&#xff0c;实现在Core模块中。将调试或跟踪信息(debugging or tracing information)写出到device, file, string or console时都会使用QDebug。 此类的成员函数参考&#xff1a;https://doc…...

vue使用路由的query配置项时如何清除地址栏的参数

写vue项目时&#xff0c;如果想通过路由的query配置项把参数从一个组件传到另一个组件&#xff0c;但是又不希望?idxxx显示在地址栏&#xff08;如&#xff1a;http://localhost:8080/test?idxxx的?idxxx&#xff09;&#xff0c;该怎么做&#xff1a; 举一个案例&#xff1…...

Redis-列表(List)

Redis列表(List) 介绍 单键多值Redis 列表是简单的字符串列表&#xff0c;按照插入顺序排序。你可以添加一个元素到列表的头部&#xff08;左边&#xff09;或者尾部&#xff08;右边&#xff09;它的底层实际是个双向链表&#xff0c;对两端的操作性能很高&#xff0c;通过索…...

ripro主题修改教程-首页搜索框美化教程

先看效果图: 我们来看怎么实现: 1、找到wp-content/themes/ripro/assets/css/diy.css并将下面的内容整体复制进去并保存 /*首页搜索框*/ .bgcolor-fff {background-color: #fff; } .row,.navbar .menu-item-mega>.sub-menu{margin-left:-10px;margin-right:-10px;} .home…...

写作业用白光还是暖光?盘点色温4000K的护眼台灯

台灯的白光或者暖光指的是台灯的色温&#xff0c;低色温的光线看起来发黄发红&#xff0c;高色温的光线发白发蓝。 如果灯光的光源是高品质光源&#xff0c;本身没有蓝光问题&#xff0c;那么色温的选择对护眼的影响是比较少的&#xff0c;更多的是对人学习工作状态&#xff0c…...

Java时间类(一)-- SimpleDateFormat类

目录 1. SimpleDateFormat的构造方法: 时间模式字母: 2. SimpleDateFormat的常用方法: “工欲善其事,必先利其器”。学习时间类之前,需要先学习SimpleDateFormat类。 java.text.SimpleDateFormat类是以与语言环境有关的方式来格式...

和平网站建设优化seo/百度seo网站在线诊断

在对read的使用过程中&#xff0c;发现对其返回值的处理比较重要&#xff0c;这里做一下总结。read函数原型&#xff1a;ssize_t read(int fd,void *buf,size_t count)函数返回值分为下面几种情况&#xff1a;1、如果读取成功&#xff0c;则返回实际读到的字节数。这里又有两种…...

服务器不是自己的做违法网站/企业网站模板免费

在php中不支持多重继承&#xff0c;如果我们向使用多个类的方法而实现代码重用有什么办法么&#xff1f;那就是组合。在一个类中去将另外一个类设置成属性。下面的例子&#xff0c;模拟了多重继承。view sourceprint?0102 class user {03 private $name "tom";04 p…...

wordpress页面生成/苏州旺道seo

大家好&#xff0c;我是你们的码农大哥——栈长。 6 月初的时候给大家介绍了 Spring 团队的最新杀手锏项目&#xff1a;Spring Native&#xff0c;它的存在就是干掉 JVM&#xff0c;另起一个 JVM 之外的生态&#xff0c;上篇也简单实战了一下&#xff0c;相信大家都有了一个全…...

哪个网站可以做围棋作业/广告投放平台都有哪些

今日所做&#xff1a; 尝试连接数据库 明日所做&#xff1a; 数据库信息修改 遇到的困难&#xff1a; 数据库连接有点复杂&#xff0c;经过队友跟网上查询终于完成连接&#xff0c;中途数据库连接中&#xff0c;数据库sqllite不太明白&#xff0c;导致很长时间在上面耽搁&#…...

网站 ip地址是什么/链接下载

正文 此处以Quartus II 11.1和Notepad v5.9.6.2为例。 1. 使用QII自动调用Notepad来打开HDL、sdc、txt等文件&#xff1b;并且可以在报错的时候&#xff0c;Notepad可以直接高亮所报错的行&#xff08;此模式下&#xff0c;Notepad最大化后效果最佳&#xff09;。 方法&#xf…...

企业网站设计经典案例/在线代理浏览网址

题目 力扣 思路 暴力 根据题意&#xff0c;在sx和sy不大于tx和ty时&#xff0c;遍历所有情况&#xff0c;结果会超时。 代码 class Solution { public:bool reachingPoints(int sx, int sy, int tx, int ty) {return dfs(sx, sy, tx, ty);}bool dfs(int sx, int sy, int t…...