20 嵌入式操作系统 | ubus:把自己的程序状态暴露出去

发布时间:2026/9/29 22:16:10

20 嵌入式操作系统 | ubus:把自己的程序状态暴露出去 嵌入式操作系统 | ubus把自己的程序状态暴露出去本课程开源地址Giteehttps://gitee.com/fujianxinxi/qianrushixitongyingyongkaifa.git课件、示例代码与验收脚本都在该仓库可直接git clone或下载 ZIP 使用。模块六 · 2 学时 · 环境VMware Ubuntu 20.04一句话概述讲清 ubus 的对象/方法模型先启动 ubusd再写一个注册 sensordata 对象的 C 程序把运行状态设备名、运行时长、被查询次数、传感器读数用 blobmsg 返回去最后用 ubus list 和 ubus call 一条命令一条命令地查询配套课堂练习与课后作业。本节目标能说出 ubus 是干什么的以及 ubusd 和 socket 文件的作用会写一个注册对象和方法、返回程序状态的 C 程序blobmsg 组返回值会先起 ubusd、再跑自己的程序、最后用ubus list/ubus call查询一、讲解内容1.1 知识讲解ubus 是什么。它是 OpenWrt 里的进程间通信IPC机制一个程序把自己的能力注册成一个对象对象里可以有若干方法别的程序或命令行的ubus通过名字就能调用它、拿回数据。路由器上执行ubus call network.interface.lan status查询网络状态用的就是这套机制。两个关键东西名字是什么ubusd一个守护进程相当于总机所有程序都连它/var/run/ubus/ubus.sock通信用的 unix socket 文件程序启动时先ls -l看它一眼就知道 ubusd 在不在这个路径是课时 15 编译时钉死在库里的默认值ubusd启动时会自动创建所在的目录。写一个 ubus 服务端就三步步骤函数干什么① 连上总机ubus_connect(NULL)连接 ubusd并ubus_add_uloop(ctx)让它的消息走 uloop② 注册对象ubus_add_object(ctx, obj)把自己登记成sensordata方法是status③ 等人调用方法回调别人ubus call时回调被调用用blobmsg组装返回值发回去blobmsg 是什么。它是 libubox 提供的一套键值对表接口先用blob_buf_init开一个空表再用blobmsg_add_string / add_u32 / add_double往里放字段最后通过ubus_send_reply发回去。命令行那边看到的就是一段 JSON正好接上下一课。1.2 操作步骤一条命令一步看现象第 1 步编译注意要链接 4 个库cd~/lab/课时20-ubus状态查询 gcc-Wall-Wextra-oubus_status ubus_status.c-lubus-lubox-lblobmsg_json-ljson-c为什么这么多-l程序用了 ubus 的接口-lubus、uloop 和 blobmsg-lubox、blobmsg 与 JSON 互转-lblobmsg_json -ljson-c。少一个就会看到undefined reference to ...。第 2 步先启动 ubusd终端 Asudoubusdls-l/var/run/ubus/ubus.sock现象出现 socket 文件说明总机已经开机srw-rw-rw- 1 root root 0 Sep 25 08:15 /var/run/ubus/ubus.sock第 3 步运行我们的程序终端 A会让出提示符前先打印三行sudo./ubus_status现象程序注册完就不动了正等别人来查① 连接 ubusd… 已连接 ② 已注册对象 sensordata方法 status ③ 现在到另一个终端执行 ubus list ubus call sensordata status第 4 步另开一个终端 B先看有哪些对象ubus list现象能看到我们刚注册的对象sensordata第 5 步查询状态这就是让程序把状态说出来ubus call sensordata status现象返回一段 JSON多查几次query_count会加 1{ device: ubuntu-gateway, uptime_s: 49321, query_count: 1, sensor: 温度, value: 25.500000, status: ok }再执行一次同样的命令{ device: ubuntu-gateway, uptime_s: 49321, query_count: 2, sensor: 温度, value: 26.000000, status: ok }第 6 步回到终端 A 看程序那边的现象← 收到第 1 次 ubus 查询 ← 收到第 2 次 ubus 查询两边对应上了终端 B 每执行一次ubus call终端 A 的程序回调就被调用一次——这就是查询程序状态的完整链路。第 7 步收工# 终端 A 按 CtrlC 停掉 ubus_status然后sudopkill-xubusd# 关掉总机1.3 常见错误与排查现象原因解决程序打印连不上 ubusdubusd 没启动先sudo ubusd 再ls -l /var/run/ubus/ubus.sock确认ubus list是空的自己的程序没在运行或刚退出先把./ubus_status跑起来它会一直等ubus call ... : Object not found对象名写错或程序没注册成功对象名必须是sensordata先ubus list看一眼ubus call没反应程序卡住了比如注册后没进 uloop检查是否调用了uloop_run()编译报undefined reference to ubus_...链接参数少写了四条都要写-lubus -lubox -lblobmsg_json -ljson-cubusd: command not found课时 15 没装好 ubus回课时 15 检查which ubusd应为/usr/local/sbin/ubusd二、学生练习本节命令速查表命令作用示例gcc … -lubus -lubox -lblobmsg_json -ljson-c编译 ubus 程序见第 1 步sudo ubusd 启动总机sudo ubusd ls -l /var/run/ubus/ubus.sock确认总机在ls -l /var/run/ubus/ubus.socksudo ./ubus_status运行自己的服务程序sudo ./ubus_statusubus list看有哪些对象ubus listubus call 对象 方法调用方法查询ubus call sensordata statussudo pkill -x ubusd关掉总机sudo pkill -x ubusd编号任务提示预期结果L20.1按步骤跑通查询先 ubusd → 再程序 → 再 callubus list有 sensordatacall 返回 JSONL20.2连查 3 次连续执行ubus callquery_count依次 1、2、3L20.3加一个字段在handle_status里加blobmsg_add_u32(b, heartbeat, 42)call 结果里多一项L20.4加第二个方法仿照status加一个ping方法返回{pong:true}ubus call sensordata ping能调通L20.5不启动 ubusd 就运行程序先sudo pkill -x ubusd程序打印连不上 ubusd并退出L20.6观察程序退出后的现象停掉 ubus_status 后再ubus list对象消失ubus call报 Object not found三、作业必做完成 L20.1、L20.2提交两个终端截图程序端 ubus call 的 JSON 输出并回答① ubusd 是什么socket 文件有什么用② 我们的程序是怎么把状态交出去的③ 为什么ubus call的输出是 JSON选做把课时 18 的采集程序和新知识合起来——在 ubus 对象里返回最后一次采集的温度让查询能拿到实时值提示把采集结果存到全局变量回调里读它提交截图 文字回答命名课时20-作业截图.png四、本节小结与下节预告本节把程序状态暴露给了别人启动 ubusd、注册sensordata对象、用 blobmsg 返回字段再用ubus list/ubus call查询。你注意到没有——ubus call打出来的就是 JSON。下节课我们就专门学 JSON怎么用它生成和解析数据。附录怎么运行 完整代码一个课件就够用先按附录 A 的顺序敲命令服务端/对端先开自己的程序后开再按附录 B 抄代码。行尾请用 LF。附录 A怎么运行注意先后顺序gcc-Wall-Wextra-oubus_status ubus_status.c-lubus-lubox-lblobmsg_json-ljson-csudoubusd# 终端A先启动 ubusdls-l/var/run/ubus/ubus.sock# 确认 socket 在sudo./ubus_status# 再运行自己的程序前台等着被查ubus list# 终端B看对象ubus call sensordata status# 查询状态返回 JSONsudopkill-xubusd# 收工附录 B文件ubus_status.c/* * ubus_status.c —— 课时 20注册一个 ubus 对象把程序状态暴露出去 * * 编译gcc -Wall -Wextra -o ubus_status ubus_status.c -lubus -lubox -lblobmsg_json -ljson-c * 运行sudo ./ubus_status # 需要先启动 ubusd见 ubus_check.sh start * * 做法三步 * ① 连上 ubusdubus_connect * ② 注册一个对象 sensordata里面有一个方法 status * ③ 别人执行 ubus call sensordata status 时我们的回调被调用 * 用 blobmsg 组一个表返回去ubus 命令行会把它打成 JSON */#includestdio.h#includesignal.h#includetime.h#includeunistd.h#includelibubox/blobmsg.h#includelibubox/uloop.h#includelibubus.hstaticstructubus_context*ctx;staticunsignedintquery_count0;/* 被查询了几次 *//* 方法回调有人 ubus call sensordata status 时uloop 会走到这里 */staticinthandle_status(structubus_context*c,structubus_object*obj,structubus_request_data*req,constchar*method,structblob_attr*msg){structblob_bufb{0};(void)c;(void)obj;(void)method;(void)msg;query_count;blob_buf_init(b,0);/* 准备一个空表 */blobmsg_add_string(b,device,ubuntu-gateway);/* 字符串字段 */blobmsg_add_u32(b,uptime_s,(uint32_t)(time(NULL)%100000));blobmsg_add_u32(b,query_count,query_count);/* 自己被查了几次 */blobmsg_add_string(b,sensor,温度);blobmsg_add_double(b,value,25.0query_count*0.5);/* 假装最新读数 */blobmsg_add_string(b,status,ok);ubus_send_reply(c,req,b.head);/* 把表发回去 */blob_buf_free(b);printf(← 收到第 %u 次 ubus 查询\n,query_count);fflush(stdout);return0;}/* 方法表本对象只有 status 一个方法不用参数 */staticconststructubus_methodstatus_methods[]{UBUS_METHOD_NOARG(status,handle_status),};staticstructubus_object_typestatus_typeUBUS_OBJECT_TYPE(sensordata,status_methods);staticstructubus_objectstatus_obj{.namesensordata,/* ubus call 时用的对象名 */.typestatus_type,.methodsstatus_methods,.n_methodsARRAY_SIZE(status_methods),};staticvoidon_signal(intsig){(void)sig;uloop_end();}intmain(void){uloop_init();signal(SIGINT,on_signal);signal(SIGTERM,on_signal);printf(① 连接 ubusd…\n);ctxubus_connect(NULL);/* NULL 用默认 socket /var/run/ubus/ubus.sock */if(!ctx){printf( 连不上 ubusd先执行 ./ubus_check.sh start 把 ubusd 起起来\n);return1;}printf( 已连接\n);ubus_add_uloop(ctx);/* 让 ubus 的消息也走 uloop 事件循环 */if(ubus_add_object(ctx,status_obj)!0){printf(② 注册对象失败\n);return1;}printf(② 已注册对象 sensordata方法 status\n);printf(③ 现在到另一个终端执行 ubus list ubus call sensordata status\n);fflush(stdout);uloop_run();/* 事件循环等别人来调用 */ubus_free(ctx);uloop_done();printf(\n④ 程序退出共被查询 %u 次\n,query_count);return0;}
延伸阅读

