玩转LuatOS消息系统:原理、流程与实战指南!

在LuatOS开发中,掌握消息机制意味着掌握了整个系统的“神经系统”。从SMS_INC到自定义new_msg,每一个消息都承载着状态变化的信号。本文将带你从零开始理解并运用这一关键机制。

LuatOS 的消息机制是其多任务协作和事件驱动编程的核心部分,主要通过 sys 核心库实现。

消息机制包括消息的发送、接收、订阅,以及系统消息的定义和使用,下面分别详细描述其原理和使用方法。

一、LuatOS 消息机制的原理

1.1 消息机制的基本原理描述

LuatOS 基于消息队列实现任务间通信,消息队列遵循先进先出(FIFO)原则。

消息机制配合 Lua 的协程(coroutine),可以非常丝滑的实现协作式多任务。

每一个协程的运行,是相互逻辑独立的;

在协程之间收发消息,可以实现不同协程间的通信。

消息发布者调用 LuatOS 的 API 发送全局消息或者定向消息。

订阅者通过回调函数或协程等待消息并处理,实现异步事件驱动。

消息调度流程大致如下:

(1)发布消息时,将消息及参数插入消息队列。

(2)消息分发函数从队列取出消息,根据消息 ID 查找订阅者列表。

(3)调用订阅者的回调函数或恢复协程,传递消息参数。

(4)订阅者处理消息,实现任务间通信和事件响应。

这种设计使得任务间解耦,消息驱动程序结构清晰,适合物联网设备的异步事件处理需求。

1.2 LuatOS 的消息队列

LuatOS 的消息队列有两个: 用户消息队列和系统消息队列。

1.2.1 用户消息队列:

用户消息队列的接收接口有三个: sys.waitUntil(),sys.waitMsg(),sys.subscribe()。

1.2.2 系统消息队列:

系统消息队列,存储在RTOS层,是RTOS操作系统的基本单元。

系统消息只能是使用 RTOS 的接口发送该消息,并且该发送消息接口是不开放给用户的。

系统消息队列的消息, 由 sys 核心库收取,并传送给对应的协程或者回调函数进行处理。

系统消息队列用于硬件事件,网络事件和定时器事件的传递。

比如说,当 Lua 脚本的某个协程运行了这行代码:

1.3 topic 和消息的差异

1.3.1 topic 和消息的差异

LuatOS 的消息,分为两类: topic 和消息。

topic 跟事件的概念是类似的,在 LuatOS 语境里面,topic 往往就是指事件。

topic 是全局消息,是广播消息。

而消息跟 topic 的不同,消息是有特定接收方的,而 topic 没有特定接收方。

LuatOS 的 sys.publish 接口是发布一个全局消息,也就是发布了一个 topic,也是发布了一个事件。

sys.subscribe 接口订阅了一个 topic,也就是订阅了一个事件。

sys.sendMsg, 是发送的消息, sys.waitMsg, 是等待和处理一个消息,是有特定的协程名字作为接收方的。

为了简化描述,在下文的其余部分,如果没有特别的说明,我们不再区分 topic 和消息的差异,统一把 topic 和消息称为消息。

1.3.2 mqtt 和 LuatOS 的 topic 的差异

mqtt 的 topic 与 sys 的 topic 有如下差异:

mqtt 的 topic 的订阅关系是服务器侧(borker)维护的,支持严格匹配和通配符匹配;

sys 的 topic 的订阅关系是 LuatOS 嵌入式系统内部维护的,只支持严格匹配。

1.4 LuatOS 消息的使用

尽管有用户消息队列和系统消息队列两种差异,但是在使用消息的时候,可以不关注这种差异。

用户只需要调用 sys.publish()接口和 sys.sendMsg()接口,按照自己的需要发送消息。

在接收和处理消息的时候,用 sys.subscribe()接口,指定某个消息的回调函数,这时候的消息,也不需要区分用户队列的消息还是系统消息,只要知道消息的名字,都可以指定消息的回调处理函数。

使用 sys.waitUtil()接口,sys.waitMsg 接口的时候,也不需要关心是用户队列的消息还是系统队列的消息,只要知道消息名字,都可以处理。

所有的发送消息,和接收处理消息的接口的使用,接下来都会做消息的介绍。

二、消息的发送

2.1 全局消息(sys 库)

全局消息,也可以理解为广播消息,所有的协程都是可以监听和处理的。

例如:

该消息发布后,会放入用户的消息队列,等待被订阅者处理。

2.2 定向消息(sys 库)

使用 sys.sendMsg(taskName, target, arg2, arg3, arg4) 向指定任务发送消息,可以指定接收消息的协程的名字,也可以同时给出消息携带的参数。

这种消息很适用于协程间的点对点通信。 例如:

该消息直接发送给指定任务,很适合请求-响应模型。

三、消息的接收处理

