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

10.22 多进程间通信-共享内存、信号量集

练习:通过信号量集完成对共享内存的同步操作

案例代码:

分文件编译:信号量集部分

sem.h

#ifndef __SEM_H__
#define __SEM_H__
#include <myhead.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) */};//1创建信号量集并初始化
int get_sem_init(int semcount);//2.申请资源P操作
void P(int semid,int semnum);//3.释放资源V操作
void V(int semid,int semnum);//4.删除信号量集
void delete_sem(int semid);#endif

sem.c

#include "sem.h"
//初始化函数
void init_sem(int semid,int semnum){union semun buf;//准备共用体变量printf("请对第%d个信号量赋初始值:",semnum+1);scanf("%d",&buf.val);//给信号量初始化if(semctl(semid,semnum,SETVAL,buf)==-1){perror("semctl error");return ;}
}
//1创建信号量集并初始化
int get_sem_init(int semcount)
{//创建key值key_t key=ftok("/",'S');if(key==-1){perror("ftok error");return -1;}//使用key值创建信号量集int semid=semget(key,semcount,IPC_CREAT|IPC_EXCL|0664);if(semid==-1){if(errno==EEXIST){//表示信号量集已经存在,则不需要进行初始化,直接打开信号量集返回id号semid=semget(key,semcount,IPC_CREAT);return semid;}perror("semget error");return -1;}//初始化信号量集for(int i=0;i<semcount;i++){init_sem(semid,i);//调用初始化函数}//将信号量级ID返回return semid;
}//2.申请资源P操作
void P(int semid,int semnum){//定义进行操作的结构体struct sembuf buf;buf.sem_num=semnum;   //要操作的信号量的编号buf.sem_op=-1;   //表示申请1个资源buf.sem_flg=0;   //表示阻塞申请//执行操作函数if(semop(semid,&buf,1)==-1){perror("semop error");return ;}
}//3.释放资源V操作
void V(int semid,int semnum){//定义进行操作的结构体struct sembuf buf;buf.sem_num=semnum;  //要操作的信号量的编号buf.sem_op=1;  //表示释放1个资源buf.sem_flg=0;  //表示阻塞释放//执行操作函数if(semop(semid,&buf,1)==-1){perror("semop error");return ;}
}//4.删除信号量集
void delete_sem(int semid){//执行操作函数进行删除if(semctl(semid,0,IPC_RMID)==-1){perror("semctl error");return;}
}

 多进程间使用共享内存同步通信

shmsnd.c

#include <myhead.h>
#include "sem.h"
#define PAGE_SIZE 4096  //物理空间单位一页大小
int main(int argc, const char *argv[])
{//使用信号量级实现多个进程间同步操作int semid=get_sem_init(2);//信号量级个数为2//1.创建一个key值key_t key=ftok("/",'m');if(key==-1){perror("ftok error");return -1;}printf("key=%#x\n",key);//2.使用key值创建一个共享内存int shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664);if(shmid==-1){perror("shmget error");return -1;}printf("shmid=%d\n",shmid);//3.获取共享内存地址char *addr=(char *)shmat(shmid,NULL,0);if(addr==(void*)-1){perror("shmat error");return -1;}printf("addr=%p\n",addr);//4.往共享内存数据存放数据while(1){//申请0信号量资源进行P操作P(semid,0);fgets(addr,PAGE_SIZE,stdin);addr[strlen(addr)-1]='\0';//释放1信号量资源进行V操作V(semid,1);if(strcmp(addr,"quit")==0){break;}}//5.断开与共享内存的链接shmdt(addr);addr=NULL;return 0;
}

shmrcv.c

#include <myhead.h>
#include "sem.h"
#define PAGE_SIZE 4096  //物理空间单位一页大小
int main(int argc, const char *argv[])
{//使用信号量级实现多个进程间同步操作int semid=get_sem_init(2);//信号量集个数为2//1.创建一个key值key_t key=ftok("/",'m');if(key==-1){perror("ftok error");return -1;}printf("key=%#x\n",key);//2.使用key值创建一个共享内存int shmid=shmget(key,PAGE_SIZE,IPC_CREAT|0664);if(shmid==-1){perror("shmget error");return -1;}printf("shmid=%d\n",shmid);//3.获取共享内存地址char *addr=(char *)shmat(shmid,NULL,0);if(addr==(void*)-1){perror("shmat error");return -1;}printf("addr=%p\n",addr);//4.取出共享内存数据while(1){//申请1信号量资源进行P操作P(semid,1);sleep(3);printf("取出数据为:%s\n",addr);//释放0信号量资源进行V操作V(semid,0);if(strcmp(addr,"quit")==0){break;}}//5.断开与共享内存的链接shmdt(addr);addr=NULL;//6.删除共享内存if(shmctl(shmid,IPC_RMID,NULL)==-1){perror("shmctl error");return -1;}//删除信号量集delete_sem(semid);return 0;
}
结果:

 练习:使用封装好了的信号量集函数,完成实现三个进程,进程1输出‘A’,进程2输出'B',进程3输出‘C’。要求输出结果为ABCABCABCABCABC...

