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

Linux操作系统 使用信号量实现进程同步

信号量

不加入控制模拟使用打印机:

比如:进程a和进程b模拟访问打印机,进程a输出第一个字符‘a’ 表示开始使用打印机,输出第二个字符‘a’表示结束使用,b进程操作与a进程相同。

//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
int main()
{int i=0;for(;i<5;i++){printf("A");fflush(stdout);int n=rand()%3;sleep(n);printf("A");fflush(stdout);n=rand()%3;sleep(n);}
}//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
int main()
{int i=0;for(;i<5;i++){printf("B");fflush(stdout);int n=rand()%3;sleep(n);printf("B");fflush(stdout);n=rand()%3;sleep(n);}
}

 正确的结果应该是:AABB成对出现

但由于打印机同一时刻只能被一个进程使用,所以输出结果不应该出现ABAB这样的交替结果

所以上面代码得到的结果是错误的

信号量的介绍

信号量就是控制某个进程能够对某个资源进行访问;保证同一时刻只能由一个进程对某个资源进程访问;

信号量是一个特殊的变量,对信号量的操作都是一个原子操作;

打印机

信号量就是一个特殊的变量,一般为正整数。他的值代表允许访问的资源树木,获取资源的时候,需要对信号量的值进行原子-1,该操作被称作P操作。当信号量的值为0的时候,代表没有资源可用,P操作会被阻塞。释放资源时,需要对信号量的值进行原子+1,该操作被称作V操作。信号量主要用来同步进程。信号量的值如果只取0,1,将其称为二值信号量。如果信号量的值大于1,则称之为技术信号量。

 临界资源:同一时刻,只能允许被一个进程或者线程访问的资源;

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

信号量接口介绍

(1)semgetint  semget(key_t  key,int nsems,int semflg);创建或者获取一个已经存在的信号量;key:两个进程使用相同的key值,就可以使用同一个信号量;nsems:创建几个信号量;semflg:标志位;如果为创建:IPC_CREAT;如果为全新创建,也就是不知道是否有人创建过,则IPC_CREAT|IPC_EXCL,
就是如果没有则创建,如果有则创建失败 ;(2)semop:int semop(int semid,struct sembuf *sops,unsigned nsops);  对信号量进行改变,做P操作或者V操作;semid:信号量的id号,也就是刚才semget的返回值;说明对哪个信号量进行操作;
sops:结构体指针,指向sembuf的结构体指针,
sembuf结构体有三个成员变量:
sem_num表示信号量的编号(即指定信号量集中的信号量下标);
sem_op表示是p还是v操作;1为v操作(加1),-1为p操作(减1);
sem_flg为标志位;  (3)semctl:int semctl(int semid,int semnum,int cmd,...);  对信号量进行控制:初始化/删除信号量semid:信号量id;semnum:信号量编号;cmd:命令:SETVAL:初始化信号量;      IPC_RMID:删除信号量;**注意**:联合体semun,这个联合体需要自己定义;

有控制的使用打印机(信号量控制):

//sem.h
#include <sys/sem.h>
#include <unistd.h>
#include <stdio.h>union semun{int val;
};void sem_init();
void sem_p();
void sem_v();
void sem_destroy();//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){perror("semget error!\n");}}else{union semun  a;a.val=1;if(semctl(semid,0,SETVAL,a)==-1){perror("semctl init error!");}}
}void sem_p()
{struct sembuf buf;buf.sem_num=0;buf.sem_op=-1;buf.sem_flg=SEM_UNDO;if(semop(semid,&buf,1)==-1){perror("p error!\n");}
}void sem_v()
{struct sembuf buf;buf.sem_num=0;buf.sem_op=1;buf.sem_flg=SEM_UNDO;if(semop(semid,&buf,1)==-1){perror("v error!\n");}
}void sem_destroy()
{if(semctl(semid,0,IPC_RMID)==-1){perror("destroy sem error!\n");}
}//a.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include "sem.h"
int main()
{int i=0;sem_init();for(;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();
}//b.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include "sem.h"
int main()
{int i=0;sem_init();for(;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);}   
}

 

 


文章转载自:

http://m79QlPkk.fnfhs.cn
http://JjgvBbOq.fnfhs.cn
http://FWmiT0rN.fnfhs.cn
http://SfZVwvhK.fnfhs.cn
http://Glax9NsT.fnfhs.cn
http://gkCLNU6U.fnfhs.cn
http://c0kifEzE.fnfhs.cn
http://vyrPMshw.fnfhs.cn
http://5ENA78Pc.fnfhs.cn
http://JmPcvIgu.fnfhs.cn
http://EEh2oSOx.fnfhs.cn
http://tAXvbknx.fnfhs.cn
http://SRCv5dT0.fnfhs.cn
http://1rpF44oe.fnfhs.cn
http://2C5DYLQP.fnfhs.cn
http://DzSXLQhY.fnfhs.cn
http://tJolWWdq.fnfhs.cn
http://lDHvwVhl.fnfhs.cn
http://RFPhbi4r.fnfhs.cn
http://v7jGAegY.fnfhs.cn
http://TyGbZP4C.fnfhs.cn
http://qdE4gAjx.fnfhs.cn
http://xlcEEahg.fnfhs.cn
http://UwIbi4yT.fnfhs.cn
http://prWxToQP.fnfhs.cn
http://2EDp8TK3.fnfhs.cn
http://644XALhq.fnfhs.cn
http://kqqQc4EV.fnfhs.cn
http://WTDIFULr.fnfhs.cn
http://3kK1S5EB.fnfhs.cn
http://www.dtcms.com/a/212548.html

相关文章:

  • OpenCV 第7课 图像处理之平滑(一)
  • 基于CEEMDAN-Transformer-BiLSTM的多特征风速气候预测的完整实现方案及PyTorch源码解析
  • Reactor模式详解:高并发场景下的事件驱动架构
  • 【redis】redis和hiredis的基本使用
  • 机器学习---各算法比较
  • 解决win10总是读硬盘
  • 测试计划与用例撰写指南
  • C++ queue对象创建、queue赋值操作、queue入队、出队、获得队首、获得队尾操作、queue大小操作、代码练习
  • MIT 6.S081 Lab9 file system
  • 计网5:HTTP/TCP的长连接和短连接的区别以及各自的应用场景
  • Spring Cloud Alibaba Sentinel安装+流控+熔断+热点+授权+规则持久化
  • C++单例模式与线程安全
  • GAN-STD:融合检测器与生成器的方法
  • 解决Visual Studio报“IntelliSense不可用,需设置TRACEDESIGNTIME = true“问题
  • 热编码(One-Hot Encoding)
  • Volatile的相关内容
  • 【MySQL系列】数据库死锁问题
  • mysql 导入导出数据
  • 人工智能概论(一)初见人工智能笔记
  • 分布式消息中间件设计与实现
  • ELF文件的作用详解
  • 互联网大厂Java求职面试:AI与大模型应用集成中的架构难题与解决方案
  • react 脚手架
  • STM32八股【10】-----stm32启动流程
  • 【Linux】磁盘空间不足
  • BTC官网关注巨鲸12亿美元平仓,XBIT去中心化交易平台表现稳定
  • github项目:llm-guard
  • SpringCloud实战:Seata分布式事务整合指南
  • Github 今日热点 完全本地化的自主AI助手,无需API或云端依赖
  • Linux进程通信之管道机制全面解析