闵行做网站/推广网

闵行做网站,推广网,做标签网站,东莞企业邮箱进程间通信——信号量 目录 一、基本概念 1.1 概念 1.2 基本操作 1.3 相关函数 1.3.1 semget创建/获取 1.3.2 semop操作信号量 1.3.3 semctl初始化/删除 二、代码操作 2.1 不用PV的 2.2 用PV 的 2.2.1 a.c 2.2.2 b.c 2.2.3 sem.h 2.2.4 sem.c 一、基本概念 1.1…

进程间通信——信号量

目录

一、基本概念 

1.1 概念

1.2 基本操作

1.3 相关函数

1.3.1 semget创建/获取

1.3.2 semop操作信号量

1.3.3 semctl初始化/删除

二、代码操作

2.1 不用PV的

2.2 用PV 的

2.2.1 a.c

2.2.2 b.c

2.2.3 sem.h

 2.2.4 sem.c


一、基本概念 

1.1 概念

信号量本质上是一个计数器,用于记录可用资源的数量。它有两种类型的操作:P 操作(也称为 wait 操作)和 V 操作(也称为 signal 操作)。P 操作会将信号量的值减 1,表示请求一个资源V 操作会将信号量的值加 1,表示释放一个资源

当信号量的值为 0 时,表示没有可用资源,此时进程在请求资源时会被阻塞,直到其他进程释放资源。

临界资源:同一时刻只允许一个进程访问的资源

临界区:访问临界资源的代码段。这段代码执行了就会访问例如打印机之类的临界资源

1.2 基本操作

初始化:在使用信号量之前,需要对其进行初始化,设置初始值。这个值通常表示系统中某种资源的初始数量。
P 操作:当一个进程需要访问共享资源时,它首先执行 P 操作。如果信号量的值大于 0,那么 P 操作会成功执行,进程可以继续执行并使用资源,同时信号量的值减 1。如果信号量的值为 0,那么进程会被阻塞,放入与该信号量相关的等待队列中,直到其他进程执行 V 操作释放资源。
V 操作:当进程使用完共享资源后,它执行 V 操作。V 操作会将信号量的值加 1,如果有其他进程在等待该资源(即信号量的等待队列不为空),那么系统会从等待队列中唤醒一个进程,让它继续执行 P 操作以获取资源。

1.3 相关函数

1.3.1 semget创建/获取

semget 函数用于创建一个新的信号量集或获取一个已存在的信号量集的标识符

#include <sys/sem.h>int semget(key_t key, int nsems, int semflg);
  • key:一个键值,用于标识信号量集。可以使用 ftok 函数生成一个唯一的键值,也可以使用特殊值 IPC_PRIVATE 来创建一个私有的信号量集,该信号量集只能由创建它的进程及其子进程访问。
  • nsems:指定信号量集中信号量的数量。如果是创建新的信号量集,必须指定该值;如果是获取已存在的信号量集,该值通常为 0。
  • semflg:标志位,用于指定创建信号量集的模式和权限等。常见的标志有:
    • IPC_CREAT:如果信号量集不存在,则创建它。
    • IPC_EXCL:与 IPC_CREAT 一起使用,若信号量集已存在,则返回错误。
    • 权限标志,如 0666 表示所有用户都有读写权限。
  • 成功时,返回一个非负整数,即信号量集的标识符(semid)。
  • 失败时,返回 -1,并设置 errno 来指示错误类型。

1.3.2 semop操作信号量

semop 函数用于对信号量集中的一个或多个信号量进行操作,如 P 操作(申请资源)和 V 操作(释放资源)

#include <sys/sem.h>int semop(int semid, struct sembuf *sops, unsigned nsops);
  • semid:信号量集的标识符,由 semget 函数返回。
  • sops:指向一个 struct sembuf 结构体数组的指针,每个 struct sembuf 结构体描述了对一个信号量的操作。struct sembuf 结构体的定义如下:
  • struct sembuf {unsigned short sem_num;  // 信号量在信号量集中的索引(从 0 开始)short          sem_op;   // 操作类型,正数表示释放资源(V 操作),负数表示申请资源(P 操作),0 表示等待信号量值为 0short          sem_flg;  // 标志位,常见的有 IPC_NOWAIT 表示非阻塞操作
    };
  • nsopssops 数组中元素的数量,即要执行的操作数量。

