任务间通信

系统中的多个任务在运行时,经常需要互相无冲突地访问同一个共享资源,或者需要互相支持和依赖,甚至有时还要互相加以必要的限制和制约,才保证任务的顺利运行。因此,操作系统必须具有对任务的运行进行协调的能力,从而使任务之间可以无冲突、流畅地同步运行,而不致导致灾难性的后果。

与人们依靠通信来互相沟通,从而使人际关系和谐、工作顺利的做法一样,计算机系统是依靠任务之间的良好通信来保证任务与任务的同步的。

举例说明

两个任务:任务 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 任务的同步与通信 --- 信号量的更多相关文章

  1. uC/OS II原理分析及源码阅读(一)

    uC/OS II(Micro Control Operation System Two)是一个可以基于ROM运行的.可裁减的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处理器和控制器,是和 ...

  2. US/OS2之任务同步与通信

    嵌入式系统中的各个任务都是以并发的方式来运行的,并为同一个大的任务服务,它们不可避免地要共同使用一些共享资源,并且在处理一些需要多个任务共同协作来完成的工作时,还需要相互的支持和限制.因此,对于一个完 ...

  3. C++同步串口通信

    问题描述:     C++串口通信,设置同步串口通信 问题解决:     (1)打开串口 注:     使用串口需要添加<Windows.h>头文件,打开串口主要是使用CreateFile ...

  4. uCos-II中任务的同步与通信

    任务的同步与通信 任务间的同步 在多任务合作工作过程中,操作系统要解决两个问题: 各任务间应该具有一种互斥关系,即对某些共享资源,如果一个任务正在使用,则其他任务只能等待,等到该任务释放资源后,等待任 ...

  5. 【原创】uC/OS II 任务切换原理

    今天学习了uC/OS II的任务切换,知道要实现任务的切换,要将原先任务的寄存器压入任务堆栈,再将新任务中任务堆栈的寄存器内容弹出到CPU的寄存器,其中的CS.IP寄存器没有出栈和入栈指令,所以只能引 ...

  6. Python 多线程、多进程 (二)之 多线程、同步、通信

    Python 多线程.多进程 (一)之 源码执行流程.GIL Python 多线程.多进程 (二)之 多线程.同步.通信 Python 多线程.多进程 (三)之 线程进程对比.多线程 一.python ...

  7. Qt 多线程同步与通信

    Qt 多线程同步与通信 1 多线程同步 Qt提供了以下几个类来完成这一点:QMutex.QMutexLocker.QSemphore.QWaitCondition. 当然可能还包含QReadWrite ...

  8. 【小梅哥SOPC学习笔记】NIOS II处理器运行UC/OS II

    SOPC开发流程之NIOS II 处理器运行 UC/OS II 这里以在芯航线FPGA学习套件的核心板上搭建 NIOS II 软核并运行 UCOS II操作系统为例介绍SOPC的开发流程. 第一步:建 ...

  9. C#多线程的同步与通信

    C#中使用lock和Monitor控制多线程对资源的使用,最常见的生产者和消费者问题就是多线程同步和通信的经典例子.了解C#多线程的同步与通信. 一.关于lock和Monitor lock可以把一段代 ...

随机推荐

  1. dhcp服务简单配置

    dhcp服务搭建 注意事项: > 配置虚拟机虚拟网络编辑器,取消"使用本地DHCP服务将IP地址分配给虚拟机" > 虚拟机网络连接设置为"仅主机模式" ...

  2. Freeradius服务器的搭建流程

    Freeradius服务器的搭建流程 一.服务器方面的配置 1 .安装radius服务器,数据库扩展插件 预先安装mysql数据库,然后安装freeradius,以及freeradius的数据库扩展插 ...

  3. Git Gui for Windows的建库、克隆(clone)、上传(push)、下载(pull)、合并(转)

    Git Gui for Windows的建库.克隆(clone).上传(push).下载(pull).合并(转) from:http://hi.baidu.com/mvp_xuan/blog/item ...

  4. PIL库图像处理

    PIL有如下几个模块 Image模块.ImageChops模块.ImageCrackCode模块 ImageDraw模块.ImageEnhance模块.ImageFile模块 ImageFileIO模 ...

  5. hive 日常技巧

    --删除表中重复数据 delete from vitae a where (a.peopleId,a.seq) in (select peopleId,seq from vitae group by ...

  6. Linux下安装GEOS环境

    1.下载对应版本的geos源码:http://download.osgeo.org/geos/ 2.下载后使用cd切换到源码目录解压:tar -xvf geosXXX.tar.gz 3.切换到解压后目 ...

  7. all about

    1.三次握手和四次挥手?2.什么是OSI七层结构?3.http vs https?4.what is Ping?基于什么协议?使用方法?5.DNS?6.cookie vs session?7.LDAP ...

  8. bash 管理小脚本

    #!/bin/bash shell_user="root" shell_pass="1233" shell_port="22" shell_ ...

  9. 超实用的 Nginx 极简教程,覆盖了常用场景

    概述 什么是 Nginx? Nginx (engine x) 是一款轻量级的 Web 服务器 .反向代理服务器及电子邮件(IMAP/POP3)代理服务器. 什么是反向代理? 反向代理(Reverse ...

  10. Javascript高级编程学习笔记(56)—— DOM2和DOM3(8)低版本IE范围

    虽然IE9支持了DOM范围,但是IE8及更早版本并不支持DOM范围 所以IE8以下的更早版本的IE提出了与之类似的概念以供大家使用 也就是 文本范围 var range = document.body ...