**我是一个嵌入式小白,遇到问题记下来!
今天学习一下ucos,不懂的太多。如果有错误麻烦告知,谢谢。

ucos任务间的同步与通信

ucosii任务间的同步和通信都可以通过“事件”的方式来搞定,这个事件包括:信号量、互斥量、邮箱和消息队列, 其中信号量和互斥量用于同步,邮箱和消息队列可用于通信。 任务中有任务控制块,同样,在“事件”中有事件控制块ECB
typedef struct os_event {
INT8U OSEventType; 事件控制块的类型
void OSEventPtr; / Pointer to message or queue structure /指针指向的类型
INT16U OSEventCnt; /
Semaphore Count (not used if other EVENT type) */只有使用计数型才会使用
OS_PRIO OSEventGrp; / 等待事件的任务组,作用相当于OSRdyGrp,和线面的任务等代表配合使用
OS_PRIO OSEventTbl[OS_EVENT_TBL_SIZE];任务等待表,跟任务就绪表的使用方法是一样的,“事件”,就把相应的bit位置1
#if OS_EVENT_NAME_EN > 0u
INT8U *OSEventName; 事件的名字
#endif
上述是事件的类型
信号量(sem)
配置操作系统支持的信号量
ucos关于配置的操作都在os_cfg.h中 例:#define OS_SEM_EN 1
二值信号量和计数型信号量
1.二值信号量:
0和1 通常使用中在共享资源的保护,使用一次共享资源就会变成0,当使用完毕就会释放变成1;初始值是1.
2.计数型信号量
初始值大于1,比如说一个办公室有五台打印机 那么初始值就是5,如果有三台在使用那分别对应标记为3,可以使用没有笔记的2个
信号量的使用方法
建立OS_EVENT *OSSemCreate (INT16U cnt)
例: OS_EVENT *pkey 定义的指针是全局变量 pkey=ossemcreate(0)
注释: 参数:cnt,初始化信号量的值,如果值大于1就是计数型,如果等于1就是二值型 如果是0就表示没有资源可以用
返回是 OS_EVENT *一个指针,就是一个ECB控制块,后期使用都是这个指针
等待OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)
这是一个阻塞等待,如果程序在一定时间等待运行,如果等不到就不会往下执行会堵在这里。不允许放在中断服务函数中,因为中断服务函数不允许被挂起。当等待使用一次时就会减1.假设有两个任务同时等待同一个信号量,是靠近的,不是优先级高低来决定。
注释: 参数1:指向与所需信号量关联的事件控制块的指针
参数2:是可选的超时时间(以时钟刻度为单位)。如果非零,则任务将等待资源,直到此参数指定的时间为止。但是如果指定0,则任务将在指定的信号量或,直到资源可用(或事件发生)一直等待,使等待。
参数3:指向错误消息将存放在何处的指针,可能的错误
发送/释放INT8U OSSemPost (OS_EVENT *pevent)
注释:参数:告诉需要操作哪一个指针 就是ECB控制块,返回值是一个错误码
释放信号量就是要把信号量的值加1,在这之前,先检查是否有任务在等待这个信号量,如果有,则去切换到高优先级任务。发一个信号量就会加1一直加下去,
检查信号资源可用 INT16U OSSemAccept (OS_EVENT *pevent)
这个就是解决在中断服务函数中要使用信号量的等待,这是会使用这个函数进行查询。
注释:参数中是等待哪一个信号量,就是句柄,is a pointer to the event control block
如果返回值是大于0,则表明信号量有资源,多少就是多少个资源,如果等于0 ,就表明没有资源。
此函数检查信号量,以查看资源是否可用,或者是否有事件发生了。与OSSemPend()不同,如果资源不可用或事件未发生。是一个非阻塞式查询信号,能用中断服务函数中。如果在等待pend使用之后查询的话,那么检查信号量的值就是0,就为不会执行。
删除OS_EVENT *OSSemDel (OS_EVENT *pevent, INT8U opt, INT8U *perr)
注释: 参数1:删除哪一个信号量/任务
参数2:opt == OS_DEL_NO_PEND 仅当没有任务挂起时才删除信号量,删除信号量没有任务等待的时候,多使用
opt == OS_DEL_ALWAYS 无论有没有任务等待都会删除
参数3:返回值如果为0,或者为空的时候 表明信号量已经成功删除。 OS_ERR_PEVENT_NULL
互斥信号量(Mutex)
作用:互斥信号量用来对共享资源的保护;解决任务优先级的反转。
思考: 1.办公室有一个打印机,现在有三个都需要打印,第一人打印是1234,第二人打印是heelo,第三人打印welcome,如果对打印机使用不保护的话,就会打印出乱如123helcome,等等
2.如果打印机加上保护,假设第一人优先级为6,第二人优先级为8,第三人优先级为10,某一时刻假设第三人在使用打印机,不听打印这个时候第一人也需要使用打印机 他的优先级比较高,但是打印机在使用,因此第一人不能使用程序中断将第一人程序挂起等待,之后第三人继续打印,过一段时间程序有被打断是第二人,但是不需要使用打印机是别的程序(如报警,灯光,,),第二人优先级为8是高于第三人优先级10的,因此程序中断去执行第二人的程序,执行完成之后,第三人又继续按照回来使用打印机,知道打印机结束之后第三人退出,第一人在挂等待程序才会执行使用打印机,可是出现一个问题,第一人优先级高于第二人,为什么会在第二人执行之后才执行呢,感觉很生气,第二人不是使用打印机的啊 ?
3.参考上述2的描述,如果对打印机任务加上互相,则就会出现第三人使用打印的时候 提高自己的优先级比如说提高4这个4优先级一定是所有优先级最高的,并且是没有使用过的优先级。这样第一人要求打印时依旧检查打印机被使用会挂起,则第二人中断过来需要处理程序时,发现优先级8没有4大,就只能等待,等待第三人使用打印机结束,然后再将第三人优先级复原,这样会执行第一人挂起的程序,从而按照优先级的高低执行,因此解决乐优先级的反转情况!
建立OS_EVENT *OSMutexCreate (INT8U prio, INT8U *perr)
例: mutex_sflash = OSMutexCreate(0, &os_err);
注释:参数 1.优先级,提高的优先级,一定是为使用过的优先级。简单说多个任务使用共享资源的时候当某一个任务使用到的时候,你要把这个任务提供到某一个优先级。这个优先级就是,多数情况下是0,
参数2:错误码 返回值:一个ECB指针
阻塞等待信号量OS_EVENT *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *perr)
注释: 和信号量一样,,,,,,,,
发送/释放INT8U OSMutexPost (OS_EVENT *pevent)
注释:顾名思义,当你使用完共享资源完以后,接下来要把共享资源发送出去释放掉。
参数:就是句柄,指针 官方:指向与所需互斥体关联的事件控制块的指针
事件标志组
在理解信号量和互斥信号量的时候都可以类比,因为他们在ucos2里面都通过相同的时间控制块即ECB这个数据结构来实现,理解了一个就很好能看懂另外一个,设置更后面的邮箱和消息队列,也能和信号量之类的类比来学习,他们都有通过ECB来维护。但是事件标志组比较特别,他是ucos2所有这些内核事件里面没有用到ECB的。他有自己的做法。不太合群。什么是事件标志组?
上面说的信号量,互斥信号量。都是用来同步任务对共享资源的访问,防止冲突而设立的。事件标志组----他是用来同步几个任务,协调几个任务工作而设立的。打个比方你现在要打个电话,打电话这个任务要执行,你必须有手机吧!那你要先执行买手机这个任务,你手机有了,没话费你也大不了吧,也就是说打电话这个任务要等买手机这个任务和充话费这个任务都完成了以后你才能去开始打电话这个任务。事件标志组就是用来标志买手机或者充话费这两个任务完成了没有。完成了的话他们会相应的置位事件标志组里面的某些标志位。那么打电话这个任务。发现事件标志组里面买手机对应的位和充话费对应的位都置位了以后就明白,现在可以开始打电话了!实际中比如你想要读数据,那你肯定要等数据采集更新好了以后你去读才有意义吧所以数据采集和读取数据这两个任务也可以用事件标志组来实现。当然,事件标志组不一定只用于两个任务之间,通过对头文件的修改,可以让事件标志组达到32位,你可以用事件标志组来协调多个任务的合理运行。达到你预期想达到的目的!事件标志组就是专门干这个活的。
事件标志组的结构比其他的会复杂一点。没一个事件标志组都维护这自己的一个等待队列的双向链表。每个事件标志组的节点里面都有一个指针和相应的任务控制块TCB一一对应。至于事件标志组的具体实现方法,可以自己去看看源代码。只要懂得一些浅显的双向链表的知识,大概理解他的运作机制不会很难。
建立OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags, INT8U *perr)
注释:参数1:包含要存储在事件标志组中的初始值,大多数使用为0
参数2:错误码 返回值:指向事件标志组的指针,如果没有更多组可用,则为空指针
发送/释放OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp, OS_FLAGS flags, INT8U opt, INT8U *perr)
注释:
消息邮箱(MailBox)
相当于发一个邮件,可以知道发几个邮件,同时拆开邮件还知道里面有什么内容!信号量却不能拆开,但是知道有多少个数。
邮箱是µC/OS-II中另一种通讯机制,它可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量。该指针指向一个包含了特定“消息”的数据结构。为了在µC/OS-II中使用邮箱,必须将OS_CFG.H中的OS_MBOX_EN常数置为1。 使用邮箱之前,必须先建立该邮箱。该操作可以通过调用OSMboxCreate()函数来完成,并且要指定指针的初始值。一般情况下,这个初始值是NULL,但也可以初始化一个邮箱,使其在最开始就包含一条消息。如果使用邮箱的目的是用来通知一个事件的发生(发送一条消息),那么就要初始化该邮箱为NULL,因为在开始时,事件还没有发生。如果用户用邮箱来共享某些资源,那么就要初始化该邮箱为一个非NULL的指针。在这种情况下,邮箱被当成一个二值信号量使用。
邮箱包含的内容是一个指向一条消息的指针。一个邮箱只能包含一个这样的指针(邮箱为满时),或者一个指向NULL的指针(邮箱为空时)。 任务或者中断服务子程序可以调用函数OSMboxPost(),但是只有任务可以调用函数OSMboxPend()和OSMboxQuery()。
建立 OS_EVENT *OSMboxCreate (void pmsg)
邮箱一旦建立,是不能被删除的。
注释:参数 是指向要存入邮箱的邮件的指针。如果将此值设置为空指针(即(void
)0),然后设置邮箱将被认为是空的。
返回值是一个指向事件控制块的指针, 这个指针在调用函数OSMboxPend(),OSMboxPost(),OSMboxAccept()和OSMboxQuery()时使用。因此,该指针可以看作是对应邮箱的句柄。值得注意的是,如果系统中已经没有事件控制块可用,函数OSMboxCreate()将返回一个NULL指针。
等待void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)
注释:它和OSSemPend()也很相似,因此,在这里只讲述其中的不同之处。OSMboxPend()首先检查该事件控制块是由OSMboxCreate()函数建立的。当.OSEventPtr域是一个非NULL的指针时,说明该邮箱中有可用的消息。这种情况下,OSMboxPend()函数将该域的值复制到局部变量msg中,然后将.OSEventPtr置为NULL。这正是我们所期望的,也是执行OSMboxPend()函数最快的路径。
如果此时邮箱中没有消息是可用的(.OSEventPtr域是NULL指针),OSMboxPend()函数检查它的调用者是否是中断服务子程序。象OSSemPend()函数一样,不能在中断服务子程序中调用OSMboxPend(),因为中断服务子程序是不能等待的。这里的代码同样是为了以防万一。但是,如果邮箱中有可用的消息,即使从中断服务子程序中调用OSMboxPend()函数,也一样是成功的。
如果邮箱中没有可用的消息,OSMboxPend()的调用任务就被挂起,直到邮箱中有了消息或者等待超时。当有其它的任务向该邮箱发送了消息后(或者等待时间超时),这时,该任务再一次成为最高优先级任务,OSSched()返回。这时,OSMboxPend()函数要检查是否有消息被放到该任务的任务控制块中。如果有,那么该次函数调用成功,对应的消息被返回到调用函数。
参数1:等待哪一个句柄,就是哪个指针
参数2:等待的时间
参数3:返回错误码 返回值:如果返回值不等于空,!= (void *)0,就说等到接收到的消息了,把这个指针指向接收到的消息地址
如果返回值等于空,就表明没有接收到消息。 综合消息邮箱接收是有返回值来表示的,和信号量不一样。
发送INT8U OSMboxPost (OS_EVENT *pevent, void *pmsg)
注释:参数1:需要发送到哪个消息邮箱,就是句柄。
参数2:发送的消息邮箱的地址

