UCOSII-信号量与信号量集

2023-05-16

文章目录

  • 一.前言
    • 1.任务间的同步
    • 2.事件
  • 二.信号量
    • 1.信号与信号量介绍
    • 2.信号量常用函数
    • 3.信号量使用流程(互斥信号量和信号量两种)
    • 4.互斥型信号量使用
    • 5.使用一般信号量做任务同步
  • 三.信号量集(事件标志组)
    • 1.信号量集概念
    • 2.信号量集的结构组成
    • 3.等待任务
    • 4.等待任务链表
    • 5.信号量集常用函数
    • 6.信号量集使用步骤*****
  • 四.总结

一.前言

1.任务间的同步

应用程序中的各个任务,必须通过彼此之间的有效合作,才能完成一项大规模的工作。因此在多任务合作工作的过程中,操作系统应该解决两个问题:一是各任务之间应该具有一种互斥关系,即对于某个共享资源,如果一个任务正在使用,则其他任务只能等待,直到请求资源被释放后才能使用。二是相关的任务的执行上要有先后次序,一个任务要等其他伙伴发来通知,或建立某个条件后才能继续执行。任务间的这种制约性的合作机制叫做任务间的同步。

2.事件

UCOSII系统中使用到的信号量、消息邮箱、消息队列来实现任务之间通信。统一称为事件。
两个任务通过事件通信的示意图:
在这里插入图片描述

二.信号量

1.信号与信号量介绍

使用信号量的最初目的是为了给共享资源设立一个标志。
信号量通常分为两种:信号信号量
信号只能取值为0或1,用于互斥任务之间的通信,用于那些只能一个任务使用的资源。信号量值大于1,可用于那些资源可以同时被几个任务所使用。调用释放信号量函数post(),信号量值加1,调用请求信号量函数pend(),信号量值减1。同时可以设置请求信号量的等待时限。
在这里插入图片描述

2.信号量常用函数

OSSemCreate();             //1.建立一个信号量*****
OSSemDel();                //2.删除一个信号量
OSSemPend();               //3.等待一个信号量*****
OSSemPendAbrot();          //4.取消等待
OSSemPost();               //5.释放或发出一个信号量*****
OSSemSet();                //6.强制设置一个信号量

其中主要用到的函数是创建,请求,发送。

3.信号量使用流程(互斥信号量和信号量两种)

定义信号量:

OS_EVENT * sem_mutex;		       //定义互斥型信号量指针(只能取值0或1)
OS_EVENT * sem_ordinary;		   //定义蜂鸣器信号量指针(取值大于1)

创建信号量:

sem_mutex=OSMutexCreate(2,&err);    //创建互斥型信号量sem_mutex,优先级为2
sem_ordinary=OSSemCreate(0);		    //创建信号量,信号量初始计数器值为0		 	

请求信号量:

OSMutexPend(sem_mutex,0,&err);  //请求信号量函数,等待时间为无限长
OSSemPend(sem_ordinary,0,&err); //请求信号量函数,等待时间为无限长

释放信号量:

OSMutexPost(sem_mutex);        //发送互斥型信号量
OSSemPost(sem_ordinary);       //发送信号量函数

4.互斥型信号量使用

u8 share_resource[]="share_resource";  //定义共享资源
//任务一的任务函数
void task1_task(void *p_arg)
{
   while(1)
   {
     OSMutexPend(sem_mutex,0,&err);  //请求信号量函数,等待时间为无限长
     printf("task1=%s\n",share_resource);
     /*******************任务1执行的代码**********************/
     OSMutexPost(sem_mutex);        //发送互斥型信号量
   }
}
//任务二的任务函数
void task2_task(void *p_arg)
{
   while(1)
   {
     OSMutexPend(sem_mutex,0,&err);  //请求信号量函数,等待时间为无限长
     printf("task2=%s\n",share_resource);
     /*******************任务2执行的代码**********************/
     OSMutexPost(sem_mutex);        //发送互斥型信号量
   }
}

可以看出,任务1和任务2共享了资源share_resource[],因此未来保障共享资源同一时刻只能被一个任务使用,因此要采用互斥型信号量做通信,每个信号开始前先请求信号量,(信号量变为0,另一个任务请求不到),任务执行结束后释放信号量(信号量值为1)。

