lv5 嵌入式开发-12 信号灯

目录

1 信号量/灯(semaphore)基本概念

2 信号量-P/V操作概念

3 三种信号灯

3.1 有名信号灯

3.1.1 打开

3.1.2 关闭

3.1.3 删除

3.2 无名信号灯

3.2.1 初始化

3.2.2 销毁

3.3 信号灯P操作

3.4 信号灯V操作

3.5 示例

3.5.1 有名信号示例

3.5.2 无名信号灯示例(逻辑同上)

3.5 System V 信号灯使用:

3.5.1 创建/打开信号灯

3.5.2 进行P - V操作

3.5.3 初始化/删除

3.5.4 System V IPC - 信号灯特点

3.5.5  System V信号灯使用步骤

3.6 System V信号灯示例


掌握:信号灯机制、信号灯初始化、打开/创建信号灯、信号灯-P操作、信号灯-V操作、信号灯、共享内存

1 信号量/灯(semaphore)基本概念

信号量代表某一类资源,其值表示系统中该资源的数量。

概念:是不同进程间或一个给定进程内部不同线程间同步的机制。类似我们的生产者和消费者场景。

类似之前讲过的条件变量。

信号量是一个受保护的变量,只能通过三种操作来访问

  •         初始化
  •         P操作(申请资源)
  •        V操作(释放资源)

2 信号量-P/V操作概念

P(S) 含义如下:if  (信号量的值大于0) {   申请资源的任务继续运行;信号量的值减一;}else {   申请资源的任务阻塞;} V(S) 含义如下:信号量的值加一;if (有任务在等待资源) {唤醒等待的任务,让其继续运行}

3 三种信号灯

信号灯也叫信号量,用于进程/线程同步或互斥的机制

信号灯的类型  

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

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

wait 相当于p操作,post相当于v操作 

3.1 有名信号灯

3.1.1 打开

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

3.1.2 关闭

int sem_close(sem_t *sem);

3.1.3 删除

int sem_unlink(const char* name);

3.2 无名信号灯

3.2.1 初始化

int sem_init(sem_t *sem, int shared, unsigned int value);

 参数:

sem:需要初始化的信号灯变量

shared: shared指定为0,表示信号量只能由初始化这个信号量的进程使用,不能在进程间使用,linux 不支持进程间同步。0 – 线程间   1 – 进程间  

Value:信号量的值

3.2.2 销毁

int sem_destroy(sem_t* sem);

成功时返回0,失败时返回EOF  

sem  指向要操作的信号量对象

3.3 信号灯P操作

int sem_wait(sem_t *sem);

成功时返回0,失败时返回EOF  

sem  指向要操作的信号量对象

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

3.4 信号灯V操作

int sem_post(sem_t *sem);

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

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

3.5 示例

3.5.1 有名信号示例

避免读写混乱:规定写资源初值为1,读资源初值为0。获取写入权限,后写-1,读+1,获取读权限后,读-1,写+1。

sem_r.c

#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>//删除信号,以免程序退出(ctrl+c) 重新打开无法开启
void delsemfile(int sig){sem_unlink("mysem_r");exit(0);
}int main(){sem_t *sem_r,*sem_w;key_t key;int shmid;char *shmaddr;struct sigaction act;act.sa_handler = delsemfile;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaction(SIGINT,&act,NULL); //启用linux中信号退出回调函数delsemfile,用于删除信号量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_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);   //创建初值为0的读信号灯sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);   //创建初值为1的写信号灯while(1){sem_wait(sem_r);             //P操作,获取读资源,读资源-1printf("%s\n",shmaddr);sem_post(sem_w);             //V操作,写资源+1}
}

sem_w.c

#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>void delsemfile(int sig){sem_unlink("mysem_w");exit(0);
}int main(){sem_t *sem_r,*sem_w;key_t key;int shmid;char *shmaddr;struct sigaction act;act.sa_handler = delsemfile;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);  //创建信号灯,500个字节if(shmid<0){perror("shmget");return 0;}shmaddr = shmat(shmid,NULL,0);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);}}

