任务的同步与通信

任务间的同步

在多任务合作工作过程中,操作系统要解决两个问题:

  • 各任务间应该具有一种互斥关系,即对某些共享资源,如果一个任务正在使用,则其他任务只能等待,等到该任务释放资源后,等待任务之一才能使用它;
  • 相关的任务在执行上要有先后次序,一个任务要等其伙伴发来通知,或建立了某个条件后才能继续执行,否则只能等待;

任务之间的这种制约性的合作运行机制叫任务间的同步;

任务中的事件

uCosII使用信号量、消息邮箱和消息队列这些中间环节来实现任务之间的通信,而这些中间环节都统一称为事件;

事件控制块及事件处理

事件控制块

对于事件来说,当其被占用时,会导致其他请求该事件的任务因暂时得不到该事件的服务而处于等待状态;

作为功能完善的事件,应该对这些等待任务有两方面的管理能力:

  • 要对等待事件的所有任务进行记录并排序;
  • 允许等待任务有一个等待时限,即当等待任务认为等不及时可以退出对事件的请求;

对于等待事件任务的记录,系统定义了一个INT8U类型的数组OSEventTbl[]作为等待事件任务的记录表,即等待任务表;

等待任务表以任务优先级别为顺序为每个任务分配一个二进制位,来表示这一位对应的任务为事件的等待任务,否则不是等待任务;

为了加快该表的访问速度,也定义了一个INT8U类型的变量OSEventGrp来表示等待任务中的任务组;

等待任务的等待时限记录在等待任务的任务控制块TCB的成员OSTCBDly中,并在每个时钟节拍中断服务程序中对该数据进行维护,每当有任务的等待时限到达时,便将该任务从等待任务表中删除,并使它进入就绪状态;

系统为了把描述事件的数据结构统一起来,使用叫做事件控制快ECB的数据结构来描述诸如信号量、消息邮箱和消息队列等事件;

事件控制块的组织是通过事件控制块链表的形式;

事件处理函数

系统中对事件控制块进行基本操作的函数定义在文件os_core.c中;

  • EventWaitListInit()事件控制块的初始化函数,作用是把变量OSEventGrp及任务等待表中的每一位都清0,即令事件任务等待表中不含有任何等待任务;
  • OS_EventTaskWait()把一个任务置于等待状态;
  • OS_EventTaskRdy()把调用这个函数的任务在任务等待表中的位置清0(解除等待状态)后,再把任务在任务就绪表中对应的位置设置为1,然后引发一次任务调度;
  • OS_EventTO()使一个等待超时的任务进入就绪状态;

信号量及其操作

当事件控制块成员OSEventType的值被设置为OS_EVENT_TYPE_SEM时,这个事件控制块描述的就是一个信号量;

信号量由计数器和等待任务表两部分组成;

操作

OSSemCreate

应用程序在使用信号量之前必须先调用该函数来创建一个信号量;

OSSemPend

请求信号量,为防止任务因得不到信号量而处于长期的等待状态,该函数允许用参数timeout设置一个等待时间的限制,当任务等待时间超过timeout时,可以结束等待状态而进入就绪状态,如果该参数设置为0,则表明任务的等待时间为无限长;

当任务需要访问一个共享资源时,先要请求管理该资源的信号量,这样就可以根据信号量当前是否有效(即信号量计数器的值是否大于0)来决定该任务是否可以继续运行,如果信号量有效,则把信号量计数器减1,然后继续运行任务,如果信号量无效(即信号量计数器的值等于0),则会在等待任务表中把该任务对应的位设置为1而让任务处于等待状态,并把等待时限timeout保存在任务控制块对应的变量中;

如果希望任务在请求信号量,当信号量无效时不进入等待状态而继续运行,则不调用函数OSSemPend(),而是调用函数OSSemAccept()来请求信号量;

OSSemPost

任务获得信号量,在访问共享资源结束以后,必须调用该函数释放信号量,也叫发送信号量;

该函数在对信号量的计数器操作之前,要检查是否还有等待该信号量的任务,如果没有,则将信号量计数器值加1,如果有,则调用调度器OS_Sched()去运行等待任务中优先级最高的任务;