1.3.3 semctl初始化/删除

semctl 函数用于对信号量集进行控制操作,如初始化信号量的值、获取信号量的状态信息、删除信号量集等。

#include <sys/sem.h>int semctl(int semid, int semnum, int cmd, ...);
  • semid:信号量集的标识符,由 semget 函数返回。
  • semnum:信号量在信号量集中的索引(从 0 开始)。如果 cmd 不需要指定特定的信号量,则该值通常为 0。
  • cmd:要执行的控制命令,常见的命令有:
    • SETVAL:设置指定信号量的值,需要传递一个 int 类型的参数作为新值。
    • GETVAL:获取指定信号量的值,返回值即为信号量的当前值。
    • IPC_RMID:删除信号量集,不需要指定 semnum,也不需要额外的参数。
  • ...:可变参数,根据 cmd 的不同而有所不同。例如,当 cmd 为 SETVAL 时,需要传递一个 int 类型的参数作为新的信号量值。
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "sem.h"int main()
{sem_init(); // 创建并初始化信号量for(int i=0; i<5; i++){sem_p();printf("A");fflush(stdout);int n = rand() % 3; // 随机睡眠一段时间sleep(n);printf("A");fflush(stdout);sem_v();n = rand() % 3;sleep(n);}sleep(10);sem_destroy(); // 删除信号量
}

二、代码操作

2.1 不用PV的

a.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>int main()
{for(int i=0;i<5;i++){printf("A");fflush(stdout);int n=rand()%3;sleep(n);printf("A");fflush(stdout);}
}

b.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>int main()
{for(int i=0;i<5;i++){printf("B");fflush(stdout);int n=rand()%3;sleep(n);printf("B");fflush(stdout);}
}

 

  1. /a &./b& :在后台同时运行可执行文件 a 和 b ,[1] 10916 和 [2] 10917 分别是这两个后台进程的作业编号和进程号。

2.2 用PV 的

2.2.1 a.c

a.c使用信号量进行进程同步的C语言程序示例。

它演示了如何使用信号量来控制对共享资源的访问,以防止数据竞争和条件竞争

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "sem.h"int main()
{sem_init();//创建并初始化信号量//pfor(int i = 0; i < 5; i++ ){sem_p();printf("A");fflush(stdout);int n = rand() % 3;sleep(n);printf("A");fflush(stdout);sem_v();n = rand()%3;sleep(n);}//vsleep(10);sem_destroy();//删除信号量
}

2.2.2 b.c

 b.c它演示了如何使用信号量来控制对共享资源的访问。

在这个例子中,程序通过信号量来确保在打印字符'B'时不会有多个线程或进程同时执行,从而避免输出混乱。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "sem.h"
int main()
{sem_init();for(int i = 0; i < 5; i++ ){sem_p();printf("B");fflush(stdout);int n = rand() % 3;sleep(n);printf("B");fflush(stdout);sem_v();n = rand()%3;sleep(n);}}

2.2.3 sem.h

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/sem.h>union semun
{int val;
};void sem_init();
void sem_p();
void sem_v();
void sem_destroy();

定义了一组与信号量操作相关的函数原型和一个用于信号量操作的联合体semun

这个联合体用于在信号量操作中传递信号量的值

这些函数原型定义了信号量操作的接口,下面是这些函数可能的实现方式:

  1. sem_init:初始化信号量。

  2. sem_p:执行信号量的P操作(wait操作),减少信号量的值,如果信号量的值小于0,则进程将被阻塞。

  3. sem_v:执行信号量的V操作(signal操作),增加信号量的值,如果有进程因等待此信号量而被阻塞,则它们可能会被唤醒。

  4. sem_destroy:销毁信号量,释放相关资源。

 2.2.4 sem.c

信号量操作实现