5.使用一般信号量做任务同步

//任务一的任务函数
void task1_task(void *p_arg)
{
   u8 key;
   u8 err;
   while(1)
   {
     key=KEY_Scan(0);                //按键扫描
     if(key=WKUP_PRES)
     {
        OSSemPost(sem_ordinary);                               //发送信号量函数
       LCD_ShowxNum(192,50,sem_ordinary->OSEventCnt,3,16,0X80);//显示信号量的值
     }
     delay_ms(10);                  //延时10ms
   }
}
//任务二的任务函数
void task2_task(void *p_arg)
{
   u8 err;
   while(1)
   {
       OSSemPend(sem_ordinary,0,&err); //请求信号量函数,等待时间为无限长
       LCD_ShowxNum(192,50,sem_ordinary->OSEventCnt,3,16,0X80);//显示信号量的值
      LED1=!LED1;                      //LED翻转
      delay_ms(1000);                  //延时1s
   }
}

由上面可以看出,通过信号量sem_ordinary实现了任务1与任务2之间的同步,按键按下后任务1发送信号量,信号量计数加1,任务二每隔1S请求一次信号量,信号量值减1,减至0后无限等待

三.信号量集(事件标志组)

1.信号量集概念

有时候一个任务需要与多个事件同步,这个时候就需要使用事件标志组。事件标志组与事件之间有两种同步机制:“或”同步和“与”同步。
在UCOSII中事件标志组为OS_FLAG_GRP,如果需要使用事件标志组的时候需要将宏OS_CFG_FLAG_EN置1。
在这里插入图片描述

2.信号量集的结构组成

UCOSII把信号量集的功能分为两部分:标志组(存放了信号量集的所有信号)和等待任务链表(链表中的每个节点对应一个叫做OS_FLAG_NODE的结构,实质上就是等待任务控制块)。也就是说,UCOSII信号量集由一个标志组多个等待任务控制块组成。

标志组OSFlagFlags实际上就是一个位图,其长度可以在OS_CFG.H中定制,系统默认16位。该位图每一位对应一个信号量,位图的作用是接收和保存其他任务所发送来的信号量值,所以可以看做是输入信号暂存器
在这里插入图片描述
信号量集需要一个控制块,这个控制块叫做标志组OS_FLAG_GRP,OSFlagFlags是标志组的成员。标志组是一个结构体,具体如下:

typedef struct struct
{  
    INT8U         OSFlagType;      //标志是否为信号量集的标志
    void         *OSFlagWaitList;  //指向等待任务链表的指针
    OS_FLAGS      OSFlagFlags;     //输入信号量值列表
} OS_FLAG_GRP;

其中:
1.OSFlagFlags为核心成员;
2.OSFlagType为信号量集标识,其值固定为OS_EVENT_TYPE_FLAG;
3.OSFlagWaitList指针有两种用途,主要是指向一个链表,该链表中存放了给信号量集的全部等待任务。
OS_FLAG_GRP如下图:
在这里插入图片描述

3.等待任务

等待任务就是那些以及向信号量集发出了请求操作的任务。
信号量集等待任务的操作比较复杂,等待任务必须完成以下两个操作:
1.在多个信号量的输入中挑选等待任务感兴趣的输入(过滤)。
2.把挑选出来的输入按照等待任务所希望的逻辑来运算,以得出输出(与或)。
这里定义了一个OSFlagNodeWaitType变量来指定对筛选出来的信号的逻辑运算。可选值和意义见下表:
在这里插入图片描述
OSFlagFlags,OSFlagNodeFlags,OSFlagNodeWaitType三者之间的关系如下图所示:
在这里插入图片描述

4.等待任务链表

信号量集用双向链表来组织等待任务,每一个等待任务都是该链表中的一个节点(Node)。标志组OS_FLAG_GRP的成员OSFlagWaitList就指向了信号量集的这个等待任务链表。
等待任务链表与标志组的整个信号量集示意图如下所示:
在这里插入图片描述

5.信号量集常用函数