代码实现:
#include <myhead.h>
#include "sem.h"
void handler(int signo){if(signo==SIGCHLD){while(waitpid(-1,NULL,WNOHANG)>0);   //非阻塞回收僵尸进程}
}
int main(int argc, const char *argv[])
{//将子进程结束信号SIGCHLD与signal信号绑定函数进行绑定if(signal(SIGCHLD,handler)==SIG_ERR){perror("signal error");return -1;}//使用信号量级实现进程间同步int semid=get_sem_init(3);pid_t pid=fork();if(pid>0){//父进程pid_t pid1=fork();if(pid1>0){//父进程//申请0信号量资源进行P操作for(int i=0;i<5;i++){P(semid,0);putchar('A');sleep(1);fflush(stdout);//释放1信号量资源进行V操作V(semid,1);}}else if(pid1==0){//子进程//申请1信号量资源进行P操作for(int i=0;i<5;i++){P(semid,1);putchar('B');sleep(1);fflush(stdout);//释放2信号量资源进行V操作V(semid,2);}exit(EXIT_SUCCESS);//结束进程}else {perror("fork error");return -1;}}else if(pid==0){//子进程for(int i=0;i<5;i++){//申请2信号量资源进行P(semid,2);putchar('C');sleep(1);fflush(stdout);//释放0信号量资源进行V操作V(semid,0);}exit(EXIT_SUCCESS);  //结束进程}else {perror("fork error");return -1;}wait(NULL);//阻塞回收子进程资源,避免父进程提前结束wait(NULL);delete_sem(semid);//删除信号量集return 0;
}
结果: 

 思维导图

 

相关文章:

10.22 多进程间通信-共享内存、信号量集

练习&#xff1a;通过信号量集完成对共享内存的同步操作 案例代码&#xff1a; 分文件编译&#xff1a;信号量集部分 sem.h #ifndef __SEM_H__ #define __SEM_H__ #include <myhead.h> union semun {int val; /* Value for SETVAL */struct semid_ds…...

输入输出管理器的使用

解释 InputMgr 是一个输入管理器&#xff0c;主要用于检测并管理用户的输入事件&#xff08;例如键盘和鼠标输入&#xff09;。它通过监听输入事件&#xff0c;并利用事件中心 (EventCenter) 来触发相应的事件。在这里&#xff0c;你可以管理多种输入类型&#xff0c;如按下、…...

windows连接linux服务器上的jupyter lab

文章目录 服务器上开启jupyter lab本地cmd将端口8888映射到服务器的8889上本地浏览器打开8888端口 服务器上开启jupyter lab jupyter-lab --ip 0.0.0.0 --port 8889 --no-browser --allow-root本地cmd将端口8888映射到服务器的8889上 ssh -N -f -L localhost:8888:localhost:…...

golang生成并分析cpu prof文件

1. 定义一个接口&#xff0c;请求接口时&#xff0c;生成cpu.prof文件 在主协程中新启一个协程&#xff0c;当请求接口时&#xff0c;生成一个60秒的cpu.prof文件 go func() {http.HandleFunc("/prof", startProfileHandler)http.ListenAndServe(":9092"…...

【Python爬虫实战】XPath与lxml实现高效XML/HTML数据解析

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、为什么学习xpath和lxml &#xff08;一&#xff09;高效解析和提取数据 …...

软件测试学习笔记丨Selenium学习笔记:元素定位与操作

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/22510 本文为霍格沃兹测试开发学社的学习经历分享&#xff0c;写出来分享给大家&#xff0c;希望有志同道合的小伙伴可以一起交流技术&#xff0c;一起进步~ 说明&#xff1a;本篇博客基于sel…...

在 HTML 中,<input> 元素支持的事件汇总

在 HTML 中&#xff0c;<input> 元素支持多种事件&#xff0c;这些事件可以在用户与输入字段交互时触发。以下是一些常见的 <input> 事件&#xff1a; input: 当 <input> 元素的值发生变化时触发。适用于文本、数字、日期等类型的输入。 change: 当 <inp…...

vue3【实战】 渲染 md 文件(markdown语法 .md后缀的文件)

1. 安装相关插件 npm i unplugin-vue-markdown markdown-it-prism prism unhead/vue2. 添加配置 src/main.ts // 给 md 文件创建头部 import { createHead } from unhead/vue // md 文件中代码高亮的样式 import prismjs/themes/prism.css // 自定义 md 文件的样式 import /as…...

Sora高端制造业WordPress外贸主题

Sora是一款专为高端制造业设计的WordPress主题&#xff0c;由国内知名wordpress开发团队简站wordpress主题开发&#xff0c;它以红色为主色调&#xff0c;适合外贸企业出海建独立站的模板。这个主题适用于WordPress 6.0及以上版本&#xff0c;并且只服务于真正有需要的用户。主…...

windows安装superset及各种问题解决

1,背景 先说说背景,之前在2月份已经安装过superset3.1.1,当时还没有提示SECRET_KEY异常,能正常运行,且已配置数据库连接. 2,报错信息及解决途径 1,创建admin时,提示Error! User already exists 这个是因为之前已经创建过admin用户,需要删除C:\Users\用户名\.superset下的.…...

JMeter模拟并发请求

PostMan不是严格意义上的并发请求工具&#xff0c;实际是串行的&#xff0c;如果需要测试后台接口并发时程序的准确性&#xff0c;建议采用JMeter工具。 案例&#xff1a;JMeter设置20个并发卖票请求&#xff0c;查看后台是否存在超卖的情况 方式一&#xff1a;一共10张票&…...

【小趴菜前端实习日记5】

实习日记5 一、vue3中如何使用router&#xff08;获取this)二、ts中用object定义类型太宽泛导致Ts无法推断出正确类型三、动态设置日记封面失败vite动态引入静态资源1.方法一vue3父子组件生命周期执行顺序 2.方法二3.方法三 四、打包问题总结1.The import.meta meta-property i…...

如何通过谷歌外推占据搜索引擎首页?

外贸企业在推广过程中&#xff0c;如何在谷歌搜索引擎中占据有利位置&#xff0c;获取更多曝光&#xff0c;GLB谷歌霸屏服务就可以派上用场。它通过高效的品牌外推策略&#xff0c;可以让你的企业信息在谷歌中实现“霸屏”效果&#xff0c;特别是长尾关键词的全面覆盖 很多企业…...

jmeter学习(6)逻辑控制器

1. 简单控制器 简单控制器用来存放组件的&#xff0c;没有提供什么逻辑功能。 2. 循环控制器 用来循环执行请求&#xff0c;可以配置循环次数。注意它与线程组、测试计划中的循环是相互独立的&#xff0c;比如在线程组中设置循环2次&#xff0c;循环控制器设置循环3次&#…...

Android14 和android12 在锁屏界面Keyguard输错5次密码后倒计时30秒时重启手机不显示倒计时

参考如下修改&#xff1a;Android9.0在锁屏界面Keyguard输错5次密码后倒计时30秒时重启手机不显示倒计时_android 锁屏密码输错5次-CSDN博客 android 14 修改如下&#xff1a; androidap/SYSTEM/frameworks/base$ git status Refresh index: 100% (47218/47218), done. HEAD d…...

智能时代摩托车一键启动无钥匙进入感受科技前线

向智能化与高性能迈进,技术创新与绿色转型引领摩托车行业智能化出行。 摩托车一键启动无钥匙进入功能是一种先进的车辆控制系统&#xff0c;它允许驾驶员在不使用传统机械钥匙的情况下&#xff0c;通过智能感应技术自动解锁和启动摩托车。这种系统通常包括一个智能钥匙&#x…...

需要补充的技能

密码管理 文件管理 人际管理 Microsoft365 teams和onedrive,outlook,sharepoint等 被问到自己不懂的问题的时候怎么迅速反应快速回答&#xff1f; 被帅锅的时候怎么解决&#xff1f; 谈判技巧&#xff1f; 说话的语速&#xff1f; 遇到解决不了的问题如何处理&#xff1f; 考…...

15分钟学 Go 第 15 天:映射(Map)

第15天&#xff1a;映射&#xff08;Map&#xff09; 学习目标 在本节中&#xff0c;我们将深入理解Go语言中的字典类型&#xff08;映射&#xff09;&#xff0c;通过例子与图示来帮助你掌握其使用方法。我们将涵盖以下几个方面&#xff1a; 概念定义创建和使用映射访问和更…...

element-plus 官方表格排序问题

element-plus 官方API 默认表格排序存在问题&#xff0c;一个list 被多组排序 修改后&#xff1a; 注意点&#xff1a; 这里一定要使用 sortable"custom"&#xff0c;自定义 sort-change 方法 使用 sortable true 的情况排序会冲突&#xff0c;出现莫名奇妙的问题…...

AI语音模型在家宽业务中的应用

在运营商家宽业务支撑场景中&#xff0c;存在多个APP和系统需要与装维人员交互&#xff0c;传统的功能按钮点击型操作交互界面&#xff0c;越来越难以满足装维人员工作提效的迫切需求。家宽施工调度系统所需的AI语音能力主要包括ASR&#xff08;音转字&#xff09;和TTS&#x…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

Kubernetes 节点自动伸缩(Cluster Autoscaler)原理与实践

在 Kubernetes 集群中&#xff0c;如何在保障应用高可用的同时有效地管理资源&#xff0c;一直是运维人员和开发者关注的重点。随着微服务架构的普及&#xff0c;集群内各个服务的负载波动日趋明显&#xff0c;传统的手动扩缩容方式已无法满足实时性和弹性需求。 Cluster Auto…...