更多相关文章

2026/9/29 22:16:10

产业资本运作之运行逻辑

产业资本运作之运行逻辑何伏 融通资管 投资合伙人现在不是躺着就能赚钱的时代了。结构性筑底,就是把过去错配的资本,重新分配给高效的产业环节。产业资本运作不是借钱扩张,不是炒估值套利,它就是帮产业“做手术”;…

2026/9/29 22:11:09

Linux进程信号详解:从产生、保存到捕捉的完整排查记录

上周线上一个后台采集进程半夜挂了,日志最后一行是空的,没有堆栈,没有 core。运维说机器没重启,OOM 也没记录。我第一反应是收到了某个默认动作是终止的信号,比如 SIGTERM 或 SIGPIPE。这篇就把排查过程和我重新梳理的…

2026/9/29 22:11:09

Agent Skills实战指南:从安装到编写,解锁AI编程超级能力

最近圈子里聊AI编程,三句话不离skills。我刚开始以为又是营销号在造概念,直到自己动手把GitHub上的skills装进Claude Code,又照着社区规范写了一个用于数学建模论文排版的技能包之后,才明白为什么大家都说这是AI编程的“超级能力”…

2026/9/30 2:41:33

Java中toString()方法的正确使用技巧

咱们来详细说说在Java这玩意儿里面括号括起来的那个方法到底是怎么回事儿, 还有为啥这么重要的道理。在 Java 开发中,() 是我们最常用的方法之一。无论是调试程序、输出日志,还是快速查看对象内容,() 方法都起到了至关重要的作用。本篇博客将…