OSFlagCreate();         //创建信号量集*****
OSFlagDel();            //删除信号量集
OSFlagPend();           //请求信号量集*****
OSFlagPendAbort();      //取消等待信号量集
OSFlagPendGetFlagsRdy();//获取使任务就绪的事件标志
OSFlagPost();           //发送信号量集*****

6.信号量集使用步骤*****

1.定义信号量集

OS_FLAG_GRP * flags;	     //定义信号量集flags

2.创建信号量集

flags=OSFlagCreate(0,&err); //创建信号量集,初始值为0		  

3.请求信号量集

//在任务1中进行信号量集的请求,并根据请求到的情况进行操作
void uart1_task(void *pdata)
{
	u8 err;
	u16 flag_receive=0;
	while(1)
  {
        flag_receive=OSFlagPend(flags,0X0003,OS_FLAG_WAIT_SET_ALL+OS_FLAG_CONSUME,0,&err);//请求信号量集第0位,第1位,两位全部接收到1才可跳过。OS_FLAG_CONSUME表示请求到信号之后清0处理
		if(flag_receive==1)printf("KEY0 DOWN  \n"); //只接收到了第0位
		if(flag_receive==2)printf("KEY1 DOWN  \n"); //只接收到了第1位
		if(flag_receive==3)printf("KEY2 DOWN  \n"); //只接收到了第0位,第1位
		if(flag_receive==6)printf("KEY_UP DOWN  \n");//只接收到了第1位,第2位,但是此处第2位被屏蔽掉了,所以永远不会执行
	    delay_ms(50);
		//OSFlagPost(flags,0X001F,OS_FLAG_CLR,&err);  //全部信号量清零,如果不清零则flags的值一直存在,也就是全部post0。也可以在pend函数中加上消耗OS_FLAG_CONSUME,即
		//flag_receive=OSFlagPend(flags,0X0003,OS_FLAG_WAIT_SET_ALL+OS_FLAG_CONSUME,0,&err);//请求信号量集第0位,第1位,两位全部接收到1才可跳过
	};
}

4.发送信号量集

//在key_task任务中根据不同按键值发送不同的信号位
void key_task(void *pdata)
{
	u8 key=0;
	u8 err=0;
	while(1)
  {
    key=KEY_Scan(0);
		switch(key)
		{
			case 1: 
				OSFlagPost(flags,1,OS_FLAG_SET,&err);//将当前的KEY值作为信号量集发送出去,然后信号量集任务中就会收到(发送第0位)
		    break;
			case 2: 
				OSFlagPost(flags,2,OS_FLAG_SET,&err);//将当前的KEY值作为信号量集发送出去,然后信号量集任务中就会收到(发送第1位)
		    break;
			case 3: 
				OSFlagPost(flags,3,OS_FLAG_SET,&err);//将当前的KEY值作为信号量集发送出去,然后信号量集任务中就会收到(发送第0,1位)
		    break;
			case 4: 
				OSFlagPost(flags,8,OS_FLAG_SET,&err);//将当前的KEY值作为信号量集发送出去,然后信号量集任务中就会收到(发送第3位)
		    break;
			default:break;							
		}
		delay_ms(10);
	};
}

最终的实验现象:按下KEY2,串口打印KEY2 DOWN,按下KEY0和KEY1,串口打印KEY2 DOWN。
5.查询信号量集状态(备用)

#if OS_FLAG_QUERY_EN > 0u
OS_FLAGS  OSFlagQuery (OS_FLAG_GRP  *pgrp,   //待查询的信号量集的指针
                       INT8U        *perr    //错误信息
                      )
{
   ....................................................
}

6.删除信号量集

OS_FLAG_GRP *OSFlagDel(
                          OS_FLAG_GRP *pgrp,//待删除的信号量集指针
                          INT8U opt,INT8U *err;//错误信息
                      )

四.总结

1.信号量表明一个共享资源被使用情况的标志,该标志实质上是一个计数器,如果计数器的初值大于1,则叫做信号量,如果计数器的值只能为1或0,则叫做信号
2.能防止出现优先级反转的信号叫做互斥型信号量。
3.信号量集实现了多个信号量的组合功能,它是一个多输入多输出系统,使一个任务可以与多个任务进行同步。
4.信号量集的多个信号量输入值由标志组来存放,等待任务控制块对标志组中的输入信号进行过滤并实施逻辑运算,其结果就是等待任务所请求的信号量值。
5.每个信号量集都有一个等待任务链表,链表的每一个节点都通过任务控制块关联着一个任务。

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