OSSemDel

如果应用程序不需要某个信号,那么可调用该函数来删除该信号;

函数中的参数opt用来指明信号量的删除条件,该参数有两个参数值可以选择:

  • OS_DEL_NO_PEND当等待任务表中已没有等待任务时才删除信号量;
  • OS_DEL_ALLWAYS在等待任务表中无论是否有等待任务都立即删除信号量;

需要注意,只能在任务中删除信号量,而不能在中断服务程序中删除;

OSSemQuery

任务可以调用该函数随时查询信号量的当前状态;

互斥信号量

互斥信号量时一个二值信号,可以使任务以独占方式使用共享资源;

使用互斥型信号量会出现任务优先级反转的问题,即在可剥夺型内核中,当任务以独占方式使用共享资源时,会出现低优先级任务先于高优先级任务而被运行的现象,这种现象在实时系统中是不允许出现的,因为它破坏了任务执行的预期顺序,可能会导致严重的后果;

解决该现象的办法之一是,使获得信号量任务的优先级别在使用共享资源期间暂时提升到所有任务最高优先级的高一个级别上,以使该任务不被其他任务所打断,从而能尽快地使用完共享资源并释放信号量,然后在释放信号量之后,再恢复该任务原来的优先级别;

OSMutexCreate

创建互斥型信号量,在描述互斥型信号量的事件控制块中,除了成员OSEventType要赋予常数OS_EVENT_TYPE_MUTEX以表明是一个互斥型信号量和仍然没有使用成员OSEventPtr之外,成员OSEventCnt被分成了低8位和高8位两部分,高8位用来存放为了避免出现优先级反转现象而要提升的优先级prio,低8位赋予常数OS_MUTEX_AVAILABLE,表明信号量尚未被任何任务所占用,处于有效状态;

OSMutexPend

请求互斥型信号量;

也可以调用函数OSMutexAccept()无等待地请求一个互斥型信号量;

OSMutexPost

发送一个互斥型信号量;

OSMutexQuery

获取互斥型信号量的当前状态;

OSMutexDel

任务调用该函数可删除一个互斥型信号量;

消息邮箱

OSMboxCreate

创建消息邮箱;

OSMboxPost

向消息邮箱发送消息;

OSMboxPostOpt

向消息邮箱发送消息,可以以广播的方式向事件等待任务表中的所有任务发送消息;

OSMboxPend

请求消息邮箱;

OSMboxAccept

请求消息邮箱失败时,不进行等待而是继续运行;

OSMboxQuery

查询消息邮箱当前状态信息;

OSMboxDel

删除一个消息邮箱;

消息队列

使用消息队列可在任务之间传递多条消息,消息队列由三部分组成:时间控制块、消息队列和消息;

事件控制块成员OSEventPtr指向一个叫做队列控制块(OS_Q)的结构,该结构管理着一个数组MsgTbl[],该数组中的元素都是指向消息的指针;

OSQCreate

创建消息队列,首先需要定义一个指针数组,然后把各个消息数据缓冲区的首地址存入这个数组中,最后调用该函数来创建消息队列;

OSQPend

请求消息队列,即从消息队列中获取消息;

如果希望任务无等待地请求一个消息队列,则可调用函数OSQAccept()函数;

OSQPost/OSQPostFront

向消息队列发送消息;

函数OSQPost()是以FIFO的方式组织消息队列;

函数OSQPostFront()以LIFO的方式组织消息队列;

OSQPostOpt

该函数时任务将以广播的方式通过消息队列发送消息;

OSQFlush

清空消息队列;

OSQDel

删除一个已存在的消息队列;

OSQQuery

查询一个消息队列的状态;