消息队列(Queue)
消息队列有两种,一种是先进先出FIFO主要保证数据的连贯性,一种是后进先出LIFO保证了数据的及时性,发送的是最新的数据;通俗地讲消息队列就是有多个消息邮箱构成,那既然有邮箱了为什么还有消息队列呢,是因为驱动和应用程序之间多了一个一个缓存区,这个缓存区就是队列,就是说如果应用层处理消息比较慢而驱动层发送数据处理比较快,而这个缓存区就会保证数据不会丢失。 每调用一次OSQPend函数,该函数会将队列的消息减1,指向下一个消息指针*ComMsg1[i++],直到队列完全没有消息为止。先创建然creat后发送post最后等待pend。
创建OS_EVENT *OSQCreate (void **start, INT16U size)
注释:参数1:指向指针的指针即双指针,指向队列缓存区的首地址,
参数2:缓存区的大小,或者说消息队列的大小,是多少个元素 不是多少个字节
发送INT8U OSQPost (OS_EVENT *pevent, void *pmsg)
注释:参数1:消息队列的指针/句柄
参数2:发送的消息内容是什么 返回值:表明是否发送成功,其中包括队列满不满,指针为空等
接收/等待void *OSQPend (OS_EVENT *pevent, INT16U timeout, INT8U perr)
注释:pend是一个阻塞等待,等待不到会一直等,或者等待一定时间
参数1:等待那个句柄就是队列
参数2:等待的时间,当为0时就表示一直等待。
参数3:错误码
返回值:如果返回值为空null 表明没有接收到任何消息,如果非空的话,接收到了消息,这个消息被void
指针保存。
查询void *OSQAccept (OS_EVENT *pevent, INT8U perr)
注释:无阻塞的等待查询,查询消息队列中是否有消息,如果有需要干什么事情,如果没有也不会阻塞在这里。
参数1:消息队列的句柄,参数2:错误码
清空INT8U OSQFlush (OS_EVENT pevent)
注释:在通讯过程中阻塞非常严重的时候,就需要清空队列,还有就是使用消息队列之前清空一下消息队列也可以。
参数1:队列的指针

