Linux信号灯

news2024/11/13 9:37:09

概念:是不同进程间或一个给定进程内部不同线程间同步的机制。类似我们的

PV操作概念:

生产者和消费者场景

P(S) 含义如下:

     if  (信号量的值大于0) { 

             申请资源的任务继续运行;

             信号量的值减一;

    } else {  

            申请资源的任务阻塞;

    }

V(S) 含义如下:

     信号量的值加一;

     if (有任务在等待资源) {  

            唤醒等待的任务,让其继续运行

    }

信号灯P操作

int sem_wait(sem_t *sem);

获取资源,如果信号量为0,表示这时没有相应资源空闲,那么调用线程就将挂起,直到有空闲资源可以获取

信号灯V操作

int sem_post(sem_t *sem);

释放资源,如果没有线程阻塞在该sem上,表示没有线程等待该资源,这时该函数就对信号量的值进行增1操作,表示同类资源多增加了一个。如果至少有一个线程阻塞在该sem上,表示有线程等待资源,信号量为0,这时该函数保持信号量为0不变,并使某个阻塞在该sem上的线程从sem_wait函数中返回

注意:编译posix信号灯需要加pthread动态库。

三种信号灯:

Posix 有名信号灯

Posix 无名信号灯 (linux只支持线程同步)

System V 信号灯

Posix 有名信号灯和无名信号灯使用:

 有名信号灯打开:

sem_t *sem_open(const char *name, int oflag);
sem_t *sem_open(const char *name, int oflag,mode_t mode, unsigned int value);
参数:
name:name是给信号灯起的名字
oflag:打开方式,常用O_CREAT 
mode:文件权限。常用0666
value:信号量值。二元信号灯值为1,普通表示资源数目

信号灯文件位置:/dev/shm

有名信号灯关闭

int sem_close(sem_t *sem);

有名信号灯的删除

int sem_unlink(const char* name);

 有名信号灯:

 sem_w.c

#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<semaphore.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>


int main()
{
	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	int shmid;
	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return 0;
	}

	char* shmaddr;
	shmaddr = shmat(shmid,NULL,0);

	sem_t* sem_r,*sem_w;
	sem_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
	sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);

	while(1)
	{
		sem_wait(sem_w);
		printf(">");
		fgets(shmaddr,500,stdin);
		sem_post(sem_r);
	}

	return 0;
}

sem_r.c

#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<semaphore.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>


int main()
{
	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	int shmid;
	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return 0;
	}

	char* shmaddr;
	shmaddr = shmat(shmid,NULL,0);

	sem_t* sem_r,*sem_w;
	sem_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
	sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);

	while(1)
	{
		sem_wait(sem_r);
		printf("%s\n",shmaddr);
		sem_post(sem_w);
	}

	return 0;
}

运行结果: 

test_r.c

#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<semaphore.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<signal.h>

void handle(int sig)
{
    sem_unlink("mysem_w");
	exit(0);
}


int main()
{
	struct sigaction act;
	act.sa_handler = handle;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaction(SIGINT,&act,NULL);

	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	int shmid;
	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return 0;
	}

	char* shmaddr;
	shmaddr = shmat(shmid,NULL,0);

	sem_t* sem_r,*sem_w;
	sem_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
	sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);

	while(1)
	{
		sem_wait(sem_r);
		printf("%s\n",shmaddr);
		sem_post(sem_w);
	}

	return 0;
}

 test_w.c

#include<stdio.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<semaphore.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/shm.h>
#include<signal.h>

void handle(int sig)
{
	sem_unlink("mysem_r");
	exit(0);
}

int main()
{
	struct sigaction act;
	act.sa_handler = handle;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);
	sigaction(SIGINT,&act,NULL);

	key_t key;
	key = ftok(".",100);
	if(key < 0)
	{
		perror("ftok");
		return 0;
	}
	int shmid;
	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid < 0)
	{
		perror("shmget");
		return 0;
	}

	char* shmaddr;
	shmaddr = shmat(shmid,NULL,0);

	sem_t* sem_r,*sem_w;
	sem_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
	sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);

	while(1)
	{
		sem_wait(sem_w);
		printf(">");
		fgets(shmaddr,500,stdin);
		sem_post(sem_r);
	}

	return 0;
}

运行结果: 

无名信号灯初始化 

int sem_init(sem_t *sem, int shared, unsigned int value);
参数:
sem:需要初始化的信号灯变量
shared: shared指定为0,表示信号量只能由初始化这个信号量的进程使用,不能在进程间使用,linux 不支持进程间同步。
Value:信号量的值

 无名信号灯销毁

int sem_destroy(sem_t* sem);

无名信号灯: 

        该程序包含一个主进程和一个读取进程。主进程负责从标准输入中读取用户输入,并将其写入共享内存中,读取进程则从共享内存中读取数据并输出到标准输出。

1.信号处理函数,用于在程序中断时销毁信号量destroysem

