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

Linux——信号量

目录

一、信号量定义

二、信号量种类

三、信号量操作

3.1 P操作

3.2 V操作

四、信号量的代码实现

4.1 信号量创建,初始化

4.2 销毁信号量

4.3 p操作

4.4 v操作

五、使用PV操作代码实现

5.1 d.c 

5.2 e.c


一、信号量定义

信号量是一种用于同步多线程或进程之间的机制,用于控制对共享资源的访问。信号量可以用来保护临界区,防止多个线程同时访问某个共享资源导致数据不一致或竞争条件的发生。

二、信号量种类

信号量是用来实现进程之间的同步和互斥的一种机制。信号量种类主要分为两种:

  1. 二进制信号量(Binary Semaphore):也称为互斥信号量,只能取两个值,通常是0和1。用于实现互斥访问共享资源(互斥锁(Mutex)),保证同一时间只有一个线程访问共享资源。

  2. 计数信号量(Counting Semaphore):可以取多个值,用来进行进程间的同步。用于管理有限数量的共享资源,允许多个线程同时访问资源,但访问数量有限制。它可以表示一定数量的资源可用或者表示某种事件发生的次数。

除了这两种主要的信号量种类,还有一些其他类型的信号量,如忙等待信号量、无忙等待信号量、实时信号量等,这些信号量种类可以根据具体的应用场景和需求进行选择和使用。

三、信号量操作

信号量操作通常包括两种:P操作和V操作。

3.1 P操作

        1.申请资源。

        2.如果信号量的值大于 0,则将其减 1,表示成功获取资源。

        3.如果信号量的值为 0,则线程进入等待状态,直到信号量的值大于 0。

3.2 V操作

        1.释放资源。

        2.将信号量的值加 1,表示释放一个资源。

        3.如果有线程因等待该信号量而阻塞,V 操作会唤醒其中一个线程。

临界资源:同一时刻值运行一个进程访问的资源。

临界区:访问临界资源的代码段。 

四、信号量的代码实现

4.1 信号量创建,初始化

sem_init()

static int semid = -1;void sem_init()
{semid = semget((key_t)1234,1,IPC_CREAT|IPC_EXCL|0600);//全新创建一个信号量if(semid==-1)//如果失败,说明已经创建,直接获取id即可{semid=semget((key_t)1234,1,0600);//获取别人创建的信号量if(semid==-1){printf("semget err\n");return;}}else{union semun a;a.val=1;if( semctl(semid,0,SETVAL,a) == -1){printf("semctl init err\n");}}
}

4.2 销毁信号量

sem_destroy()

void sem_destroy()
{if(semctl(semid,0,IPC_RMID) == -1){printf("semctl rm err\n");}
}

4.3 p操作

sem_p()

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");}
}

4.4 v操作

sem_v()

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");}
}

五、使用PV操作代码实现

5.1 d.c 

#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);}
}

5.2 e.c

下面的示例是程序通过信号量来保证在打印字符'B'时不会有多个线程或进程同时执行,从而避免出现混乱。

#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);}sleep(10);sem_destroy();
}

编译通过后,运行结果如下:

相关文章:

  • linux 内核 ida机制分析
  • 【SpringMVC】深入解析自定义拦截器、注册配置拦截器、拦截路径方法及常见拦截路径、排除拦截路径、拦截器的执行流程
  • 视觉SLAM和激光SLAM建图输出的文件类型
  • 域控制器升级的先决条件验证失败,证书服务器已安装
  • 基于大模型的反流食管炎手术全流程风险预测与治疗方案研究报告
  • 【钱包】Tron签名总结
  • c# 数据结构 链表篇 有关双向链表的一切
  • Vue el-from的el-form-item v-for循环表单如何校验rules(一)
  • TMS320F28P550SJ9学习笔记15:Lin通信SCI模式结构体寄存器
  • 【Java学习】Knife4j使用流程
  • MongoDB常见语句
  • dsp的主码流,子码流是指什么,有什么区别和作用
  • 实践001-Gitlab基础项目准备
  • [MySQL] 事务管理(一) 事务的基本概念
  • Python基础知识(基础语法二)
  • 【ROS2】行为树 BehaviorTree(六):各种各样的节点
  • 循环神经网络 - 扩展到图结构之递归神经网络
  • AI核心概念之“Function Calling” - 来自DeepSeek
  • 4-15记录(冒泡排序,快速选择排序)
  • 电路(b站石群老师主讲,持续更新中...)
  • 什么样的赛事能推进建设全球著名体育城市,上海半马就是答案
  • 商务部:消费者已累计购买以旧换新家电产品超1亿台
  • 特写|为何这么多人喜欢上海半马,答案藏在他们的笑容里
  • 大理州工业投资(集团)有限公司党委副书记、副总经理赵云接受审查调查
  • 杨国荣丨阐释学的内涵与意义——张江《阐释学五辨》序
  • 推动中阿合作“向新而行”,这场论坛在上海松江举行