OSAL 消息收发过程 | 学习笔记

简介: 快速学习 OSAL 消息收发过程

开发者学堂课程【嵌入式之 RFID 开发与应用2020版:OSAL 消息收发过程】学习笔记,与课程紧密联系,让用户快速学习知识。

课程地址:https://developer.aliyun.com/learning/course/665/detail/11130


OSAL 消息收发过程

知道 OSAL 系统总的调度原理,接下来有一个非常常用的一个手段或者说是一个功能,就是某个进程之间某个任务之间,A 任务要给 B 任务发一个消息,这个消息的收发的过程是怎样的?

首先发送这个消息本质上是通过 osal set 去设置这个事件,提供了 osal msg send message send,仔细去分析这个源代码,想了解的哪个地方可以直接去搜索。

image.png

以这个串口为例,串口在接收到数据的他把接收到的串口的数据,把它放到了 msg里面,PMSG 然后再加一个 msg,这里 OSAL 申请的空间给了 pmsg,之后就调用了 osal send message 去发送,那这个地方有个任务 ID,也就是说要把这个消息发给哪一个任务,这个就是他的 ID 也就是刚才第一个任务,ID;第二个是发的内容。

j++; 〃记录字符数

flag=1; 〃己经从串口接收到信息

}

if(flag==1) 〃已经从串口接收到信息

{

/* Allocate memory for the data */

//分配内存空间,为机构体内容+数据内容+1个记录长度的数据 pMsg = (mtOSALSerialData_t *)osal_msg|_allocate( sizeof

(mtOSALSerialData_t )+j+3);

//事件号用原来的 cmd_serial[msg

pAfsg->hdr.event = CMD_SERIAL_MSG;

pMsg->msg = (uint8*)(pMsg+l); //把数据定位到结构体数据部分

pMsg->msg [θ]= port;//给上层的数据第一个是串口号

pMsg->msg [1]= j;//给上层的数握第二个是长度

buf[j] = 0;

strcpy((char *)&(pMsg->msg[2]),(const char *)buf);

// for(i=θ;i<j;i++) 〃从第二个开始记录数据

// pMsg->msg [i+2]= buf[i];

osal_msg_send( my_TaskID, (byte *)pMsg ); 〃登记任务,发往上层

/* deallocate the msg */

// osal_msg_deallocate ( (uint8 *)pMsg ); 〃释放内存

}

}« end MT_UartProcessZToolData »

#else

msg 消息发送过程:

osal _ msg _ send (uint8 taskID , void msg _ ptr )

msg _ ptr 指向消息内容,不能为空

放入消息队列 osal _ msg _ enqueue (& osal _ qHead , msg _ ptr );

最后通过 osal _ set _ event ( taskID , SYS _ EVENT _ MSG )给任务事件置位

msg 消息接收过程:

msg _ ptr = osal _ msg _ receive ( taskID );>消息队列取出

osal _ msg _ extract (& osal _ qHead , msg _ ptr ,

清除事件 osal _ clear _ event ( taskID , SYS_EVENT-MSG)

具体的发送的过程会把它放到队列当中去。然后通过最后你看。

Osal set event 可以到这个里面去进去看一下。

}

// Check the message header

if ( OSAL_MSG_NEXT( msg_ptr ) != NULL || OSAL_MSG_ID( msg_ptr ) != TASK_NO_TASK ) {

osal_msg_deallocate( msg_ptr ); return

( INVALID_MSG_POINTER );

}

OSAL_MSG_ID( msg_ptr ) = destination_task;

// queue message

osal_msg_enqueue( &osal_qHsad, msg_ptr );

// Signal the task that a message is waiting os[al_set_event ( destination_task, SYS_EVENT_MSG );

return ( SUCCESS );

} « end osal_msg_send »

* @fn osal_msg_receive

*

* @brief

这个事件的类型就是叫做 SYS_EVENT_MSG 然后这个消息发出去了,对方去接收让的第一步,并不是去搜这个消息,而是去搜这个事件。

//任务事件处理函数

uintl6 my_ProcessEvent( uint8 task_id, uintl6 events )

{

afIncomingMSGPacket_t *MSGpkt = NULL;

ifevents & SYS_EVENT_MSG)

