硬件代理插件使用指南
更新时间:2025/10/15
在Gitcode上查看源码

硬件代理插件使用指南

1. 概述

硬件代理插件(hwproxy插件)提供了一种直接访问硬件的机制。通过该机制,各业务组件可以将自己的硬件访问逻辑封装为插件,在保证系统稳定性的前提下实现对硬件的直接控制。

其核心特点包括:

  1. 独占式总线访问:插件执行期间锁定总线资源,确保操作完整性
  2. 自定义协议处理:开发者可自由实现数据解析和协议转换逻辑
  3. 灵活控制:通过插件机制,开发者可以灵活控制硬件访问的粒度和时序

2. 系统架构与执行流程

2.1 访问流程图

2.2 执行流程说明

  1. 请求初始化:业务组件构建包含超时配置的上下文对象
  2. 插件加载:hwproxy从/opt/bmc/lualib/hwproxy目录动态加载Lua插件
  3. 命令校验:通过插件的has_cmd方法验证命令存在性
  4. 通道传递:将封装硬件操作能力的chip对象作为首个参数传递
  5. 自定义执行:插件通过run_cmd接口实现具体操作逻辑
  6. 结果返回:将处理结果以二进制数组形式返回给调用方

3. 核心接口详解

3.1 PluginRequest接口规范

3.1.1 函数签名

lua
-- 调用示例:result = chip:PluginRequest(ctx, plugin_name, cmd, args)
function PluginRequest(
    ctx: Context,          -- 上下文对象(可设置超时时间)
    plugin_name: string,   -- 插件名称(需与目录文件名一致)
    cmd: string,           -- 命令名称(插件中定义的函数)
    args: string           -- 参数(通过skynet.pack打包)
): string                  -- 返回值(通过skynet.unpack解析)

3.1.2 参数说明

参数名类型说明
ctxContext上下文对象,可通过ctx.timeout = N设置超时时间(默认120秒)
plugin_namestring插件文件名(需与/opt/bmc/lualib/hwproxy/目录下的Lua文件名一致)
cmdstring插件中定义的命令函数名(需通过has_cmd方法验证存在)
argsstring参数序列化字符串(使用skynet.packskynet.packstring打包)

3.1.3 返回值

  • 类型:字符串(需通过skynet.unpack解析为原始数据类型)
  • 内容:插件执行结果(如读取的二进制数据、错误码等)

4. 插件开发规范

每个有效插件必须包含以下结构: 每个有效插件必须包含以下结构:

lua
-- 基础插件模板
local plugin_class = class()

-- 命令存在性校验
function plugin_class:has_cmd(cmd_name)
    return self.commands[cmd_name] ~= nil
end

-- 命令执行入口
function plugin_class:run_cmd(chip, cmd, ...)
    return self.commands[cmd](chip, ...)
end

-- 命令实现集合
plugin_class.commands = {
    read_data = function(chip, offset, length)
        -- 具体操作逻辑
    end,
    write_data = function(chip, data)
        -- 具体操作逻辑
    end
}

return plugin_class

注意事项:

  1. 上述chip为hwproxy组件的chip.lua的内存实例对象,在具体操作逻辑中,只允许调用read和write函数
  2. 单个操作逻辑,原则上不允许连续执行1秒以上

5. 典型应用场景

5.1 长数据读取案例

lua
-- 插件实现:分块读取硬件日志
function read_log_by_mcu(chip, total_size)
    local buffer = ""
    local input = object_pool.new('input_args', OFFSET, DEFAULT_MASK, BLOCK_ACCESS_TYPE, READ_LEN, nil)
    while total_size > 0 do
        local chunk = math.min(total_size, MAX_CHUNK_SIZE)
        local ok, result = pcall(chip.read, chip, input)
        buffer = buffer .. result
        total_size = total_size - chunk
    end
    return buffer
end

-- 调用示例:日志导出
local function export_log_file(file_path)
    local ctx = context.new{ timeout=600 }
    local log_data = chip:PluginRequest(ctx, "logger", "read_log_by_mcu", 1024*1024)
    file:write(skynet.unpack(log_data))
end

6. 关键注意事项

6.1 代码结构要求

  • 插件必须继承基类并实现has_cmdrun_cmd方法
  • 命令函数需以commands.[命令名]形式定义

6.2 性能与资源

警告:插件执行期间独占总线,可能导致其他硬件访问超时

6.3 参数传递限制

  • 单次参数总长度有限制,超限需改用文件路径传递

6.4 超时配置

  • 默认超时时间为120秒(2分钟),长任务需显式设置ctx.timeout = N