μ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可以把一段代 ...
随机推荐
- Notes : <Hands-on ML with Sklearn & TF> Chapter 6
.caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1px so ...
- lucene之Field属性的解释
Field类 数据类型 Tokenized是否分词 Indexed 是否索引 Stored 是否存储 说明 StringField(FieldName, FieldValue,Store.YES)) ...
- Exception in thread "main" java.lang.UnsupportedClassVersionError: org/apache/ma ven/cli/Maven
此异常是由于jdk版本和maven版本不一致导致的 在maven官网上的说明是这样的:Maven 3.3+ require JDK 1.7 or above to execute - they sti ...
- 前端 高级 (二十五)vue2.0项目实战一 配置简要说明、代码简要说明、Import/Export、轮播和列表例子
一.启动服务自动打开浏览器运行 二.配置简要说明 1.node_modules 安装好的依赖文件,中间件等,所在位置 2.package.jason 配置当前项目要安装的中间件和依赖文件 { &quo ...
- [转载]你所不了解的DevOps
DevOps开发运维训练营 一旦建立了创新的文化,即使那些并非科学家或者工程师的人——诗人.演员.记者——也能以团体的形式,接受科学文化的意义.他们信奉创新文化的概念.他们以促进这种文化的方式投票.他 ...
- 背水一战 Windows 10 (107) - 通知(Toast): 提示音, 特定场景
[源码下载] 背水一战 Windows 10 (107) - 通知(Toast): 提示音, 特定场景 作者:webabcd 介绍背水一战 Windows 10 之 通知(Toast) 提示音 特定场 ...
- Android加密解析
编码.数字摘要.加密.解密 UrlEncoder /Urldecoder String str = "http://www.baidu.com?serach = 哈哈"; Stri ...
- 使用Consul 实现 MagicOnion(GRpc) 服务注册和发现
1.下载打开Consul 笔者是windows下面开发的(也可以使用Docker). 官网下载windows的Consul https://www.consul.io/ 使用cmd窗口打开,输入con ...
- clion打断点不生效
打开CLion的偏好设置(Preferences),选择Build,Execution,Deployment->Toolchains,将Debugger中的Bundled LLDB修改为Bund ...
- IntelliJ IDEA 使用前常用设置
0.设置位置 以下设置基于IntelliJ IDEA 2018.3.2 版本. IDEA 的设置一般都在 File 下的 Settings... 里进行设置的. 1.设置字体字号行间距 2.设置背景图 ...