进程间通信——信号量

进程间通信——信号量

目录

一、基本概念 

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…

TDengine 中的命名与边界

简介 本章主要介绍命名的合法字符集和限制规则&#xff0c;这对于正确使用 TDengine&#xff0c;减小报错很重要&#xff0c;这些规则在 SQL 语句中都生效&#xff0c;在使用过程中要注意&#xff0c;避免不必要的错误。 名称命名规则 合法字符&#xff1a;英文字符、数字和…

C++ 中将函数作为参数传递

C 中将函数作为参数传递 1. 通过指针传递函数 函数可以通过传递函数的地址来作为参数传递&#xff1b;简而言之&#xff0c;就是通过指针实现这一点。 示例代码 #include <iostream> using namespace std;// 定义加法和减法函数 #include <iostream> #include …

Vala 编程语言教程-继承

继承‌ 在 Vala 中&#xff0c;一个类可以继承自 ‌一个或零个‌ 其他类。尽管实际开发中通常继承一个类&#xff08;不同于 Java 等语言的隐式继承机制&#xff09;&#xff0c;但 Vala 并不强制要求必须继承。 当定义继承自其他类的子类时&#xff0c;子类的实例与父…

Crypto Architecture Kit简介

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

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

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

SQL语言分类及命令详解(一)

目录 1. DQL&#xff08;Data Query Language&#xff09;数据查询语言 主要命令&#xff1a; SELECT 2. DDL&#xff08;Data Definition Language&#xff09;数据定义语言 主要命令&#xff1a; CREATE ALTER DROP TRUNCATE&#xff08;清空表数据&#xff0c;保留…

fluent_UDF学习笔记

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

Go 语言标准库中sort模块详细功能介绍与示例

Go语言的 sort 模块提供了对切片和自定义数据结构的排序功能&#xff0c;支持基本类型排序、自定义排序规则、稳定排序和二分查找。以下是 sort 模块的核心方法及示例说明&#xff1a; 1. 基本类型排序 sort.Ints、sort.Float64s、sort.Strings 直接对基本类型的切片进行排序…

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

由硬件框图可以知道我们要配置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>…

OpenCV 图形API(2)为什么需要图形API?

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 G-API背后的动机 G-API模块为OpenCV带来了基于图的执行模型。本章简要描述了这种新模型如何在两个方面帮助软件开发者&#xff1a;优化和移植图像处理算法…

基于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; 二.安…

数据结构C语言练习(单双链表)

本篇练习题(单链表)&#xff1a; 1.力扣 203. 移除链表元素 2.力扣 206. 反转链表 3.力扣 876. 链表的中间结点 4.力扣 21. 合并两个有序链表 5. 牛客 链表分割算法详解 6.牛客 链表回文结构判断 7. 力扣 160. 相交链表 8. 力扣 141 环形链表 9. 力扣 142 环形链表 II…

nginx部署前端项目(linux、docker)

引言 在CentOS 7系统上使用docker安装nginx&#xff0c;使用nginx部署一个由Vue开发、打包的项目 docker安装nginx 这里不多赘述&#xff0c;直接上docker-compose.yml代码 nginx:container_name: nginximage: nginx:1.27.2ports:- "80:80"volumes:- /docker/ngin…

WPF ContentPresenter详解2

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

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

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