UCOS学习(七)——信号量详解

2023-05-16

信号量

  • 信号量简介
  • 信号量保护共享资源
      • 举个栗子:如果不使用信号量
      • 信号量解决公共资源问题
        • 创建信号量:
  • 信号量实现任务同步
  • 总结

信号量简介

信号量像是一种上锁机制,代码必须获得对应的钥匙才能继续执行,一旦获得了钥匙,也就意味着该任务具有进入被锁部分代码的权限。一旦执行至被锁代码段,则任务一直等待,直到对应被锁部分代码的钥匙被再次释放才能继续执行。
信号量用于控制对共享资源的保护,但是现在基本用来做任务同步用
信号量通常分为两种:二进制信号量和计数型信号量。
二进制信号量只能取0和1两个值,计数型信号量的信号量值大于1,计数型信号量的范围由OS_SEM_CTR决定,OS_SEM_CTR可以为8位,16位和32位,取值范围分别为:0255,065535和0~4294967295。
二级制信号量用于那些一次只能一个任务使用的资源,比如I/O设备,打印机计,数型信号量用于某些资源可以同时被几个任务所使用,比如一个缓存池有10个缓存块,那么同时最多可以支持10个任务来使用内存池
第一遍看是不是看不懂,小问题,只要了解到他如何使用就知道它是什么了。

信号量保护共享资源

举个栗子:如果不使用信号量

首先先看一下我的这两个任务,我们定义一个全局数组soure_array作为公共资源,我们在task1task2两个任务中都使用了soure_array这个资源:
任务一,将数据复制到soure_array数组,并且打印出来。

//公共资源数组
char soure_array[40];
//led0任务函数
void led0_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	char task1_array[] = "task1_suning!";
	while(1)
	{
	    printf("任务一:\r\n");
		LED0 = !LED0;
		memcpy(soure_array,task1_array,sizeof(task1_array));
		delay_ms(200);
		printf("%s\r\n\r\n",soure_array);
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);
	}
}

//led1任务函数
void led1_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	char task2_array[] = "task2_runing!";
	while(1)
	{
		printf("任务二:\r\n");
		LED1 = !LED1;
		memcpy(soure_array,task2_array,sizeof(task2_array));
		delay_ms(200);
		printf("%s\r\n\r\n",soure_array);
        OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);
	}
}

运行结果:
请添加图片描述
我们期待的运行结果是任务一输出一次,任务二输出一次。
我们会发现这并不是我们想要的运行结果,这是因为任务二和任务一在同一时间占用了soure_array这个资源,如何解决呢?使用信号量就可以了。

信号量解决公共资源问题

首先我们得了解一下函数:
在这里插入图片描述
我们常用的呢就是标红的三个函数。

创建信号量:

1.创建信号量结构体

//1.创建信号量结构体
OS_SEM my_sem;

2.使用OSSemCreate()建立一个信号量
在开始任务中创建:

void  OSSemCreate (OS_SEM      *p_sem,  //全局信号量,就是刚才定义的信号量结构体
                   CPU_CHAR    *p_name, //信号量的名字
                   OS_SEM_CTR   cnt,    //cnt=1,二级制信号量,cnt>1,计数型信号量
                   OS_ERR      *p_err)  //错误码

2.信号量的使用
主要用到一下两个函数OSSemPend()OSSemPost()

//等待一个信号量
OS_SEM_CTR  OSSemPend (OS_SEM   *p_sem,  //信号量结构体指针
                       OS_TICK   timeout,//等待信号量的时间(时钟节拍数), 为0会一直等待信号量
                       OS_OPT    opt,    /*用于设置是否阻塞模式:
                                            OS_OPT_PEND_BLOCKING     指定信号量无效时,任务挂起等待信号量
                                            OS_OPT_PEND_NON_BLOCKING   信号量无效直接返回
                                         */
                       CPU_TS   *p_ts,   //时间戳,记录信号量的时刻,p_ts=NULL时无时间戳
                       OS_ERR   *p_err)  //错误码