#include "sem.h"
static int semid = -1;void sem_init()
{semid = semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);//尝试创建一个新的信号了if( semid == -1 )//信号量可能存在{semid = semget((key_t)1234,1,0600);if( semid == -1){printf("sem err\n");return;}}else//初始化 1{union semun a; a.val = 1;if( semctl(semid,0,SETVAL,a) == -1){printf("semctl err\n");}}
}
void sem_p()
{struct sembuf buf;buf.sem_num = 0;buf.sem_op = -1;//pbuf.sem_flg = SEM_UNDO;//if( semop(semid,&buf,1) == -1)//可能阻塞{printf("p err\n");}}
void sem_v()
{struct sembuf buf;buf.sem_num = 0;buf.sem_op = 1;//vbuf.sem_flg = SEM_UNDO;//if( semop(semid,&buf,1) == -1){printf("v err\n");}
}
void sem_destroy()
{if( semctl(semid,0,IPC_RMID) == -1){printf("rm semid err\n");}
}

sem_init 函数 初始化一个信号量

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

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

相关文章

Linux内核2-TFTP与NFS环境搭建

Uboot&#xff1a;引导程序 初始化硬件设备&#xff0c;初始化c语言环境&#xff0c;为内核加载做准备 zImage:内核文件 rootfs:文件系统&#xff0c;为用户提供一个与硬件设备数据交互的系统 1.TFTP和NFS功能 TFTP:简单文件传输协议网络配置 pc可以下载 2.minicom bootargs…

Crypto Architecture Kit简介

HarmonyOS 5.0.3(15) 版本的配套文档&#xff0c;该版本API能力级别为API 15 Release 文章目录 约束与限制能力范围基本概念与相关Kit的关系 Crypto Architecture Kit屏蔽了第三方密码学算法库实现差异的算法框架&#xff0c;提供加解密、签名验签、消息验证码、哈希、安全随机…

交流电机类型及其控制技术

交流电机可分为同步电机和异步电机两大种类&#xff0c;如果电机转子的转速与定子旋转磁场的转速相等&#xff0c;转子与定子旋转磁场在空间同步地旋转&#xff0c;这种电机就称为同步电机。如果电机转子的转速不等于定子旋转磁场的转速&#xff0c;转子与定子旋转磁场在空间旋…

fluent_UDF学习笔记

UDF源代码路径 D:\Program Files\ANSYS Inc\v231\fluent\fluent23.1.0\src关于颗粒反弹速度的计算 /* 通过面法向单位向量计算速度的法向向量、切向向量&#xff0c;再通过法向、切向恢复系数重新计算反弹速度*//* Compute normal velocity.将颗粒速度向面法线方向投影&#x…

第十六届蓝桥杯模拟二(串口通信)

由硬件框图可以知道我们要配置LED 和按键 一.LED 先配置LED的八个引脚为GPIO_OutPut,锁存器PD2也是,然后都设置为起始高电平,生成代码时还要去解决引脚冲突问题 二.按键 按键配置,由原理图按键所对引脚要GPIO_Input 生成代码,在文件夹中添加code文件夹,code中添加fun.…

06-ADC

ADC简介 Analog-Digital Converter 模拟-数字转换器 ADC可以将引脚上连续变化的模拟电压转换为内存中存储的数字变量&#xff0c;建立模拟电路到数字电路的桥梁。 12位逐次逼近型ADC&#xff0c;1us转换时间&#xff1b;输入电压范围&#xff1a;0-3.3V&#xff0c;转换结果…

二层综合实验

拓扑图 实验要求 1.内网IP地址使用172.16.6.0/16分配 2.sw1和sW2之间互为备份 3.VRRP/STP/VLAN/Eth-trunk均使用 4.所有Pc均通过DHCP获取IP地址 5.ISP只能配置IP地址 6.所有电脑可以正常访问IsP路由器环回 实验思路 这是一个二层综合实验每当拿到一个实验看清楚要求之后都有…

Java实现pdf中动态插入图片

今天接到一个需求&#xff0c;需要在pdf中的签名处&#xff0c;插入签名照片&#xff0c;但签名位置不固定&#xff0c;话不多说上代码&#xff1a; 1、首先引入itextpdf依赖包&#xff1a; <dependency><groupId>com.itextpdf</groupId><artifactId>…

基于Spring AI开发本地Jenkins MCP Server服务

前言 首先介绍下MCP是什么&#xff1f; MCP是由开发了 Claude 模型的 Anthropic 公司2024年12月提出并开源的一项开放标准&#xff0c;全称&#xff1a;Model Context Protocol&#xff0c;它是一个开放协议&#xff0c;它使 LLM 应用与外部数据源和工具之间的无缝集成成为可能…

vcpkg安装指定版本的库

一.vcpkg安装 使用git将vcpkg源码克隆到本地制定目录&#xff08;D:\vcpkg&#xff09;&#xff0c;并初始化 git clone https://github.com/microsoft/vcpkg.git cd vcpkg ./bootstrap-vcpkg.sh # Linux/macOS .\bootstrap-vcpkg.bat # Windows 如下图&#xff1a; 二.安…

WPF ContentPresenter详解2

ContentPresenter与ContentControl的区别 ContentControl 和 ContentPresenter 是 WPF 中两个相关的控件&#xff0c;但它们在用途和功能上有一些关键的区别。理解这两者的区别和联系有助于更好地设计和开发用户界面。 1. 类层次结构 ContentControl&#xff1a;位于 WPF 控件…

【HTML5游戏开发教程】零基础入门合成大西瓜游戏实战 | JS物理引擎+Canvas动画+完整源码详解

《从咖啡杯到财务自由&#xff1a;一个程序员的合成之旅——当代码遇上物理引擎的匠心之作》 &#x1f31f; 这是小游戏开发系列的第四篇送福利文章&#xff0c;感谢一路以来支持和关注这个项目的每一位朋友&#xff01; &#x1f4a1; 文章力求严谨&#xff0c;但难免有疏漏之…

RTMP推流+EasyDSS云服务+边缘AI分析的无人机监控系统设计

在现代科技不断发展的背景下&#xff0c;无人机技术已经广泛应用于各个领域&#xff0c;从航拍摄影到工业巡检&#xff0c;从农业监测到应急救援&#xff0c;无人机以其高效的工作能力&#xff0c;为人们的生活和工作带来了诸多便利与创新&#xff0c;而其视频传输与分析系统更…

HCIP(VLAN综合实验)

实验拓补图 实验分析 一、实验目的 掌握VLAN的创建和配置方法理解VLAN在局域网中的作用学习如何通过VLAN实现网络隔离和通信 二、实验环境 交换机&#xff08;SW1、SW2、SW3&#xff09;个人电脑&#xff08;PC1、PC2、PC3、PC4、PC5、PC6&#xff09;路由器&#xff08;R1…

第十二章——位运算

按位的与& 若x的第i位和y的第i位都是1&#xff0c;那么&#xff08;x&y&#xff09;1&#xff0c;否则&#xff08;x&y&#xff09; 0 应用&#xff1a;希望让某一位或某些位为0 。取一个数中的一段。 按位的或| 若x的第i位1或y的第i位1&#xff0c;那么&…

【Mysql:内置函数】

日期函数&#xff1a; 查看当前日期&#xff1a; select current_date();查看当前时间&#xff1a; select current_time(); 查看当前时间戳&#xff1a; select current_timestamp(); 计算两个日期的差值&#xff1a; select datediff(date1,date2); 当前的日期时间&a…

71. 我的第一个Linux驱动实验

一、字符设备驱动框架 字符设备驱动的编写主要就是驱动对应的open、close、read。。。其实就是 file_operations结构体的成员变量的实现。 其中关于 C 库以及如何通过系统调用“陷入” 到内核空间这个我们不用去管&#xff0c;我们重点关注的是应用程序和具体的驱动&#xff0…

jdk21使用Vosk实现语音文字转换,免费的语音识别

1.下载vosk的model vosk官网&#xff1a;https://alphacephei.com/vosk/models 我这里使用较小的vosk-model-small-cn-0.22 2.添加相关pom文件 <!-- 获取音频信息 --><dependency><groupId>org</groupId><artifactId>jaudiotagger</artifac…

C++修炼:string类的使用

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…

【go微服务】如何快速掌握grpc开发

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…