UCOSII-信号量与信号量集 的相关文章

  • UCOSII中的任务切换原理介绍

    1 多任务的引入 之所以引入多任务 xff0c 主要在于提高程序运行的效率 多任务的过程 xff0c 能够有效地发挥交换式任务的运作效率 类似的 xff0c 由于一个任务里面也有瓶颈的地方 xff0c 为了把瓶颈的地方抠出来 xff0c 让
  • UCOSII学习---五、任务通信之信号量

    一 xff1a 信号量的理解 xff1a 信号量的本质是数据操作锁 xff0c 它本身不具有数据交换的功能 xff0c 而是通过控制其他的通信资源 xff08 文件 xff0c 外部设备 xff09 来实现进程间通信 xff0c 它本身只是
  • UCOSII-信号量与信号量集

    文章目录 一 前言1 任务间的同步2 事件 二 信号量1 信号与信号量介绍2 信号量常用函数3 信号量使用流程 xff08 互斥信号量和信号量两种 xff09 4 互斥型信号量使用5 使用一般信号量做任务同步 三 信号量集 事件标志组 1
  • UCOSII-消息邮箱与消息队列

    文章目录 一 事件控制块及事件处理函数1 等待任务列表2 事件控制块的结构3 操作事件控制块的函数4 空事件控制块列表 二 消息邮箱1 消息邮箱介绍2 消息邮箱操作步骤 三 消息队列1 消息指针数组2 队列控制块3 消息队列的操作流程 四
  • STM32上使用UCOSII--消息队列和信号量集

    有关UCOS任务的介绍 xff1a STM32上使用UCOSII 任务 有关UCOS信号量和邮箱的介绍 xff1a STM32上使用UCOSII 信号量和邮箱 一 消息队列 使用消息队列可以在任务之间传递多条消息 消息队列由三个部分组成 x
  • ucosii中消息队列、消息邮箱、信号量的区别

    1 用信号量进行行为同步时 xff0c 只能提供同步的时刻信息 xff0c 不能提供内容信息 若被控制方要求得到控制方的内容信息时 xff0c 可以使用消息邮箱或消息队列 2 但由于消息邮箱里只能存放一条消息 xff0c 所以使用消息邮箱进
  • UCOSII 消息队列、信号量集、软件定时器

    1 消息队列 xff1a 作用 xff1a 在任务之间传递多条信息 组成 xff1a 事件控制块 消息队列 消息 消息队列数据结构 队列控制块的结构定义 xff1a typedef struct os q struct os q OSQPt
  • 学习ucosii要用到的几本书和软件

    原帖地址 xff1a http bbs ednchina com BLOG ARTICLE 2020186 HTM 打算学习一个嵌入式操作系统 xff0c 研究了一下决定还是先研究一下ucosii xff0c 一方面权当学习C语言 xff0
  • ucosii消息队列使用

    ucosii消息队列简介 ucosii的消息队列源码定义在os q c文件 xff1b 接口全部声明在ucos ii h xff0c 总共有如下接口 xff1a span class token keyword void span span
  • rtthrea-ucosii-freertos三系统学习总结

    三系统基本功能对比 RT thread ucosii freertos 任务调度 抢占式 时间片式 xff08 多级队列位图调度 xff09 抢占式 xff08 纯位图调度 xff09 抢占式 时间片式 xff08 遍历列表调度 xff09
  • 基于UCOSII的RS485通信(STM32F107)

    一 实现效果 基于ucosii实时操作系统的RS485通信 xff0c 采用USART 43 DMA进行收发 xff0c 二 开发环境 开发工具 xff1a KEIL V5开发板 STM32f107RC采用方式 xff1a USART 43
  • UCOSII 使用笔记

    UCOS使用总结 1 UCOS 是抢占式系统 xff0c 换句话来说 xff0c 优先级高的能够被准时执行 xff0c 优先级低的很容易被高优先级抢占 xff0c 导致执行任务延迟 2 UCOS一般为64个优先级 xff0c 有些可以到25
  • 从零开始学习UCOSII操作系统4--任务管理

    从零开始学习UCOSII操作系统4 任务管理 1 重讲任务 1 任务可以是一个无限的循环 xff0c 也可以在一次执行完毕后被删除 这里需要注意的是 xff0c 任务的代码并不是真正的删除了 xff0c 而是UCOSII不再理会该任务代码
  • 从零开始学习UCOSII操作系统15--总结篇

    从零开始学习UCOSII操作系统15 总结篇 前言 xff1a 在大学的时候 xff0c 我们班级上面都有很多人觉得学习UCOSII 包括UCOSIII 是没什么厉害的 xff0c 因为很多人都喜欢去学习Linux操作系统 xff0c 但是
  • ucosII 信号量使用总结(举例讲解)

    概述 信号量用于 xff1a 1 控制共享资源的使用权 xff08 满足互斥条件 xff09 2 标志某时间的发生 3 使2个任务的行为同步 OSSemCreate 赋初值 OSSemCreate INT16U cnt xff0c cnt为
  • UCOSII之项目实战总结

    电子IT行业博大精深 xff0c 没有人能够用笔记本天天记录自己所学的知识 xff0c 于是乎 xff0c 撰写博客就成了每个 IT民工 的专长 再者 xff0c 写一篇博客 xff0c 其意义与不但记录了自己所需的知识 xff0c 更提高
  • ucosII的书籍

  • UCOSII里面为什么调用OS_ENTER_CRITICAL()或OS_EXIT_CRITICAL()会出错,出错信息为:undeclared identifier `cpu_sr‘

    可以观察到OSTickISR Init 函数内部调用了OS ENTER CRITICAL 和OS EXIT CRITICAL 并且 1 该OSTickISR Init 函数所在的 C文件包含了includes h文件 include inc
  • windows下的gcc使用

    文章目录 缘起 正文 安装gcc 使用gcc来编译c语言程序 直接编译生成 exe文件 在cmd里面使用gcc编译器编译c文件流程 利用gcc编译多个c语言源文件 第一步建立文件 编译文件 链接 运行 gcc基本参数 参考文献 缘起 在wi
  • uCOSii中的互斥信号量

    uCOSii中的互斥信号量 一 互斥型信号量项管理 MUTUAL EXCLUSION SEMAPHORE MANAGEMENT OSMutexAccept 无条件等待地获取互斥型信号量 OSMutexCreate 建立并初始化一个互斥型信号

随机推荐

  • imu噪声的建模理解

    imu噪声的建模理解 前言一 IMU噪声模型简述二 两篇文档中关于imu噪声模型的描述三 Allan standard deviation AD 读取imu内参 前言 参考An introduction to inertial naviga
  • Airsim环境下的px4硬件在环仿真

    文章目录 前言1 Airsim和硬件在环介绍2 硬件在环测试的准备工作 xff08 硬件和软件 xff09 2 1 usb ttl转接线的制作 xff1a 2 2 px4的ttl端口波特率设置 3 硬件在环测试过程中的问题4 AirSim
  • 使用Kalibr标定相机和IMU(ZED+px4)外参

    提示 xff1a 文章写完后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 使用Kalibr标定相机和IMU xff08 ZED 43 px4 xff09 外参 前言一 Kalibr介绍二 CAM IMU外参标定1
  • php curl digest,php curl with digest返回两个响应

    如果对标头使用 I选项 则看起来curl具有相同的行为 xff1a curl I digest u root somepassword http localhost digest test 收益 xff1a HTTP 1 1 401 Aut
  • SET PASSWORD FOR ‘root‘@localhost=PASSWORD(‘XXXX‘);报错

    原因 xff1a 数据库版本较高 老版本 SET PASSWORD FOR root 64 localhost 61 PASSWORD XXXXX 新版本 SET PASSWORD FOR root 64 localhost 61 XXXX
  • ROS学习笔记之小乌龟跟随

    ROS学习笔记之小乌龟跟随 说明 xff1a 整个案例是跟着赵虚左老师的视频和文档资料学习的 xff0c 特此感谢赵虚左老师和Autolabor官方 文档地址 视频地址 学习案例之前的预备知识 xff1a TF坐标变换 大体实现流程 xff
  • MPC,PID,LQR,DDP算法

    算法原理 xff1a
  • 对‘image_transport::ImageTransport::~Image Transport()’未定义的引用

    这是因为cmakelist文件没配置好 xff0c 一般的cmakelist文件配置如下 xff1a cmake minimum required VERSION 2 8 3 project first test pkg Compile a
  • 【VIO笔记(学习VINS的必备基础)】第六讲 视觉前端

    文章目录 前端工作的综述特征点提取 匹配和光流为什么需要角点角点的提取光流的计算光流的总结 关键帧与三角化关键帧三角化三角化程序实现 系列教程来自某学院 xff0c 侵权删除 学习完这一系列课程再去看VINS才能做到不吃力 xff0c 不然
  • windows开机自启动frp教程

    https wp gxnas com 12153 html
  • ubuntu20.08下获取realsense内参

    ubuntu20 08下使用realsense过程记录 介绍一 安装SDK1 注册公钥2 将服务器添加到存储库列表中3 安装库4 安装开发者和调试包5 测试SDK 二 下载realsense2 camera包1 下载包2 测试包3 激活相关
  • 深度视场角(Depth Field of View)

    深度视场角 Depth Field of View Realsense相机深度图的建立依赖双目立体成像原理 xff0c 其有效视场是左 右成像器视场的重叠部分 xff0c 如下图所示 顺带一提 xff0c 这张图不能用于计算双目相机深度成像
  • ROS: Publisher and Subscriber

    通过上一节编写ROS的第一个程序hello world xff0c 我们对ROS的整个编程开发过程有了基本的了解 xff0c 现在我们就来编写真正意义上的使用ROS进行节点间通信的程序 由于之前已经建好了catkin ws这样一个工作空间
  • phpStorm2018安装教程

    1 鼠标右击 PhpStorm 2018 2 3 压缩包选择 解压到PhpStorm 2018 2 3 2 双击打开解压后的 PhpStorm 2018 2 3 文件夹 3 鼠标右击 PhpStorm 2018 2 3 exe 选择 以管理
  • 学习Java第一个星期感受和收获

    最近在学习java xff0c 学了有一个星期 xff0c 说一说这个星期的收获和总结吧 xff01 首先我也是从一个小白做起 xff0c 这个星期学习了很多 xff0c 很多java基础知识 xff0c 我印象比较深刻的是基本数据类型和引
  • MySql知识体系总结(2021版)

    一 MySQL三层逻辑架构 MySQL的存储引擎架构将查询处理与数据的存储 提取相分离 下面是MySQL的逻辑架构图 xff1a 1 第一层负责连接管理 授权认证 安全等等 每个客户端的连接都对应着服务器上的一个线程 服务器上维护了一个线程
  • freertos与linux区别,μClinux、μC/OS-II、eCos、FreeRTOS和djyos操作系统的特点及不足-嵌入式系统-与非网...

    基于 STM 平台且满足实时控制要求操作系统 xff0c 有以下 5 种可供移植选择 分别为 Clinux C xff0f OS II eCos FreeRTOS 和都江堰操作系统 djyos 下面分别介绍这五种嵌入式操作系统的特点及不足
  • SM4加密算法原理以及C语言实现

    文章目录 一 算法原理描述1 密钥及密钥参量 xff1a 2 加密算法 3 解密算法 xff1a 4 密钥扩展算法 xff1a 二 C语言算法实现 h部分代码 xff1a c部分代码 xff1a 一 算法原理描述 SM4分组密码算法是一个迭
  • SIM900A GPRS无线通信

    文章目录 一 模块介绍1 基本概况2 GPRS通信开发说明 二 TCP连接实现及其源码1 TCP连接实现方法2 程序源码 xff08 基于MSP430F149单片机 xff09 1 main c2 Config h及Config c3 SI
  • UCOSII-信号量与信号量集

    文章目录 一 前言1 任务间的同步2 事件 二 信号量1 信号与信号量介绍2 信号量常用函数3 信号量使用流程 xff08 互斥信号量和信号量两种 xff09 4 互斥型信号量使用5 使用一般信号量做任务同步 三 信号量集 事件标志组 1