跳转至

sysplus - sys库的强力补充

一. sysplus 模块核心功能概述

sysplussys 模块的扩展库,主要提供 增强的任务消息机制;

sys 模块中,使用publish和waitUntil组合时,在publish某个消息之前,要求waitUntil语句已经在阻塞等待这个消息,对代码编程的时序要求比较高,稍微不注意,就有可能出现waitUntil等不到消息的问题;

sysplus 模块的sendMsg和WaitMsg,增加了缓冲队列存储,可以很好的解决这个问题;

sys 模块是 LuatOS 的核心库,提供 任务管理、定时器、事件机制 等基础功能,是开发网络通信、传感器控制等应用的核心工具。

建议 sysplussys 一起阅读。


二. API 函数详解

(1) 任务管理

sysplus.taskInitEx(func, taskName, cbFun, ...)

  • 功能:创建一个有taskName的任务线程。
  • 参数:

    • func:任务处理函数。
    • taskName:任务名称(字符串,必须全局唯一,不同的任务使用的taskName不要重复,否则逻辑运行会错乱)。
    • cbFun:回调函数,用于处理非目标消息(目标消息是指sysplus.waitMsg(taskName, msg, timeout)等待的msg消息,除此之外,通过sysplus.sendMsg(taskName, msg)给这个taskName发送的其他消息都属于非目标消息)。
    • ...:传递给 func 的可变参数。
    • 返回值:任务线程号(thread类型),目前LuatOS开放的接口,没有地方可以用到这个返回值,大家不用过多关心这个返回值以及 thread 类型。
    • 示例:
local function taskFunc()
    while true do
        -- 等待消息"task1_event"或者10秒超时
        local msg = sysplus.waitMsg("task1", "task1_event", 10000)  

        if msg then
            -- msg.target为"task1_event"
            log.info("waitMsg", "收到task1_event消息", msg.target)
        else
            log.info("waitMsg", "10秒超时,没有收到task1_event消息")
        end
    end
end

sysplus.taskInitEx(taskFunc, "task1", function(msg)
    log.warn("Received non-target message:", msg)
end)

sysplus.taskDel(taskName)

  • 功能:删除由 taskInitEx 创建的任务线程。
  • 参数:taskName(任务名称)。
  • 返回值:无。
  • 示例:
sysplus.taskDel("task1")  -- 删除名为 "task1" 的任务

(2) 事件消息管理

sysplus.waitMsg(taskName, target, timeout)

  • 功能:等待指定目标消息,支持超时控制。
  • 参数:

    • taskName:任务名称(接收消息的任务 ID)。
    • target:目标消息标识(字符串或 nil 表示接收任意消息)。
    • timeout:超时时间(毫秒,nil 表示无限等待)。
    • 返回值:

    • 成功:返回消息 table(包含 targetarg2arg3arg4 等参数)。

    • 超时:返回 false
    • 注意:会自动注册全局函数 sys_wait,需避免命名冲突。
    • 示例:
local msg = sysplus.waitMsg("task1", "data", 2000)
if msg then
    log.info("Received:", msg.target, msg.arg2)
else
    log.warn("Timeout")
end

sysplus.sendMsg(taskName, target, arg2, arg3, arg4)

  • 功能:向指定任务发送消息。
  • 参数:

    • taskName:目标任务名称。
    • target:消息标识(接收方 waitMsgtarget 匹配项)。
    • arg2~arg4:附加参数(可选)。
    • 返回值:true(成功)或 false(失败)。
    • 注意:自动注册全局函数 sys_send,需避免命名冲突。
    • 示例:
-- 向任务 "task1" 发送目标为 "data" 的消息,携带参数 100 和 "ok"
sysplus.sendMsg("task1", "data", 100, "ok")

sysplus.cleanMsg(taskName)

  • 功能:清除指定任务的消息队列。
  • 参数:taskName(任务名称)。
  • 返回值:无。
  • 示例:
sysplus.cleanMsg("task1")  -- 清空 "task1" 的消息队列

三. 使用场景与示例代码

示例 1:任务创建与消息通信

-- 定义任务函数
local function taskFunc()
    while true do
        local msg = sysplus.waitMsg("task1", "data")  -- 无限等待 "data" 消息
        if msg then
            log.info("Received Data:", msg.arg2, msg.arg3)
        end
    end
end

-- 创建任务
sysplus.taskInitEx(taskFunc, "task1", function(msg)
    log.warn("Unknown message:", msg)
end)

-- 主线程发送消息
sysplus.sendMsg("task1", "data", 42, "Hello from main")

示例 2:超时控制与消息清理

-- 等待消息并处理超时
local msg = sysplus.waitMsg("task2", "timeout_test", 1000)
if not msg then
    log.error("Message timeout!")
    sysplus.cleanMsg("task2")  -- 清理消息队列
end

四. 注意事项

1. 任务命名唯一性:

  • taskName 必须全局唯一,避免重复导致任务覆盖或冲突。

2. 全局函数注册:

  • sysplus.waitMsgsysplus.sendMsg 会自动注册全局函数 sys_waitsys_send,需确保不与其他代码冲突。

3. 消息队列限制:

  • 消息队列容量有限,需及时处理消息或调用 sysplus.cleanMsg 避免队列溢出。

4. 协程与阻塞:

  • sysplus.waitMsg 是阻塞操作,只能在使用sysplus.taskInitEx创建的任务的主函数中使用。

5. 参数传递限制:

  • sendMsg 最多支持 4 个参数(target + 3 个附加参数),需按需设计消息结构。

五. 常见问题

1. Q:如何处理消息队列溢出?

  • 定期调用 sysplus.cleanMsg 或在 cbFun 中清理无效消息。

2. Q:waitMsg 的超时时间如何设置?

  • timeoutnil 表示无限等待,0 表示立即返回,负数同 nil

3. Q:任务被删除后如何清理资源?

  • 使用 sysplus.taskDel 同时会自动清理相关消息队列。