//释放或者发送一个信号量
OS_SEM_CTR  OSSemPost (OS_SEM  *p_sem, //信号量结构体指针
                       OS_OPT   opt,   /*选择信号量发送的方式
                                         OS_OPT_POST_1 仅向等待该任务量的优先级最高的任务发送
                                         OS_OPT_POST_ALL 向等待该信号量的所有任务发送
                                         OS_OPT_POST_NO_SCHED 该选项禁止在本函数中执行任务调度
                                         */
                       OS_ERR  *p_err)//错误码

3.更改后的任务代码如下:

//led0任务函数
void led0_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	char task1_array[] = "task1_suning!";
	while(1)
	{
	  printf("任务一:\r\n");
		LED0 = !LED0;
	OSSemPend(&my_sem,0,OS_OPT_PEND_BLOCKING,NULL,&err);//等待信号量直到不为0
		memcpy(soure_array,task1_array,sizeof(task1_array));
		delay_ms(200);
		printf("%s\r\n\r\n",soure_array);
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延时1s
	OSSemPost(&my_sem,OS_OPT_POST_1,&err);//释放信号量
	}
}

//led1任务函数
void led1_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	char task2_array[] = "task2_runing!";
	
	while(1)
	{
		printf("任务二:\r\n");
		LED1 = !LED1;
	OSSemPend(&my_sem,0,OS_OPT_PEND_BLOCKING,NULL,&err);//等待信号量不为0
		memcpy(soure_array,task2_array,sizeof(task2_array));
		delay_ms(200);
		printf("%s\r\n\r\n",soure_array);
        OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延时1s
     OSSemPost(&my_sem,OS_OPT_POST_1,&err);//释放一个信号量
	}
}

4.运行结果
这样就达到了我们想要的效果:
请添加图片描述
我们可以分析它的执行过程:

  1. 任务二等待到信号量,打印,任务二发送信号量
  2. 任务一等待到信号量,打印,任务一发送信号量
  3. 任务二等待到信号量…

如此循环,就可以解决在两个或者多个任务使用同一个资源时出错的问题了。
下面我们在介绍一种信号量的应用:

信号量实现任务同步

首先我么要知道任务同步是什么,就是一个任务每执行一次,另外一个任务也跟着执行一次。这两个任务就算同步,用信号量来实现也是非常简单的:
前面都一样,就是创建任务,创建信号量

//KEY任务函数
void key_task(void *p_arg)
{
	OS_ERR err;
	u8 key = 0;
	p_arg = p_arg;
	while(1)
	{
		key = Key_Scan(0);
		if(key == Short_Press)//按下按键
		{
			LED0 = !LED0;
			printf("任务一:\r\n");
            OSSemPost(&my_sem,OS_OPT_POST_1,&err);//发送一个信号量
			printf("当前信号量:%d\r\n\r\n",my_sem.Ctr); //打印信号量数值
		}
		OSTimeDlyHMSM(0,0,0,10,OS_OPT_TIME_PERIODIC,&err);//延时10ms
	}
}

//led1任务函数
void led1_task(void *p_arg)
{
	OS_ERR err;
	p_arg = p_arg;
	while(1)
	{
		OSSemPend(&my_sem,0,OS_OPT_PEND_BLOCKING,NULL,&err);
		LED1 = !LED1;
		printf("任务二:\r\n");
		printf("当前信号量:%d\r\n\r\n",my_sem.Ctr);
		OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延时1s
	}
}

我们看一下运行结果:
请添加图片描述
当我连续按下两次按键之后,任务一发送两次信号量,我们发现信号量数值从0变化到2;然后任务二等待信号量两次,将信号量数值从2变化到0;最终效果就是任务一执行几次,任务二就执行几次。

总结

学过这个之后,我还是有很多问题的,希望有大佬帮我解解惑:
1.在信号量实现保护资源实验中,删除OSTimeDlyHMSM(0,0,1,0,OS_OPT_TIME_PERIODIC,&err);//延时1s这个延时,任务执行还是正常的,任务一任务二依次执行,这个不是很理解。
2.二进制信号量和计数信号量的主要区别和在什么情况使用不是很清楚。
希望我的文章可以让你学会信号量,下次见!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