3.5.2 无名信号灯示例(逻辑同上)

#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_unlink("mysem_w");sem_destroy(&sem_r);sem_destroy(&sem_w);exit(0);}void *readmem(void *arg){while(1){sem_wait(&sem_r);         //P操作printf("%s\n",shmaddr);sem_post(&sem_w);         //V操作}}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_r = sem_open("mysem_r",O_CREAT|O_RDWR,0666,0);
//   sem_w = sem_open("mysem_w",O_CREAT|O_RDWR,0666,1);sem_init(&sem_r,0,0);     //有名信号灯创建,读初值0sem_init(&sem_w,0,1);     //有名信号灯创建,写初值1pthread_t tid;pthread_create(&tid,NULL,readmem,NULL);   //创建线程while(1){sem_wait(&sem_w);    //P操作printf(">");fgets(shmaddr,500,stdin);sem_post(&sem_r);    //V操作}}

3.5 System V 信号灯使用:

3.5.1 创建/打开信号灯

int semget(key_t key, int nsems, int semflg);

参数:key:ftok产生的key值(和信号灯关联的key值)

          nsems:信号灯集中包含的信号灯数目

          semflg:信号灯集的访问权限,通常为IPC_CREAT |0666   IPC_EXCL

返回值:成功:信号灯集ID ; 失败:-1

3.5.2 进行P - V操作

int semop ( int semid, struct sembuf *opsptr, size_t nops);

功能:对信号灯集合中的信号量进行P - V操作

参数:semid:信号灯集ID        

          opsptr:   操作结构体

struct sembuf {short sem_num; // 要操作的信号灯的编号short sem_op;  // 1 : 释放资源,V操作// -1 : 分配资源,P操作  short sem_flg; // 0(阻塞),IPC_NOWAIT, SEM_UNDO
};//对某一个信号灯的操作,如果同时对多个操作,则需要定义这种结构体数组

           nops: 要操作的信号灯的个数 ,1个

返回值:成功 :0 ; 失败:-1

3.5.3 初始化/删除

int semctl ( int semid, int semnum, int cmd…/*union semun arg*/);

功能:信号灯集合的控制(初始化/删除)

参数:semid:信号灯集ID

           semnum: 要操作的集合中的信号灯编号

           cmd:

           GETVAL:获取信号灯的值,返回值是获得值

           SETVAL:设置信号灯的值,需要用到第四个参数:共用体

           IPC_RMID:从系统中删除信号灯集合

返回值:成功 0 ; 失败 -1

3.5.4 System V IPC - 信号灯特点

System V 信号灯是一个或多个计数信号灯的集合

可同时操作集合中的多个信号灯

申请多个资源时避免死锁

3.5.5  System V信号灯使用步骤

  • 打开/创建信号灯  
  • semget 信号灯初始化  
  • semctl P/V操作   semop
  • 删除信号灯  semctl

3.6 System V信号灯示例

#include <semaphore.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/sem.h>#define SEM_READ   0
#define SEM_WRITE  1union semun {int val;
};               void Poperation(int semid,int semindex){struct sembuf sbuf;sbuf.sem_num =  semindex;sbuf.sem_op = -1;sbuf.sem_flg = 0;semop(semid,&sbuf,1);}
void Voperation(int semid,int semindex){struct sembuf sbuf;sbuf.sem_num =  semindex;sbuf.sem_op = 1;sbuf.sem_flg = 0;semop(semid,&sbuf,1);}int main(){key_t key;char *shmaddr;int semid,shmid;key = ftok(".",100);if(key<0){perror("ftok");return 0;}semid = semget(key,2,IPC_CREAT |0666);if(semid<0){perror("semget");return 0;}shmid = shmget(key,500,IPC_CREAT |0666);shmaddr = shmat(shmid,NULL,0);union semun mysem;mysem.val = 0;semctl(semid,SEM_READ,SETVAL,mysem);mysem.val = 1;semctl(semid,SEM_WRITE,SETVAL,mysem);pid_t pid;pid = fork();if(pid<0){perror("fork");shmctl(shmid,IPC_RMID,NULL);semctl(semid,0,IPC_RMID);exit(-1);}else if(pid == 0){while(1){Poperation(semid,SEM_READ);printf("%s\n",shmaddr);Voperation(semid,SEM_WRITE);}}else{while(1){Poperation(semid,SEM_WRITE);printf(">");fgets(shmaddr,32,stdin);Voperation(semid,SEM_READ);}}
}

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

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