LuatOS 消息的接收处理有三种方式: 订阅消息,取消订阅息,等待消息。

3.1 订阅消息

通过 sys.subscribe(id, callback) 订阅指定消息的 ID,注册回调函数,当消息到达时调用回调函数进行处理。 例如:


3.2 取消订阅


3.3 等待消息


3.3.1 sys.waitUntil 接口

接口原型为:

使用示例:

该机制基于协程挂起和恢复实现,方便同步等待异步事件。

3.3.2 sys.waitMsg 接口

waitMsg 接口用于定向接收协程间的消息,用于协程间的通信,比较适合请求-响应的多协程合作的工作模式。

接口原型:

使用示例:

waitMsg 有如下几个特点:

(1)精准定向:可以通过 taskName 和 target 指定发送方与消息名称;

(2)参数传递:sendMsg 可以支持最多 3 个参数(通过 arg2~arg4 字段);

(3)适用协程之间的通信(如 HTTP 请求响应、任务间数据同步)。

四、sys 系统消息

4.1 系统消息是什么

LuatOS 框架预定义了一些系统消息,开发者可以直接订阅这些消息实现对硬件和系统事件的响应。

系统消息是由 LuatOS 内核或底层驱动自动发布的全局事件,面向所有订阅者广播,适用于硬件状态、网络事件等。

LuatOS 的系统消息,跟普通的消息并没有区别,但是由于是 LuatOS 底层发布的消息,并没有指定明确的接收协程名称,所以系统消息只能是当做全局的广播消息来处理。

用户可以使用 sys.WaitUntil 和 sys.subscibe 接口来处理系统消息,不能用 susplus.waitMsg 接口处理系统消息。

以下按功能模块分类详细说明所有系统消息及其触发条件和参数:

4.2 系统消息详解

详细的系统消息的定义和解读,参见如下链接:

LuatOS 系统消息详细定义:https://docs.openluat.com/osapi/sys_pub/

4.3 补充说明

1, 这些系统消息均为系统自动发布,不能由用户主动发布。

2, 可结合 LuatOS 库的 API(如 mobile.getCellInfo()、mobile.scell())获取详细数据。

五、LuatOS 的定时器机制

LuatOS 定时器机制基于消息驱动,常用的软件定时器接口集中在 sys 库中。

定时器到时后,会由 sys 库接收到定时器超时消息,并触发注册的回调函数或唤醒挂起的任务。

下面详细介绍其用法和原理。

5.1 LuatOS 定时器的基本原理


5.2 常用定时器 API 及用法

5.2.1 单次定时器

1,创建方式:

2,代码示例:

5.2.2 循环定时器

1, 创建方式:

2, 代码示例


5.2.3 停止定时器

1, 创建方式:

(1)停止指定定时器:

(2)停止所有绑定到某个回调的定时器:

2,代码示例


5.2.4 在任务中延时/等待消息

1, 函数说明

(1)sys.wait(ms):在 task 协程中挂起指定毫秒数,底层用定时器实现

(2)sys.waitUntil("MSG_ID", timeout_ms):等待某个消息或超时

代码示例:


5.2.5 判断定时器状态

1,使用方式

2, 代码示例

5.3 总结

1, sys.wait sys.waitUntil sys.waitMsg只能在 task 协程中使用。

2, 定时器到时后,底层会向消息队列推送 rtos.MSG_TIMER 消息,并附带定时器 ID。

3, 系统主循环 sys.run() 检测到该消息后,会查找定时器池,将参数传递给注册的回调或唤醒挂起的协程

4, 定时器总结表


六、消息机制的使用流程示例

如下的示例,展示了如何订阅消息、发布消息和在任务中等待消息,帮助理解 LuatOS 消息机制的核心用法。

该示例完整展示了 LuatOS 消息机制的核心用法,建议在真实设备运行时结合串口日志观察执行流程。

实际项目中可根据需要调整消息类型和定时器间隔。

6.1 代码示例

6.2 代码的执行流程说明

1, 初始化阶段:

2, 消息传递流程:

3, 定时器生命周期:

6.3 执行日志


6.4 关键 API 对照表


七、总结

消息机制原理:基于消息队列和协程,发布者将消息放入队列,订阅者通过回调或协程等待并处理,支持异步事件驱动。

发送消息:sys.publish() 广播消息,sys.sendMsg() 定向发送消息。

接收消息:sys.subscribe() 订阅消息,sys.waitUntil() 和 sys.waitMsg()阻塞等待消息,sys.unsubscribe() 取消订阅。

系统消息:框架预定义多种系统事件消息,直接订阅即可响应硬件和系统事件。

应用场景:网络模块通信、传感器数据广播、定时器事件处理等。

通过合理使用 LuatOS 的消息机制,可以实现高效、解耦的物联网应用架构,支持复杂的事件驱动和多任务协作。

今天的内容就分享到这里了~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值