2026/9/30 2:41:33

一键将图片转为炫酷字符画

在这篇文章里头, 我们会去用到下面这些个知识点的哦。完整的一个程序, 那个用来把图片转换成字符画的py脚本。请先在命令行工具中找到存放图片文件的那个目录位置, 接着把当前路径切换到那个地方去执行操作, 然后启动名为图片转字符画.py的这个程序脚本并在其后面跟上参数.png这…

2026/9/30 2:41:33

cocos2d-x双人坦克大战demo:输入分发与碰撞判定实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 2:41:33

Verilog三段式状态机设计:状态编码、串口实现与跨平台映射

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/30 2:41:33

DETR深度解析:Transformer如何颠覆目标检测的端到端范式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/29 11:07:23

东莞市品牌网站建设报价常见报错与解决

东莞品牌网站建设报价单背后:一份保姆级建站教程避坑实录 网站做好了没人访问,这大概是很多老板最头疼的事。花了大几万做的品牌站,上线后流量惨淡,比路边摊还冷清。别急着骂外包公司,很多“东莞品牌网站建设报价”里藏着不少猫腻,比如用模板站冒充定制…

2026/9/29 21:48:03

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解

如何划分训练/验证集:Spirula Studio五种eval_mode策略详解 【免费下载链接】spirula-studio Cross-vendor 3D Gaussian Splatting trainer - video to splat to mesh, Vulkan or CUDA. 项目地址: https://gitcode.com/GitHub_Trending/sp/spirula-studio Sp…