相关文章

Visual Studio 中将TAB设置为空格

将TAB设置为空格的原因很多&#xff0c;其中一点是为了统一不同编译器对TAB的解释&#xff0c;防止代码风格在不同编译器下不一致等。 在菜单中选择: 工具-->选项-->文本编辑器--->所有语言-->制表符 在窗口中选择&#xff0c;制表符大小和缩进大小都选为4&#xf…

10.1 国庆节小任务

目录 select实现服务器并发 服务器 客户端 运行现象 select实现服务器并发 服务器 #include<myhead.h>#define PORT 8888 //1024~49151 #define IP "192.168.1.104" //ifconfig查看本机IPint main(int argc, const char *argv[]) {//创建流式…

WiFi网络分析工具Airtool for Mac

Airtool是一款Mac平台上的WiFi网络分析工具&#xff0c;它可以帮助用户监测、分析和管理无线网络。 以下是Airtool的一些主要功能和特点&#xff1a; 实时监测&#xff1a;Airtool可以实时监测当前Mac设备所连接的WiFi网络&#xff0c;包括网络速度、信号强度、连接状态等。信…

Spark SQL

Spark SQL 一、Spark SQL概述二、准备Spark SQL的编程环境三、Spark SQL程序编程的入口四、DataFrame的创建五、DataFrame的编程风格六、DataSet的创建和使用七、Spark SQL的函数操作 一、Spark SQL概述 Spark SQL属于Spark计算框架的一部分&#xff0c;是专门负责结构化数据的…

NIO基础

nio : non-blocking io 非阻塞IO 1. 三大组件 1.1 channel和buffer channel 有点像stream &#xff0c;他就是读写数据的双向通道&#xff0c;可以从channel将数据读入buffer&#xff0c;也可以将buffer的数据写入channel&#xff0c;之前的stream 要么输入&#xff0c;要么…

建筑能源管理(3)——建筑能源监管

为了全面落实科学发展观&#xff0c;提高建筑能源管理水平&#xff0c;进一步降低能源和水资源消耗、合理利用资源&#xff0c;以政府办公建筑和大型公共建筑的运行节能管理为突破口&#xff0c;建立了既有政府办公建筑和大型公共建筑运行节能监管体系&#xff0c;旨在提高政府…

28271-2012 米制超细牙螺纹 公差

声明 本文是学习GB-T 28271-2012 米制超细牙螺纹 公差. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了米制超细牙螺纹的公差和标记。 本标准适用于精密仪器和电子设备等领域的螺纹连接。 2 规范性引用文件 下列文件对于本文件…

windows server 2019 、win11安装docker desktop

Docker Desktop Docker Desktop是可以部署在windows运行docker的应用服务&#xff0c;其基于windos的Hyper-V服务和WSL2内核在windos上创建一个子系统(linux)&#xff0c;从而实现其在windows上运行docker。 前提条件 WSL 查看wsl是否安装 我们可以直接在 cmd 或 powershe…

MySql出错点

一、DDL 1.修改表&#xff0c;添加新的字段时&#xff0c;不要加引号 2.在修改表中字段的类型时&#xff0c;会发生数据截断。 像DATETIME 转化为 TIME 二、DML 1.插入和删除的注意点 2.可以通过 select 来协助插入 3.

Linux 基本语句_4_指针和函数

指针函数 顾名思义&#xff0c;即返回值为指针的函数 int * f (int n){int *p NULL;//空指针return p;//返回一个地址 }函数指针 指向函数的指针&#xff0c;每个函数都有自己的入口地址&#xff0c;函数指针专门指向这些地址#include <stdio.h>int max(int a, int b)…