2.读取进程函数readmem

sem_wait(&sem_r); // 等待写入信号量

printf("%s\n",shmaddr); // 读取共享内存内容并打印

sem_post(&sem_w); // 发送写入信号量

3.设置信号处理函数sigaction

4.生成共享内存ftok

5.创建共享内存shmget

6.将共享内存连接到当前进程的地址空间shmat

7.初始化信号量sem_init

8.创建读取进程pthread_create

9.读取数据并输出到标准输出

 sem_wait(&sem_w); // 等待读取信号量
 printf(">"); 
 fgets(shmaddr,500,stdin); // 从标准输入读取数据到共享内存
 sem_post(&sem_r); // 发送读取信号量

具体代码: 

#include <fcntl.h>           /* For O_* constants */
#include <sys/stat.h>        /* For mode constants */
#include <semaphore.h>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <signal.h>
#include <pthread.h>


sem_t sem_r,sem_w;
char *shmaddr;
void destroysem(int sig){

	sem_destroy(&sem_r);
	sem_destroy(&sem_w);
	exit(0);

}

void *readmem(void *arg){
	while(1){
		sem_wait(&sem_r);
		printf("%s\n",shmaddr);
		sem_post(&sem_w);

	}

}


int main(){


	key_t key;
	int shmid;

	struct sigaction act;
	act.sa_handler = destroysem;
	act.sa_flags = 0;
	sigemptyset(&act.sa_mask);

	sigaction(SIGINT,&act,NULL);

	key = ftok(".",100);
	if(key<0){
		perror("ftok");
		return 0;
	}

	shmid = shmget(key,500,0666|IPC_CREAT);
	if(shmid<0){
		perror("shmget");
		return 0;
	}

	shmaddr = shmat(shmid,NULL,0);


	sem_init(&sem_r,0,0);
	sem_init(&sem_w,0,1);

	pthread_t tid;
	pthread_create(&tid,NULL,readmem,NULL);

	while(1){
		sem_wait(&sem_w);
		printf(">");
		fgets(shmaddr,500,stdin);
		sem_post(&sem_r);
	}

}

        这个程序的主要功能是从标准输入中读取用户输入,并将其写入共享内存,然后另一个进程从共享内存中读取数据并打印到标准输出。

运行结果: 

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

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

相关文章

同态滤波算法详解

同态滤波是一种用于增强图像的方法&#xff0c;特别适用于去除图像中的照明不均和阴影。该算法基于照射反射模型&#xff0c;将图像分解为两个分量&#xff1a;照射分量&#xff08;illumination component&#xff09;和反射分量&#xff08;reflection component&#xff09;…

腾讯云服务器地域是什么?地域选择看着一篇就够了

腾讯云服务器地域怎么选择&#xff1f;不同地域之间有什么区别&#xff1f;腾讯云哪个地域好&#xff1f;地域选择遵循就近原则&#xff0c;访客距离地域越近网络延迟越低&#xff0c;速度越快。腾讯云百科txybk.com告诉大家关于地域的选择还有很多因素&#xff0c;地域节点选择…

如何在Windows系统部署Plex影音站点并实现公网访问内网媒体库

文章目录 1.前言2. Plex网站搭建2.1 Plex下载和安装2.2 Plex网页测试2.3 cpolar的安装和注册 3. 本地网页发布3.1 Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1.前言 用手机或者平板电脑看视频&#xff0c;已经算是生活中稀松平常的场景了&#xff0c;特别是各…

NO5 蓝桥杯实践之矩阵键盘的使用(或许是一篇求助帖...)

1 任务 2 思路 视频中老师的思路写的代码过长&#xff0c;所以我想了个自己的思路&#xff0c;但是没完全跑出来&#xff0c;求大神指教&#xff01;&#xff01;&#xff01;&#xff01; 我的思路是首先将矩阵键盘的行和列对应的端口引脚分别存储在类似数组&#xff0c;然后…

【Python】快捷找到最大最小 N 个元素

heapq 简单数据结构取出最大最小N个元素复杂数据结构中取出最大最小N个元素代码解析&#xff1a;lambda Python 中有 heapq 模块可以快捷找到数组中最大最小的 N 个元素&#xff1b; heapq.nlargest(num, arr) # 从arr数组中取出最大num个元素 heapq.nsmallest(num, arr) # …

matplotlib-柱状图

日期&#xff1a;2024.03.14 内容&#xff1a;将matplotlib的常用方法做一个记录&#xff0c;方便后续查找。 # from matplotlib import pyplot as plt# 设置画布大小 plt.figure(figsize(20,8),dpi 300)# 全局设置中文字体 plt.rcParams[font.sans-serif] [Simhei]# 绘制三…

2024年1月粮油调味行业分析(TOP品牌/店铺/商品销售数据分析)