{

MSGpkt = (aflncomingMSGPacket t *)osal msg receive( my TaskID );

while(MSGpkt != NULL){

switch ( MSGpkt->hdr.event )

{

case ZDO_STATE_CHANGE:

identity_nwk = (devStates_t)(MSGpkt->hdr.status);

if(identity_nwk == DEV_END_DEVICE){

debug("入'网成功\n");

debug("获得地址=0x%x\n",NLME_GetShortAddr());

#if CTRL_0R GATHER // 控制节点/采集节点入网成功后尧发一个数据给协调器以确认自己是谁,

send_coord_affirm(SAMPLEAPP_CTRL_CLUSTERID);//这是不同终端要改

#else

send_coord_affirm(SAMPLEAPP_SENSOR_CLUSTERID);//这是不同终端要改

只要被调度,就要去判断有没有发生这个事件,被调度的是因为有人给他调用了osal set event 他才会被调用。他被调用的第一步就检测有没有收到这个消息,如果if是成立的就表示收到这个消息之后再调用 osal msg receive 这个函数去接收消息。可以看到它首先调用这个函数从消息队列里面把消息提取出来,最后清除这个任务。

消息收发操作流程:

申请消息空间(消息开头都会有 osal _ msg _ hdr _ t 结构): msgstr = osal _ m $ g _ allocate (1en)

消息内容的初始化: strcpy ( msgstr ,” helloln ");>发送消息: osal _ msg _ send ( xxTaskID , msgstr )- osal _ msg _ enqueue (在链表结尾添加节点

接收消息(根据任务 ID 进行接收): msg = osal _ msg _ receive ( xx _ TaskID )

对得到的消息进行处理

释放消息: osal _ msg _ deallocate O()

这里也有他的详细过程,申请,空间,拷贝,接收完了以后还要释放,这个地方接收是在这个里面。这个消息调用了操作系统,这个 osal_ msg_ ollocate, 释放必须要调的 deallocate,这就有点像 C 语言里面的那个 Malloc 和 Free,但他释放的对象是谁得去看它在发送的时候 Allocation 给了谁,他给的 pmsg。相当于他的这个返回值。

再去找有没有地方调用 deallocate 也就是前面这些接收到消息之后,这里都是使用。当使用完不再使用的时候,就必须要调用这个就把

把它释放掉。这个就是整个消息的收发流程,在操作系统里面这个任务之间通信也是时常发生的,所以这个过程一定要搞清楚,而且一定要理解消息收发的本质是什么。

本质其实就是往消息队列里面放了一块申请的空间,并且通过之前那个事件的机制去把某个事件给置位,让操作系统在轮询调度的过程当中能够发现这个事件从而去调度相应的任务去处理这个消息。

相关文章
|
2月前
|
存储 安全 API
基于FreeRTOS中的串口不定长接收(使用队列进行数据传输)
基于FreeRTOS中的串口不定长接收(使用队列进行数据传输)
168 0
|
C#
C# 中串口通信 serialport1.DataReceived 函数无法触发或者出发延时等等问题解决方法
原文:C# 中串口通信 serialport1.DataReceived 函数无法触发或者出发延时等等问题解决方法 以前这个问题困扰我多天最后查资料一大堆,最后最终攻克了,看到非常多人做C#串口都遇到相同的问题,所以写一篇博文,以便学习交流。
3440 0
|
消息中间件 数据安全/隐私保护
【OpenAirInterface5g】ITTI消息收发机制
OAI各个模块拥有自己的消息队列,当其他模块需要向该模块发送消息时,只需将封装好的message压入对端模块队列,本模块进行消息接收时,从本模块队列依次取出message,进行解析。
312 0
|
C语言 芯片
STM32学习笔记(5) 串口通讯-接收与发送
一个码元就是一个脉冲信号,一个脉冲信号有可能携带1bit数据,也有可能携带2bit数据、4bit数据!你发送一个脉冲信号,如果就可以携带4bit数据,肯定发送速率更快啊!
495 0
|
移动开发 缓存 物联网
串口接收并处理数据流程|学习笔记
快速学习串口接收并处理数据流程
串口接收并处理数据流程|学习笔记
|
消息中间件 物联网 Linux
Msgrcv 接收消息|学习笔记
快速学习 Msgrcv 接收消息
Msgrcv 接收消息|学习笔记
LINUX编程实战指发送UDP消息
LINUX编程实战指发送UDP消息
|
消息中间件 RocketMQ 开发者
发送异步消息|学习笔记
快速学习发送异步消息
|
数据采集 异构计算
FPGA-串口通信的接收模块(发送接收模块)
FPGA-串口通信的接收模块(发送接收模块)
221 0