UCOS学习(七)——信号量详解 的相关文章

  • UCOS的事件有:信号量,消息邮箱,消息队列,信号量集

  • linux与freertos区别,谈谈uCOS和freeRTOS这两种实时系统的结构以及编程思想

    距离上次总结 xff0c 已经过去有差不多半年了 xff0c 最近又到了自己半年一次的总结了 首先说说自己的编程风格的变化 xff0c 在上一篇 第三篇文 中提到的数据结构 配置文件结构 预编译结构 xff0c 目前已经逐渐适应 xff0c
  • ucos-ii 的任务调度原理和实现

    ucosii 任务调度和原理 1 ucos ii 任务创建与任务调度 1 1 任务的创建 当你调用 OSTaskCreate 进行任务的创建的时候 xff0c 会初始化任务的堆栈 保存cpu的寄存器 创建任务的控制块 xff08 OS TC
  • UCOS-III

    一 UCOSIII 简介 UCOSIII 是一个可裁剪 可固化 可剥夺 的多任务系统 xff0c 没有任务数目的限制 xff0c 是 UCOS 的第三代内核 xff0c UCOSIII 有以下几个重要的特性 xff1a 可剥夺多任务管理 x
  • 白话----之UCOS 信号量和邮箱

    总体理解 xff1a 两个任务需要共同访问一个共同的资源 xff0c 来切换或跳到不同的动作执行 这就产生信号量 两个任务 需要根据不同的按键选择 xff0c 来执行不同的动作 xff0c 产生邮箱 信号量和邮箱 我通过一个例子来学习的 希
  • 推荐ucos-II 3本参考书 经典

    在这里给大家推荐三本学习ucos的必看书籍 1 xff08 比较难买 xff09 嵌入式实时操作系统uc os II教程 西安电子科技大学出版 这本书对UCOS的源代码分析的非常清楚 比作者原著 在某种程度上要好 xff0c 这本书对关键的
  • uCOS/FreeRTOS任务创建的两种模式

    在我们使用uCOS FreeRTOS编写代码时 xff0c 首先要面临的一个问题是怎样创建任务并启动整个系统 一般来说 xff0c 我们会有两种不同的方式 这两种方式不仅适用于uCOS FreeRTOS xff0c 同时也适用于其它RTOS
  • UCOS-II任务间通信(信号量、邮箱、消息队列)

    保护任务之间的共享数据和提供任务之间的通讯方法 xff1a 利用宏OS ENTER CRITICAL 和OS EXIT CRITICAL 来关闭和打开中断 xff0c 这可以用于多任务或者任务和ISR共享某些数据时可以采用这种方法 利用OS
  • uCOS消息队列相关函数的理解

    OSQCreate xff1a 创建消息队列函数 有四个入口参数 xff1a 消息队列指针 xff1b 消息队列名称 xff1b 消息队列大小 xff08 不能为0 xff09 xff1b 返回错误类型 函数过程 xff1a 首先进行安全检
  • Huawei LiteOS与freeRTOS、Ucos主流嵌入式操作内核的区别

    LiteOS与freeRTOS Ucos主流嵌入式操作内核的区别 云社区 华为云
  • ucos iii 任务栈使用率统计方法

    第一步 使能任务统计功能 修改文件 os cfg h中的 OS CFG STAT TASK STK CHK EN宏 span class token comment TASK MANAGEMENT span span class token
  • UCOS-II任务设计

    UCOS II任务设计 任务函数的结构 xff1a 在用户任务函数中 xff0c 必须包含至少一次对操作系统服务函数的调用 xff0c 否则比其优先级低的任务将无法得到运行的机会 xff0c 这是用户任务与普通函数的明显区别 任务函数按照执
  • UCOS II 中信号量的使用

    UCOS II 中信号量的使用 UCOS II 中信号量的使用1 声明信号量2 创建信号量3 请求信号量4 发送信号量5 删除信号量 UCOS II 中信号量的使用 1 声明信号量 例如 xff1a OS EVENT Fun semp 声明
  • UCOS学习(三)——任务管理基础

    大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的大二学生 最近开始学习UCOS操作系统 xff0c 后面会更新一些关于UCOS学习笔记 今天学习了任务管理基础知识 感谢你的阅读 xff0c 不对
  • 从 C51+uCos-II 近距离了解操作系统任务切换原理

    前言 从 C51 43 uCos II 简单介绍下任务切换的原理 方便大家更形象的理解多任务怎么切换 为后续写 x86 43 Linux 任务切换做铺垫练手吧 参考资料如下 xff1a uCos II 源码 单片机原理与应用及 C51 编程
  • (转)ucos的事件 任务的通讯和同步 信号量 互斥量 消息邮箱 消息队列

    这会想了想 xff0c 在复习资料后 xff0c 最后再做个核心代码分析 ucos中使用信号量 消息邮箱 消息队列 xff0c 这些数据结构来作为通信中间媒介 这些数据结构会影响任务的程序流程 xff0c 因此也叫做事件 一 信号量 是进行
  • UCOS II两个任务的模板

    芯片lm3s9b92 include lt includes h gt include 34 utils uartstdio h 34 Application tasks 优先级 define TASK2 PRIO 11 define ta
  • cpu.h-栈的宏定义-满减栈

    常常两两相对的东西 整一起后有点记不住 就写下来 cpu h中有宏定义使用哪种栈 define OS STK GROWTH 1 Stack grows from HIGH to LOW memory on ARM 栈的四种 满栈 满 字表示
  • UCOS2的文件目录

    想着闲着也是闲着 把之前学习ucos2源码的笔记整理一下 复盘一次 总结内容将其写为博客作为学习的输出 一 为什么要学RTOS或者IOTOS 我在大一时 开始进入实验室接触单片机 摸爬滚打的参加了几次比赛 也因此入了嵌入式的坑 大三时开始思
  • ucos-ii嵌入式操作系统任务调度(一)----任务调度的过程及实现原理

    先给自己打个广告 本人的微信公众号正式上线了 搜索 张笑生的地盘 主要关注嵌入式软件开发 股票基金定投 足球等等 希望大家多多关注 有问题可以直接留言给我 一定尽心尽力回答大家的问题 二维码如下 一 概念 在单片机裸机程序中 我们以函数为最