uCos-II中任务的同步与通信的更多相关文章

  1. ucos ii 百度官方介绍

          μC/OS II(Micro-Controller Operating System Two)是一个可以基于ROM运行的.可裁剪的.抢占式.实时多任务内核,具有高度可移植性,特别适合于微处 ...

  2. ucos实时操作系统学习笔记——任务间通信(队列)

    ucos操作系统中的queue机制同样使用了event机制来实现,其实和前面的sem,mutex实现类似,所不同的是对sem而言,任务想获得信号量,对mutex而言,任务想获得的是互斥锁.任务间通信的 ...

  3. DE1-SOC开发板上搭建NIOS II处理器运行UCOS II

    DE1-SOC开发板上搭建NIOS II处理器运行UCOS II   今天在DE1-SOC的开发板上搭建NIOS II软核运行了UCOS II,整个开发过程比较繁琐,稍微有一步做的不对,就会导致整个过 ...

  4. [转]在Windows中配置Rsync同步

    在Windows中配置Rsync同步 Rsync是一款不错的文件免费同步软件,可以镜像保存整个目录树和文件系统,同 时保持原来文件的权限.时间.软硬链接.第一次同步时 rsync 会复制全部内容,下次 ...

  5. Win32多线程编程(3) — 线程同步与通信

      一.线程间数据通信 系统从进程的地址空间中分配内存给线程栈使用.新线程与创建它的线程在相同的进程上下文中运行.因此,新线程可以访问进程内核对象的所有句柄.进程中的所有内存以及同一个进程中其他所有线 ...

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

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

  7. javaEE开发中使用session同步和token机制来防止并发重复提交

    javaEE开发中使用session同步和token机制来防止并发重复提交 通常在普通的操作当中,我们不需要处理重复提交的,而且有很多方法来防止重复提交.比如在登陆过程中,通过使用redirect,可 ...

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

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

  9. Qt 多线程同步与通信

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

随机推荐

  1. selenium-webdriver的二次封装(十)

    接着上篇随笔 selenium-配置文件定位元素 ,进行了配置文件设置后,将配置文件运用到定位元素中 思路:拿到定位的 key 和 value 后,对 webdrvier 中定位进行封装,使可以直接运 ...

  2. SQL 行转列 PIVOT 学习示例

    CREATE TABLE [StudentScores] ( ), --学生姓名 ), --科目 [Score] FLOAT, --成绩 ) select * from [StudentScores] ...

  3. name 'reload' is not defined解决方法

    今天在学习scrapy的时候,在网上找了一段代码,运行出了一点问题. 命令行报错: name 'reload' is not defined 原因是,python版本的问题 原代码如下: import ...

  4. DES加密算法应用:分组加密模式

    通常,大多数的分组加密算法都是把数据按照64位分组的方式进行加密和解密.但是几乎所有的加密工作所涉及的数据量都远远大于64位,因此就需要不断地重复加密过程,直到处理完所有的分组.这种分组加密中所涉及的 ...

  5. 【shell基础】if分支语句

    1.if判断式if [ 条件判断一 ] && (||) [ 条件判断二 ]; thenelif [ 条件判断三 ] && (||) [ 条件判断四 ]; thenels ...

  6. Codeforces #541 (Div2) - F. Asya And Kittens(并查集+链表)

    Problem   Codeforces #541 (Div2) - F. Asya And Kittens Time Limit: 2000 mSec Problem Description Inp ...

  7. 数据的偏度和峰度——df.skew()、df.kurt()

    我们一般会拿偏度和峰度来看数据的分布形态,而且一般会跟正态分布做比较,我们把正态分布的偏度和峰度都看做零.如果我们在实操中,算到偏度峰度不为0,即表明变量存在左偏右偏,或者是高顶平顶这么一说. 一.偏 ...

  8. ABP之Caching

    简介 ABP提供缓存抽象,默认使用MemoryCache.但是可以替换成其他缓存程序,比如 Abp.RedisCache 是使用Redis实现缓存. ICacheManager 缓存的主要接口是ICa ...

  9. Collections算法类

    Collections类定义了一系列用于操作集合的静态方法. 常用方法: 1.sort():排序(默认是升序排列,降序实现方法) 如果ArrayList的泛型指定为String int等类型,可以通过 ...

  10. JS中的事件委托(事件代理)

    一步一步来说说事件委托(或者有的资料叫事件代理) js中事件冒泡我们知道,子元素身上的事件会冒泡到父元素身上. 事件代理就是,本来加在子元素身上的事件,加在了其父级身上. 那就产生了问题:父级那么多子 ...