ucos任务间的同步与通信相关推荐

  1. 任务中断间的同步与通信概述

    文章目录 1 任务中断间的同步与通信概述 1 任务中断间的同步与通信概述 通常情况下,任务并不是独立运行的,总是要与其他任务或中断发生联系. RTOS提供的协同机制: 我们需要解决的问题: 同步的概念 ...

  2. 铂金04:令行禁止-为何说信号量是线程间的同步利器

    欢迎来到<并发王者课>,本文是该系列文章中的第17篇. 在并发编程中,信号量是线程同步的重要工具.在本文中,我将带你认识信号量的概念.用法.种类以及Java中的信号量. 信号量(Semap ...

  3. 【VxWorks系列】任务间同步与通信之共享内存

    在开始之前先说明三个概念,任务间的同步,互斥,通信. 同步,是指一个任务等待某个条件发生,而另外一个任务引发这个条件后,等待的任务会被触发执行相应的处理.这就是一个任务与另一任务之间的同步控制. 互斥 ...

  4. 线程间同步和通信,event semaphore mailbox

    线程间同步和通信,event semaphore mailbox 1. 概述 2. 事件event 3. wait_order() 4. 旗语(semaphore) 5. semaphore::get ...

  5. (85)Verilog HDL:板间信号同步

    (85)Verilog HDL:板间信号同步 1.1 目录 1)目录 2)FPGA简介 3)Verilog HDL简介 4)Verilog HDL:板间信号同步 5)结语 1.2 FPGA简介 FPG ...

  6. 线程同步,通信与虚方法

    线程同步,通信与虚方法 目录 线程同步,通信与虚方法 进程同步,通信 事件event 旗语semaphore 信箱mailbox 虚方法 实例理解 将子类句柄赋值成父类句柄 将父类句柄赋值成子类句柄 ...

  7. ITRON同步和通信管理

    ITRON同步和通信管理 在多任务的实时系统中,一项工作的完成往往要通过多个任务或多个任务与多个中断处理过程(ISRs)共同完成.它们之间必须协调动作互相配合,甚至需要交换信息进行通信.这些通信和同步 ...

  8. 任务之间的同步与通信

    目录 系列文章目录 前言: 一:任务间的同步 二:事件 1.信号量 2.消息邮箱 3.消息队列 三:事件控制块级相关操作函数 1:事件控制块结构 2:相关操作函数 系列文章目录 第一章裸机系统与操作系 ...

  9. 假定某计算机的cpu,假定某计算机字长16位,CPU内部结构如图5.1所示,CPU和存储器之间采用同步方式通信,按字编址。采_搜题易...

    假定某计算机字长16位,CPU内部结构如图5.1所示,CPU和存储器之间采用同步方式通信,按字编址.采用定长指令字格式,指令由两个字组成,第一个字指明操作码和寻址方式,第二个字包含立即数Imm16.若 ...