2026/9/29 7:00:49

SEO怎么推广速查手册新手避坑实战指南

SEO怎么推广速查手册新手避坑实战指南 模板网站太丑不够用?别急着加滤镜,那是治标不治本。很多老板盯着后台流量掉得眼红,却还在纠结首页Banner的圆角是不是3像素。这就像穿着西装去挖土,姿势不对,努力白费。我整理这份 速查手册…

2026/9/30 0:01:22

MATLAB+Yalmip+CPLEX实战:综合能源系统优化调度全流程解析

做综合能源系统优化调度这活儿,最痛苦的不是建模本身,而是模型写完之后不知道该怎么求解。看论文里轻飘飘一句“采用Yalmip调用CPLEX求解”,自己上手时却往往卡在环境配置、变量声明、约束写法和求解状态判读上,一耗就是两三天。这…

2026/9/30 0:01:22

I3C比I2C快10倍?RK3576实战:速率、DTS配置与混合总线避坑指南

I3C 比 I2C 快 10 倍?这句话在嵌入式群里传了很久,每次都能吵出一堆截图。前段时间我正好在 RK3576 上调板级 I3C 接口,从控制器寄存器一路摸到 Linux DTS 配置,踩了不少坑,也把这笔速度账彻底算明白了。本文就用 RK35…

2026/9/30 0:01:22

字符串转对象:JSON.parse、new Function与URLSearchParams

“字符串转对象”这几个字,我在技术群里见过的问法至少有十几种:有人拿着一串{a:1,b:2}说 JSON.parse 直接报错,有人要从 URL 里抠出参数,还有人只是想把abc变成能挂属性的东西。js 这门语言里,字符串和对象之间的转换…

2026/9/29 3:53:39

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/29 9:46:12

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/29 6:36:14

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