【Linux】完美解决ubuntu18.04下vi不能使用方向键和退格键

今天在刚安装完ubuntu18.04&#xff0c;发现在使用vi命令配置文件时使用方向键并不能移动光标&#xff0c;而是出现一堆奇怪的英文字母&#xff0c;使用退格键也不能正常地删除内容&#xff0c;用惯了CentOS的我已经感觉到ubuntu没有centos用着丝滑&#xff0c;但是没办法&…

【C++】类和对象(中)

一、类的6个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。但是空类中并不是真的什么都没有&#xff0c;任何类在什么都不写的时候&#xff0c;编译器会自动生成以下 6 个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成…

5G消息发展的前景与挑战

随着5G技术的快速发展和普及&#xff0c;5G消息正逐渐成为全球通信领域的新焦点。 随着5G技术的快速发展和普及&#xff0c;5G消息正逐渐成为全球通信领域的新焦点。 5G消息发展呈现规模化、产业化趋势 自2020年4月国内三大运营商联合发布5G消息白皮书以来&#xff0c;已经过…

【C语言】通讯录系统实现 (保姆级教程,附源码)

目录 1、通讯录系统介绍 2、代码分装 3、代码实现步骤 3.1、制作菜单menu函数以及游戏运行逻辑流程 3.2、封装人的信息PeoInfo以及通讯录Contact结构体类型 3.3、初始化通讯录InitContact函数 3.4、增加联系人AddContact函数 3.5、显示所有联系人ShowContact函数 3.6、…

【Idea】idea、datagrip设置输入法

https://github.com/RikudouPatrickstar/JetBrainsRuntime-for-Linux-x64/releases/tag/jbr-release-17.0.6b829.5https://github.com/RikudouPatrickstar/JetBrainsRuntime-for-Linux-x64/releases/tag/jbr-release-17.0.6b829.5 下载后解压并重命名为 jbr, 然后替换对应 ide…

CTF-XSS

知识 例子 。2022 CNSS夏令营 To_be_Admin_Again_and_Again XSS攻击. 与admin有关, 可以尝试http://1.117.6.207:65005/admin, 显示Get out, HACKER! Only admin can see the flag!, 说明需要一个admin的验证, 这里想到获取admin的cookie. 每条留言会自动查看, 可以使用XS…

Python-Flask:编写自动化连接demo脚本:v1.0.0

主函数&#xff1a; # _*_ Coding : UTF-8 _*_ # Time : 13:14 # Author : YYZ # File : Flask # Project : Python_Project_爬虫 import jsonfrom flask import Flask,request,jsonify import sshapi Flask(__name__)# methods: 指定请求方式 接口解析参数host host_info[…

TSM动作识别模型【详解】

文章目录 本文使用的是somethingv2数据集&#xff0c;解压后是如下形式&#xff1b; 由于该压缩数据进行了分卷操作&#xff0c;需要合并后才能进行解压。首先我们将下面4个json文件剪贴到其他文件夹&#xff0c;只保留00-19的文件&#xff0c;然后在该文件夹下打开cmd&#xf…

模块化CSS

1、什么是模块化CSS 模块化CSS是一种将CSS样式表的规则和样式定义封装到模块或组件级别的方法&#xff0c;以便于更好地管理、维护和组织样式代码。这种方法通过将样式与特定的HTML元素或组件相关联&#xff0c;提供了一种更具可维护性、可复用性和隔离性的方式来处理样式。简单…

机器人制作开源方案 | 四轴飞行器

1. 概述 基于探索者搭建的模块化四轴飞行器研究平台&#xff0c;采用独特的设计方式&#xff0c;可实现在室内完成对四轴飞行器、无人机等运动控制的原理研究&#xff0c;以及学习飞行控制的原理知识。 2. 组装 请按照下图进行机架的组装。 整体图 请解压文末资料中的 /软件/Mi…