最新文章

  1. mysql之索引组织表
  2. Bash脚本获取自身完整路径的可靠方法
  3. 源代码解读Cas实现单点登出(single sign out)功能实现原理--转
  4. CSS 文字处理总结
  5. Flink Forward Asia 2021 正式启动!议题火热征集中!
  6. ios 获取最后一个cell_关于ios:向UICollectionView的第一个和最后一个单元格添加填充...
  7. 在单节点和多节点上的Hadoop设置
  8. 怎样在php中使用PDF文档功能
  9. spdk/dpdk 编译相关问题汇总
  10. ffmpeg添加到环境变量_如何在Windows 10上下载和安装FFmpeg
  11. xubuntu16.04是linux系统,win10建立Ubuntu16.04子系统,安装经常使用软件以及图形界面(包括win10远程桌面链接Ubuntu)...
  12. php整理(二): 数组
  13. Adopt Open JDK官方文档(五) Docker镜像
  14. t470键盘拆解_ThinkPad T470拆机图赏:堪称商务本的业界标杆
  15. Backtrader量化平台教程-跟踪止损单(十)
  16. 影响力最大化 RIS 反向影响力采样算法
  17. 对电化学极化曲线(LSV/Tafel)的数据进行自动化处理并可视化作图/画图(科研投稿)
  18. 微信分享给朋友 图片显示正常,但是分享到朋友圈图片黑色【显示不出来】
  19. Jdk14其他新特性
  20. G - RMQ and RAQ (cugb2023-s)

热门文章

  1. html搜索框 input标签
  2. linux zip 添加密码,在Linux中如何使用密码保护zip文件
  3. 如何在win7系统中启动摄像头
  4. python二多分支例题_python二级考试题
  5. 通过 useExtendedLib 扩展库的方式引入 WeUI
  6. 【春节安全保障有我们】安全狗春节放假值班通知
  7. PE 019 Counting Sundays
  8. c语言restrict,一个c语言关键字restrict例子的疑问
  9. 前端搬运工 零基础的前端开发初学者应如何系统地学习 前端掌握技能的学习路线
  10. cas.NewLifeGroup.com.cn