ucos实时操作系统学习笔记——任务间通信(消息)
ucos另一种任务间通信的机制是消息(mbox),个人感觉是它是queue中只有一个信息的特殊情况,从代码中可以很清楚的看到,因为之前有关于queue的学习笔记,所以一并讲一下mbox。为什么有了queue机制还要用mbox呢,只要设置queue的msg只有一个不就行了?其实很简单,就是为了节约资源,因为使用queue的话需要专门描述queue的机构体os_q,同时需要分配一段内存用来存放msg,而如果直接使用mbox机制的话,就好多了,节约。。。。。
首先从mbox的创建开始,mbox创建的函数是OSMboxCreate ,简化代码如下:
OS_EVENT *OSMboxCreate (void *pmsg)
{
OS_EVENT *pevent; if (OSIntNesting > ) { /* See if called from ISR ... */
return ((OS_EVENT *)); /* ... can't CREATE from an ISR */
}
OS_ENTER_CRITICAL();
pevent = OSEventFreeList; /* Get next free event control block */
if (OSEventFreeList != (OS_EVENT *)) { /* See if pool of free ECB pool was empty */
OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
}
OS_EXIT_CRITICAL();
if (pevent != (OS_EVENT *)) {
pevent->OSEventType = OS_EVENT_TYPE_MBOX;
pevent->OSEventCnt = ;
pevent->OSEventPtr = pmsg; /* Deposit message in event control block */
OS_EventWaitListInit(pevent);
}
return (pevent); /* Return pointer to event control block */
}
mbox使用同样使用event机制,它与sem的不同之处在于sem使用event中OSEventCnt变量存放信号量,而mbox使用OSEventPtr存放创建时候的msg地址,可以对比sem的create代码,两者的create代码如此相似。
void *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *perr)
{
void *pmsg; if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
*perr = OS_ERR_EVENT_TYPE;
return ((void *));
}
if (OSIntNesting > ) { /* See if called from ISR ... */
*perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return ((void *));
}
if (OSLockNesting > ) { /* See if called with scheduler locked ... */
*perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
return ((void *));
}
OS_ENTER_CRITICAL();
pmsg = pevent->OSEventPtr;
if (pmsg != (void *)) { /* See if there is already a message */
pevent->OSEventPtr = (void *); /* Clear the mailbox */
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (pmsg); /* Return the message received (or NULL) */
}
OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */
OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
OS_EXIT_CRITICAL();
OS_Sched(); /* Find next highest priority task ready to run */
OS_ENTER_CRITICAL();
switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
case OS_STAT_PEND_OK:
pmsg = OSTCBCur->OSTCBMsg;
*perr = OS_ERR_NONE;
break; case OS_STAT_PEND_ABORT:
pmsg = (void *);
*perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
break; case OS_STAT_PEND_TO:
default:
OS_EventTaskRemove(OSTCBCur, pevent);
pmsg = (void *);
*perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
break;
}
OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
OSTCBCur->OSTCBEventPtr = (OS_EVENT *); /* Clear event pointers */
OSTCBCur->OSTCBMsg = (void *); /* Clear received message */
OS_EXIT_CRITICAL();
return (pmsg); /* Return received message */
}
因为好于其他的机制代码对比,所以将整个代码贴出来,其实主要的差别在黄色部分,因为在创建msg的时候,或者在post msg的时候,会将msg放到OSEventPtr,所以直接从中取出msg,判断当前的msg是否存在,如果存在的话就会将msg返回并且对msgbox即OSEventPtr清0操作;如果msg没有则直接将当前任务挂起处于event的等待列表中,进行任务调度也就是黄色部分下面的处理过程,不做过多的赘述。
INT8U OSMboxPost (OS_EVENT *pevent, void *pmsg)
{
if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
return (OS_ERR_EVENT_TYPE);
}
OS_ENTER_CRITICAL();
(1)====================================================================================================
if (pevent->OSEventGrp != ) { /* See if any task pending on mailbox */
/* Ready HPT waiting on event */
(void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
OS_EXIT_CRITICAL();
OS_Sched(); /* Find highest priority task ready to run */
return (OS_ERR_NONE);
}
(2)====================================================================================================
if (pevent->OSEventPtr != (void *)) { /* Make sure mailbox doesn't already have a msg */
OS_EXIT_CRITICAL();
return (OS_ERR_MBOX_FULL);
}
pevent->OSEventPtr = pmsg; /* Place message in mailbox */
OS_EXIT_CRITICAL();
return (OS_ERR_NONE);
(3)====================================================================================================
}
mbox的post函数代码如上所示,其实处理过程和sem等类似,post其实就是填充的功能,首先判断有没有在等待当前event的任务存在,如果有的话直接将msg等交给等待任务,如果没有则进入到第三部分,判断当前的OSEventPtr中是否有msg,如果有表示没有任务从中取出msg,这时会返回错误,如果OSEventPtr中没有msg,则将msg放到OSEventPtr中,等待任务从中取出。
通过学习sem,mutex,queue以及mbox的内核实现可以大体的了解操作系统任务间的通信机制是如何实现的,也可以和其他的操作系统作对别,通过简单的内核实现取理解复杂的操作系统该部分的实现机制,比如所Linux操作系统,这是一个很好的学习方法。下面简单总结一下这四中通信机制的功能:
1. 信号量:信号量其实就是一种通过数字大小来实现限制资源使用的一种机制,设置信号量其实就是设置资源最大可以允许多少个任务同时访问同一个资源,通过信号量pend和post操作即信号量变量的加减实现任务控制,当特殊情况,只有一个信号量的时候就有点互斥的意思。
2. 互斥锁:互斥锁就是同一时间只有一个任务可以占有资源,当有其他任务要访问资源的时候就会将这个任务挂起,放到event的等待列表中,当占有资源的任务释放掉锁的时候,等待任务才可以占有资源并且上锁,为了防止优先级的翻转,使用了优先级继承的机制,就是把占有资源的任务的优先级提升一下比要使用资源的任务的优先级高。
3. 队列:队列就是取一段内存用于存放消息,这个消息是一个地址,真正的消息内容是存放在这个地址中,这样的话可以就可以实现真正的任务间通信,将数据从一个任务传到另一个任务,而不像信号量和互斥锁一下仅仅是一个限制作用。队列使用要注意,如果多个任务在等待不同的消息的话,有可能会出现不同任务获得了不是自己想要的信息并且将消息从队列中去除掉了,所以使用的时候需要注意。
4. 消息:消息其实是队列的一种特殊情况,为了节省资源,之前也有讲到,如果消息数量一定的话同一时间只有一个消息使用,那么采用消息机制更简单,同样实现了数据的传输功能。消息的使用也同样要注意,pend和post的使用,因为如果有多个任务同时使用的话,就会存在是否是当前任务想要的信息,如果不是的话有可能把别的任务的消息给去处并释放掉了,所以使用时需要注意。
ucos实时操作系统学习笔记——任务间通信(消息)的更多相关文章
- ucos实时操作系统学习笔记——任务间通信(信号量)
ucos实时操作系统的任务间通信有好多种,本人主要学习了sem, mutex, queue, messagebox这四种.系统内核代码中,这几种任务间通信机制的实现机制相似,接下来记录一下本人对核心代 ...
- ucos实时操作系统学习笔记——任务间通信(队列)
ucos操作系统中的queue机制同样使用了event机制来实现,其实和前面的sem,mutex实现类似,所不同的是对sem而言,任务想获得信号量,对mutex而言,任务想获得的是互斥锁.任务间通信的 ...
- ucos实时操作系统学习笔记——任务间通信(互斥锁)
想讲一下ucos任务间通信中的mutex,感觉其设计挺巧妙,同sem一样使用的是event机制实现的,代码不每一行都分析,因为讲的没邵贝贝老师清楚,主要讲一下mutex的内核是如何实现的.可以理解互斥 ...
- ucos实时操作系统学习笔记——操作系统在STM32的移植
使用ucos实时操作系统是在上学的时候,导师科研项目中.那时候就是网上找到操作系统移植教程以及应用教程依葫芦画瓢,功能实现也就罢了,没有很深入的去研究过这个东西.后来工作了,闲来无聊就研究了一下这个只 ...
- ucos实时操作系统学习笔记——内核结构和任务创建
对于ucos实时操作系统,邵贝贝的那本书已经写得很详细了,我因为之前不深的研究过ucos,所以在这里做一个笔记,写一些个人对该操作系统的理解,仅仅是个人理解,如果有人看到这边随笔有不对的地方,望给我指 ...
- RTX51 Tiny实时操作系统学习笔记—初识RTX51 Tiny
一,RTX51 Tiny简单介绍 RTX51 Tiny是一种实时操作系统(RTOS),能够用它来建立多个任务(函数)同一时候运行的应用(从宏观上看是同一时候运行的,但从微观上看,还是独立运行的 ...
- 操作系统学习笔记----进程/线程模型----Coursera课程笔记
操作系统学习笔记----进程/线程模型----Coursera课程笔记 进程/线程模型 0. 概述 0.1 进程模型 多道程序设计 进程的概念.进程控制块 进程状态及转换.进程队列 进程控制----进 ...
- 操作系统学习笔记5 | 用户级线程 && 内核级线程
在上一部分中,我们了解到操作系统实现多进程图像需要组织.切换.考虑进程之间的影响,组织就是用PCB的队列实现,用到了一些简单的数据结构知识.而本部分重点就是进程之间的切换. 参考资料: 课程:哈工大操 ...
- 深挖计算机基础:趣谈Linux操作系统学习笔记
参考极客时间专栏<趣谈Linux操作系统>学习笔记 核心原理篇:内存管理 趣谈Linux操作系统学习笔记:第二十讲 趣谈Linux操作系统学习笔记:第二十一讲 趣谈Linux操作系统学习笔 ...
随机推荐
- 微信小程序开发心得
微信小程序也已出来有一段时间了,最近写了几款微信小程序项目,今天来说说感受. 首先开发一款微信小程序,最主要的就是针对于公司来运营的,因为,在申请appid(微信小程序ID号)时候,需要填写相关的公司 ...
- node服务的监控预警系统架构
需求背景 目前node端的服务逐渐成熟,在不少公司内部也开始承担业务处理或者视图渲染工作.不同于个人开发的简单服务器,企业级的node服务要求更为苛刻: 高稳定性.高可靠性.鲁棒性以及直观的监控和报警 ...
- Asp.Net MVC中使用StreamReader读取“Post body”之应用场景。
场景:有三个市场(Global.China.USA),对前台传过来的数据有些验证需要细化到每个市场去完成. 所以就出现了基类(Global)和派生类(China.USA) 定义基类(Global)Pe ...
- MSDN文档篇
很多人网上下载3~10G不等的MSDN文档,发现,下载完成了不会用 很多人每次都得在线下载文档,手上万千PC,都重新下载不是得疯了? so==> 先看几张图 推荐一个工具:https://vsh ...
- SQL Server 无法连接到服务器。SQL Server 复制需要有实际的服务器名称才能连接到服务器。请指定实际的服务器名称。
异常处理汇总-数据库系列 http://www.cnblogs.com/dunitian/p/4522990.html SQL性能优化汇总篇:http://www.cnblogs.com/dunit ...
- HTML5 介绍
本篇主要介绍HTML5规范的内容和页面上的架构变动. 目录 1. HTML5介绍 1.1 介绍 1.2 内容 1.3 浏览器支持情况 2. 创建HTML5页面 2.1 <!DOCTYPE> ...
- python黑魔法 -- 内置方法使用
很多pythonic的代码都会用到内置方法,根据自己的经验,罗列一下自己知道的内置方法. __getitem__ __setitem__ __delitem__ 这三个方法是字典类的内置方法,分别对应 ...
- C++随笔:.NET CoreCLR之GC探索(1)
一直是.NET程序员,但是.NET的核心其实还是C++,所以我准备花 一点时间来研究CoreCLR和CoreFX.希望这个系列的文章能给大家带来 帮助. GC的代码有很多很多,而且结构层次对于一个初学 ...
- maven 快照
大型应用软件一般由多个模块组成,一般它是多个团队开发同一个应用程序的不同模块,这是比较常见的场景.例如,一个团队正在对应用程序的应用程序,用户界面项目(app-ui.jar:1.0) 的前端进行开发, ...
- Linux实战教学笔记03:操作系统发展历程及系统版本选择
标签(空格分隔): Linux实战教学笔记-陈思齐 第1章 Linux简介 1.1 什么是操作系统? 简单讲:操作系统就是一个人与计算机硬件的中介. 操作系统,英文名称Operating System ...