随机推荐

  • 阿里云在线扩容磁盘,最简化,但不一定适用你的ECS版本

    在扩展系统盘扩展分区和文件系统前 xff0c 请提前完成以下工作 已创建快照备份数据 为防止操作失误导致数据丢失 xff0c 建议您操作前使用快照备份数据 若尚未创建快照 xff0c 请参见创建快照 已扩容云盘 若尚未扩容 xff0c 请参
  • AD学习笔记(二)原理图库以及原理图绘制

    文章目录 AD学习笔记第二讲 原理图库以及原理图绘制一 认识原理图二 原理图库绘制三 原理图绘制1 原理图纸的操作2 原理图库的调用放置3 导线及网络标识的添加4 原理图可读性优化处理5 原理图统一编号设置6 PCB封装名称的统一添加与管理
  • C工程与寄存器封装

    目录 一 C语言工程简介 二 启动代码分析 三 C语言实现LED 四 寄存器的封装方式 五 寄存器操作的标准化 六 流水灯 一 C语言工程简介 先将工程模板解压 include里是 h文件 src里是 c文件 start里面是 s启动文件
  • Python第三章函数

    函数 文章目录 函数一 函数基础1 参数2 拆分参数列表3 参数传递位置传递地址传递传对象引用 4 函数返回值5 变量的作用域局部变量全局变量nonlocal关键字 7 包8 猴子补丁9 python标准库的应用1 random模块2 ti
  • 无显示器怎么玩树莓派

    无显示器怎么玩树莓派 文章目录 无显示器怎么玩树莓派 前言一 给树莓派烧系统二 设置WiFi及ssh端口三 远程连接四 注意事项 前言 很多时候我们在使用树莓派的时候身边都没有显示器 xff0c 关于这个问题 xff0c 我也十分苦恼 xf
  • ROS智能车定位导航仿真(Gazebo搭建赛道)

    ROS智能车定位导航仿真 xff08 Gazebo搭建赛道 xff09 前言一 ROS仿真功能包下载二 安装运行所需的插件三 racecar功能包编译四 测试程序运行五 运行功能包赛道六 注意事项 前言 Ubuntu版本 xff1a 18
  • 阿木实验室PX4开发课程整理

    1 1 xff1a alt 43 ctrl 43 t 打开终端 cd Desktop 进入到桌面目录 cd 返回上次访问目录 cd 返回上一目录 gedit circular cpp 进入某文件 roscd px4 control 进入文件
  • Java并发编程—CompletableFuture的异步执行案例

    在博主前几篇博客中 xff0c https blog csdn net qq 52545155 article details 128167519 spm 61 1001 2014 3001 5501 xff0c 给大家分享了关于多线程中异
  • 手写rtos的第一天

    唉 xff0c 不自不觉已经大三了啊 xff0c 大二的智能车生涯已经结束了 xff0c 不得不说 xff0c 省二是我不太能接受的 结果 xff0c 虽然嘴上说着没啥 xff0c 真正面对全省排名的时候 xff0c 内心的寂寥真的难以言表
  • FreeRTOS任务(动态)创建与删除(一)

    FreeRTOS学习总结 文章目录 前言一 浅浅了解二 创建任务1 动态任务创建2 动态实践 总结 前言 听朋友说 xff0c FreeRTOS很好用 xff0c 就在无聊的上网课期间浅学一下 提示 xff1a 以下是本篇文章正文内容 xf
  • FreeRTOS操作系统队列及队列API函数(五)

    FreeRTOS学习总结 文章目录 前言一 队列功能1 数据存储2 多任务访问3 出队阻塞4 入队阻塞 二 队列操作过程图示1 创建队列2 向队列发送第一个消息3 向队列发送第二个消息4 从队列中读取消息 二 API函数1 队列创建函数2
  • php导出word文件,打开损坏或者乱码

    下载Word文件 fileinfo 61 pathinfo fullname ob end clean header 39 Content type application x 39 fileinfo 39 extension 39 hea
  • FreeRTOS操作系统优先级翻转问题(八)

    FreeRTOS总结 文章目录 前言一 浅浅了解优先级翻转二 模拟 优先级翻转实验1 代码 总结 前言 在使用二值信号量的时候会遇到很常见的一个问题 优先级翻转 xff0c 优先级翻转在可剥夺 内核中是非常常见的 xff0c 在实时系统中不
  • 伽马分布,指数分布,卡方分布三者关系

    1 伽马分布是一个连续概率分布 xff0c 具有两个参数 alpha 和 lambda xff0c 记为
  • 数据结构 马踏棋盘 栈应用 C++

    include lt iostream gt 包含其它头文件 using namespace std const int StackInitSize 61 10 const int StackInc 61 10 typedef int SE
  • STM32智能小车------红外遥控

    文章目录 一 原理讲解1 实物图2 工作原理 xff1a 3 接线 xff1a 二 软件驱动代码1 驱动函数2 获取键值 总结最终效果 大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的普通大学生
  • UCOS学习(一)——前后台系统、RTOS系统

    大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的大二学生 最近开始学习UCOS操作系统 xff0c 后面会更新一些关于UCOS学习笔记 今天了解了UCOS操作系统 xff0c 总结一下知识点 感
  • UCOS学习(二)——UCOS-II、UCOS-III移植到STM32F103

    大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的大二学生 最近开始学习UCOS操作系统 xff0c 后面会更新一些关于UCOS学习笔记 今天学习了如何将UCOS II和UCOS III移植到ST
  • UCOS学习(三)——任务管理基础

    大家好哇 xff01 我是小光 xff0c 嵌入式爱好者 xff0c 一个想要成为系统架构师的大二学生 最近开始学习UCOS操作系统 xff0c 后面会更新一些关于UCOS学习笔记 今天学习了任务管理基础知识 感谢你的阅读 xff0c 不对
  • UCOS学习(七)——信号量详解

    信号量 信号量简介信号量保护共享资源举个栗子 xff1a 如果不使用信号量信号量解决公共资源问题创建信号量 xff1a 信号量实现任务同步总结 信号量简介 信号量像是一种上锁机制 xff0c 代码必须获得对应的钥匙才能继续执行 xff0c