μC/OS-II 任务的同步与通信 --- 信号量
任务间通信
系统中的多个任务在运行时,经常需要互相无冲突地访问同一个共享资源,或者需要互相支持和依赖,甚至有时还要互相加以必要的限制和制约,才保证任务的顺利运行。因此,操作系统必须具有对任务的运行进行协调的能力,从而使任务之间可以无冲突、流畅地同步运行,而不致导致灾难性的后果。
与人们依靠通信来互相沟通,从而使人际关系和谐、工作顺利的做法一样,计算机系统是依靠任务之间的良好通信来保证任务与任务的同步的。
举例说明
两个任务:任务 A 和任务 B,它们需要通过访问同一个数据缓冲区合作完成一项工作,任务 A 负责向缓冲区写入数据,任务 B 负责从缓冲区读取该数据。显然,当任务A还未向缓冲区写入数据时(缓冲区为空时),任务 B 因不能从缓冲区得到有效数据而应该处于等待状态,只有等任务 A 向缓冲区写入了数据之后,才应该通知任务 B 去取数据。
事件控制块
为了把描述事件的数据结构统一起来,μC/OS-II 使用叫做事件控制块 ECB 的数据结构来描述诸如信号量、邮箱(消息邮箱)和消息队列这些事件。事件控制块中包含包括等待任务表在内的所有有关事件的数据。
typedef struct
{
INT8U OSEventType; //事件的类型
INT16U OSEventCnt; //信号量计数器
void *OSEventPtr; //消息或消息队列的指针
INT8U OSEventGrp; //等待事件的任务组
INT8U OSEventTbl[OS_EVENT_TBL_SIZE];//任务等待表
} OS_EVENT;
把一个任务置于等待状态要调用 OS_EventTaskWait( ) 函数。该函数的原型为:
void OS_EventTaskWait (
OS_EVENT *pevent //事件控制块的指针
);
函数 OS_EventTaskWait ( ),将在任务调用函数 OS×××Pend( ) 请求一个事件时,被 OS×××Pend( ) 所调用。
空事件链表
在 μC/OS-II 初始化时,系统会在初始化函数 OSInit( ) 中按应用程序使用事件的总数 OS_MAX_EVENTS(在文件OS_CFG.H中定义),创建 OS_MAX_EVENTS 个空事件控制块并借用成员 OSEventPtr 作为链接指针,把这些空事件控制块链接成一个单向链表。由于链表中的所有控制块尚未与具体事件相关联,故该链表叫做空事件控制块链表。
信号量的操作
在使用信号量之前,应用程序必须调用函数 OSSemCreate( ) 来创建一个信号量,OSSemCreate( ) 的原型为:
OS_EVENT *OSSemCreate (
INT16U cnt //信号量计数器初值
);
函数的返回值为已创建的信号量的指针。
请求信号量
任务通过调用函数 OSSemPend( ) 请求信号量,函数 OSSemPend( ) 的原型如下:
void OSSemPend ( OS_EVENT *pevent, //信号量的指针
INT16U timeout, //等待时限
INT8U *err //错误信息
);
参数 pevent 是被请求信号量的指针。
为防止任务因得不到信号量而处于长期的等待状态,函数 OSSemPend 允许用参数 timeout 设置一个等待时间的限制,当任务等待的时间超过 timeout 时可以结束等待状态而进入就绪状态。如果参数 timeout 被设置为 0,则表明任务的等待时间为无限长。
释放信号量
任务获得信号量,并在访问共享资源结束以后,必须要释放信号量,释放信号量也叫做发送信号量,发送信号量需调用函数 OSSemPost ( )。OSSemPost ( ) 函数在对信号量的计数器操作之前,首先要检查是否还有等待该信号量的任务。如果没有,就把信号量计数器 OSEventCnt加一;如果有,则调用调度器 OS_Sched( ) 去运行等待任务中优先级别最高的任务。
函数 OSSemPost ( ) 的原型为:
INT8U OSSemPost (
OS_EVENT *pevent //信号量的指针
);
调用函数成功后,函数返回值为 OS_ON_ERR,否则会根据具体错误返回 OS_ERR_EVENT_TYPE、OS_SEM_OVF。
删除信号量
应用程序如果不需要某个信号量了,那么可以调用函数 OSSemDel( ) 来删除该信号量,这个函数的原型为:
OS_EVENT *OSSemDel (
OS_EVENT *pevent, //信号量的指针
INT8U opt, //删除条件选项
INT8U *err //错误信息
);
互斥型信号量
在描述互斥型信号量的事件控制块中,除了成员 OSEventType 要赋以常数 OS_EVENT_TYPE_MUTEX 以表明这是一个互斥型信号量和仍然没有使用成员 OSEventPtr 之外,成员 OSEventCnt 被分成了低8位和高8位两部分:低8位用来存放信号值(该值为 0xFF 时,信号为有效,否则信号为无效),高8位用来存放为了避免出现优先级反转现象而要提升的优先级别 prio。
创建互斥信号量
创建互斥型信号量需要调用函数 OSMutexCreate( )。函数 OSMutexCreate( ) 的原型如下:
OS_EVENT *OSMutexCreate (
INT8U prio, //优先级别
INT8U *err //错误信息
);
函数 OSMutexCreate( ) 从空事件控制块链表获取一个事件控制块,把成员 OSEventType 赋以常数 OS_EVENT_TYPE_MUTEX 以表明这是一个互斥型信号量,然后再把成员 OSEventCnt 的高8位赋以 prio(欲提升的优先级别),低8位赋以常数 OS_MUTEX_AVAILABLE(该常数值为 0xFFFF)的低8位(0xFF)以表明信号量尚未被任何任务所占用,处于有效状态。
请求互斥信号量
当任务需要访问一个独占式共享资源时,就要调用函数 OSMutexPend( ) 来请求管理这个资源的互斥型信号量,如果信号量有信号(OSEventCnt 的低8位为 0xFF),则意味着目前尚无任务占用资源,于是任务可以继续运行并对该资源进行访问,否则就进入等待状态,直至占用这个资源的其他任务释放了该信号量。
函数 OSMutexPend( ) 的原型为:
void OSMutexPend (
OS_EVENT *pevent, //互斥型信号量指针
INT16U timeout, //等待时限
INT8U *err //错误信息
);
释放互斥信号量
任务可以通过调用函数 OSMutexPost( ) 发送一个互斥型信号量,这个函数的原型为:
INT8U OSMutexPost (
OS_EVENT *pevent //互斥型信号量指针
);
参考自:《μC/OS-II 入门教程》
μC/OS-II 任务的同步与通信 --- 信号量的更多相关文章
- uC/OS II原理分析及源码阅读(一)
uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的.可裁减的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和 ...
- US/OS2之任务同步与通信
嵌入式系统中的各个任务都是以并发的方式来运行的,并为同一个大的任务服务,它们不可避免地要共同使用一些共享资源,并且在处理一些需要多个任务共同协作来完成的工作时,还需要相互的支持和限制.因此,对于一个完 ...
- C++同步串口通信
问题描述: C++串口通信,设置同步串口通信 问题解决: (1)打开串口 注: 使用串口需要添加<Windows.h>头文件,打开串口主要是使用CreateFile ...
- uCos-II中任务的同步与通信
任务的同步与通信 任务间的同步 在多任务合作工作过程中,操作系统要解决两个问题: 各任务间应该具有一种互斥关系,即对某些共享资源,如果一个任务正在使用,则其他任务只能等待,等到该任务释放资源后,等待任 ...
- 【原创】uC/OS II 任务切换原理
今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS.IP寄存器没有出栈和入栈指令,所以只能引 ...
- Python 多线程、多进程 (二)之 多线程、同步、通信
Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.python ...
- Qt 多线程同步与通信
Qt 多线程同步与通信 1 多线程同步 Qt提供了以下几个类来完成这一点:QMutex.QMutexLocker.QSemphore.QWaitCondition. 当然可能还包含QReadWrite ...
- 【小梅哥SOPC学习笔记】NIOS II处理器运行UC/OS II
SOPC开发流程之NIOS II 处理器运行 UC/OS II 这里以在芯航线FPGA学习套件的核心板上搭建 NIOS II 软核并运行 UCOS II操作系统为例介绍SOPC的开发流程. 第一步:建 ...
- C#多线程的同步与通信
C#中使用lock和Monitor控制多线程对资源的使用,最常见的生产者和消费者问题就是多线程同步和通信的经典例子.了解C#多线程的同步与通信. 一.关于lock和Monitor lock可以把一段代 ...
随机推荐
- 【慕课网实战】二、以慕课网日志分析为例 进入大数据 Spark SQL 的世界
MapReduce的局限性: 1)代码繁琐: 2)只能够支持map和reduce方法: 3)执行效率低下: 4)不适合迭代多次.交互式.流式的处理: 框架多样化: 1)批处理(离线):MapRed ...
- ArcSDE
ArcSDE,即数据通路,是ArcGIS的空间数据引擎,它是在关系数据库管理系统(RDBMS)中存储和管理多用户空间数据库的通路.从空间数据管理的角度看,ArcSDE是一个连续的空间数据模型,借助这一 ...
- JMS Cluster modules
是GeoServer实现集群还是在数据库实现集群? Hadoop.Spark.HBase与Redis的适用性见解:https://blog.csdn.net/cuiyaonan2000/article ...
- php中测试运行的时间,从而选择得出优化程序
对于新手来说,优化代码的习惯十分重要, 测试运行的时间,从而得出最好的一个 <?php $t1=microtime(true); //获取程序1,开始的时间 程序1(代码...) $t2=m ...
- 利用Python+163邮箱授权码发送带附件的邮件
背景 前段时间写了个自动爬虫的脚本,定时在阿里云服务器上执行,会从某个网站上爬取链接保存到txt文本中,但是脚本不够完善,我需要爬虫完毕之后通过邮件把附件给我发送过来,之前写过一个<利用Pyth ...
- openvpn搭建和使用
一.openvpn原理 openvpn通过使用公开密钥(非对称密钥,加密解密使用不同的key,一个称为Publice key,另外一个是Private key)对数据进行加密的.这种方式称为TLS加密 ...
- 时间字符串格式化 js
/*格式化*/ function dateFormat(dateString, format) { if (!dateString) return ""; //var time = ...
- scrapy 中 xpath 用string方法提取带有空格符解决方法
注释掉的是刚开始的代码,匹配的全是带空格的,replace替换不了空格 后面加上了normalize-space() 匹配到的文本内容变成了可replace 问题解决
- 用python处理csv文件
1.准备csv文件(这里是平安银行的统计表:下载并另存为pingan.csv) >>> from urllib import urlretrieve >>> url ...
- 关于 Block 中捕获 self 的分析
问题 最近遇到一个已经使用了weak-strong dance的block依旧强引用了self的情况,好在block没被VC持有只是延迟释放,但这里的关键是用了weak_self的blcok理应不会强 ...