Linux信号灯

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

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.hqwc.cn/news/541070.html

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

相关文章

防范服务器被攻击:查询IP地址的重要性与方法

在当今数字化时代&#xff0c;服务器扮演着重要的角色&#xff0c;为企业、组织和个人提供各种网络服务。然而&#xff0c;服务器也成为了网络攻击者的目标之一&#xff0c;可能面临各种安全威胁&#xff0c;例如DDoS攻击、恶意软件攻击、数据泄露等。为了有效地防范服务器被攻…

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]…

项目性能优化—性能优化的指标、目标

项目性能优化—性能优化的指标、目标 性能优化的终极目标是什么 性能优化的目标实际上是为了更好的用户体验&#xff1a; 一般我们认为用户体验是下面的公式&#xff1a; 用户体验 产品设计&#xff08;非技术&#xff09; 系统性能 ≈ 系统性能 快 那什么样的体验叫快呢…

java复健-接口的开发及参数校验

遇到的问题以及解决方案 Q1. 开发接口的流程 A1&#xff1a; 明确需求阅读接口文档思路分析开发测试 Q2. 开发时用到的技术 A2&#xff1a; LomBok&#xff1a;Data&#xff0c;自动为我们的实体类创建构造方法&#xff0c;set&#xff08;&#xff09;&#xff0c;get&am…

探索仿函数(Functor):C++中的灵活函数对象

文章目录 一、仿函数定义及使用二、仿函数与函数指针的区别三、仿函数与算法的关系四、仿函数的实践用例 在C编程中&#xff0c;我们经常需要对数据进行排序、筛选或者其他操作。为了实现这些功能&#xff0c;C标准库提供了许多通用的算法和容器&#xff0c;而其中一个重要的概…

GPU性能测试中的张量和矩阵运算

正文共&#xff1a;888 字 7 图&#xff0c;预估阅读时间&#xff1a;1 分钟 前面我们使用PyTorch将Tesla M4跑起来之后&#xff08;成了&#xff01;Tesla M4Windows 10AnacondaCUDA 11.8cuDNNPython 3.11&#xff09;&#xff0c;一直有个问题&#xff0c;那就是显存容量的问…

“CT每多做一次,患癌风险就增加43%”冲上热搜,CT到底还能不能做?

多家媒体报道某专家称做一次 CT 患癌风险提高 43%&#xff0c;这个让很多朋友感到很恐慌&#xff0c;甚至拒绝 CT 和 X 线检查&#xff0c;那么这种说法到底有道理吗&#xff1f; 先说结论&#xff0c; 这其实是该话题在传播过程中省略了很多关键信息&#xff0c;结果造成了误…

51单片机产生波特率的计算分析,为什么常见11.0592mhz

数据手册中的资料 参考短文&#xff0c;机械周期 对波特率产生的计算分析 经常看到的公式是 b a u d f s o c / 12 / ( 计时器溢出需的数量 ) 2 s m o d ∗ 16 baud \dfrac{f_{soc}/12/(计时器溢出需的数量)}{2^{smod}*16} baud2smod∗16fsoc​/12/(计时器溢出需的数量…

类似爱加速的代理ip软件有哪些?叫什么

和爱加速相似的换IP软件有很多&#xff0c;其中一些比较知名的包括&#xff1a;虎观代理、花生代理等&#xff0c;这些软件都可以提供类似的功能&#xff0c;帮助用户更换IP地址以保护网络隐私和加速网络访问等目的。用户可以根据自己的需求和喜好选择合适的换IP软件使用。 如果…

激活函数理解

前言 为什么神经网中非要有各种各样的激活函数&#xff1f;他们有什么用&#xff1f;没有他们会怎样&#xff1f;常见的激活函数有哪些&#xff0c;他们都有什么特点&#xff1f; 如果我们不运用激活函数&#xff0c;神经网络的输出信号将仅仅是一个简单的线性函数。线性方程…

#15封装vue3+el-table表格数据请求函数

目录 1、useTableData 2、util 3、使用 开箱即用&#xff0c;理解容易。 1、useTableData import { reactive } from vue import { getType } from /utils/utilsexport const useTableData (api) > {if (typeof api ! function && getType(api) ! Promise) {th…

Modbus -tcp协议使用第二版

1.1 协议描述 1.1.1 总体通信结构 MODBUS TCP/IP 的通信系统可以包括不同类型的设备&#xff1a; &#xff08;1&#xff09;连接至 TCP/IP 网络的 MODBUS TCP/IP 客户机和服务器设备&#xff1b; &#xff08;2&#xff09;互连设备&#xff0c;例如&#xff1a;在 TCP/IP…