鲸参谋监测的某东1月份粮油调味市场销售数据已出炉&#xff01; 根据鲸参谋电商数据分析平台显示&#xff0c;今年1月份&#xff0c;某东平台上粮油调味品的销量约6200万件&#xff0c;环比上个月增长45%&#xff0c;同比去年下滑15%&#xff1b;销售额约25亿元&#xff0c;环…

宝妈在家带孩子还是出去工作?足不出户,两者如何兼顾?

我是电商珠珠 很多女性生完孩子之后&#xff0c;就在家当家庭主妇带孩子。部分人舍不得吃穿&#xff0c;把从老公那里要来的钱都给孩子买了东西。自己也想过要出去工作&#xff0c;但是空窗期太久&#xff0c;觉得自己什么都不会&#xff0c;没有企业会要。 前段时间有一个硕…

CUDA下载安装与配置

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 CUDA是什么&#xff1f; CUDA&#xff08;Compute Unified Device Architecture&#xff09;是由NVIDIA推出的并行计算平台和编程…

sqllab第十二关通关笔记

知识点&#xff1a; 一般字符型注入分类 单引号闭合双引号闭合这是一个双引号闭合 看界面又是一个输入框的注入;通过admin admin进行登录发现页面还是有回显 直接使用万能密码尝试 构造payload:usernameadminor11 没有任何反应&#xff1b;可能是没加注释符的关闭 构造user…

npm yarn 一起使用报错

项目记录&#xff0c;具有独特性&#xff0c;仅供参考 项目好好的运行&#xff0c;前一天装个测试工具包&#xff0c; 突然就不行了&#xff0c;卸载重装也不行&#xff0c;所有的项目都安装失败&#xff0c;新起一个项目也不行&#xff0c;有时候某个单独安装一个包可以&…

C# 连接neo4j数据库,包括非默认的neo4j默认库

官方文档没找见&#xff0c;自己在源码里面找到的 private string _dbHost "bolt://localhost:7687"; private string _dbUser "neo4j"; private string _dbPassword "******"; private IDriver? _driver;public CQLOperation(string _data…

采购代购系统独立站,接口采集商品上货

采购代购系统独立站的建设与商品上货接口的采集是一个综合性的项目&#xff0c;涉及前端开发、后端开发、数据库设计以及API接口的对接等多个环节。以下是一个大致的步骤和考虑因素&#xff1a; 一、系统规划与需求分析 明确业务需求&#xff1a;确定代购系统的核心功能&…

有没有图像转3D模型的软件?

云端地球是一款免费的在线实景三维建模软件&#xff0c;不需要复杂的技巧&#xff0c;只要需要手机&#xff0c;多拍几张照片&#xff0c;就可以得到完整的三维模型&#xff01; 无论是大场景倾斜摄影测量还是小场景、小物体建模&#xff0c;都可以通过云端地球将二维数据向三…

Windows系统下载安装Emby结合内网穿透实现公网访问本地影音网站

文章目录 1.前言2. Emby网站搭建2.1. Emby下载和安装2.2 Emby网页测试 3. 本地网页发布3.1 注册并安装cpolar内网穿透3.2 Cpolar云端设置3.3 Cpolar内网穿透本地设置 4.公网访问测试5.结语 1.前言 在现代五花八门的网络应用场景中&#xff0c;观看视频绝对是主力应用场景之一&…

Python实现BOA蝴蝶优化算法优化BP神经网络分类模型(BP神经网络分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 蝴蝶优化算法(butterfly optimization algorithm, BOA)是Arora 等人于2019年提出的一种元启发式智能算…

*地宫取宝c++

题目 输入样例1&#xff1a; 2 2 2 1 2 2 1输出样例1&#xff1a; 2输入样例2&#xff1a; 2 3 2 1 2 3 2 1 5输出样例2&#xff1a; 14 思路 题目说从入口开始&#xff0c;只能向右或向下行走到达右下角&#xff0c;类似“摘花生”这道题的模型。题目又说只有当格子里的宝…

Linux编程4.5 网络编程-套接字(Socket)

1、简介 Socket(套接字)是一种通讯机制&#xff0c;它包含一整套的调用接口和数据结构的定义&#xff0c;它给应用进程提供了使用如TCP/UDP等网络协议进行网络通讯的手段。 Linux中的网络编程通过Socket接口实现&#xff0c;Socket既是一种特殊的IO&#xff0c;提供对应的文件…

JS向指定位置添加元素

内容参考来源 splice方法 splice() 方法向/从数组中添加/删除项目&#xff0c;然后返回被删除的项目。 //在数组指定位置插入 var fruits ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(2, 0, "Lemon", "…

号外!全球首位AI软件工程师:Devin 来了

Cognition 实验室发布全球首位AI软件工程师 &#xff1a;Devin 目前Devin已经成功通过了顶尖 AI 公司的实际工程面试&#xff0c;并在 Upwork 上完成了真实工作。 Devin具有完全自主能力&#xff0c;可以通过使用自己的 Shell、代码编辑器和网络浏览器解决工程任务。 Devin是什…