为了在OpenWrt中提供各种守护程序和应用程序之间的进程间通信,开发了一个名为ubus的项目。它由几个部分组成,包括守护进程、库和一些额外的助手。
这个项目的核心是ubusd守护进程。它为其他守护进程提供了一个接口来注册自己以及发送消息。对于那些好奇的人,这个接口是使用Unix套接字实现的,它使用TLV(类型-长度-值)消息。
为了简化使用ubus(连接到它)的软件开发,已经创建了一个称为libubus的库。
每个守护进程都会在一个特定的命名空间下注册一组路径。每个路径都可以提供包含任意数量的参数的多个处理流程。每个处理流程回复一个响应消息。
ubus命令行客户端
ubus命令行工具允许与ubusd服务器(与所有当前注册的服务)交互。它对于调查/调试已注册的名称空间以及编写shell脚本非常有用。对于调用具有参数的过程和返回响应,它使用用户友好的JSON格式。下面是对其命令的解释。
root@OpenWrt:~# ubus Usage: ubus [<options>] <command> [arguments...] Options: -s <socket>: Set the unix domain socket to connect to -t <timeout>: Set the timeout (in seconds) for a command to complete -S: Use simplified output (for scripts) -v: More verbose output -m <type>: (for monitor): include a specific message type (can be used more than once) -M <r|t> (for monitor): only capture received or transmitted traffic Commands: - list [<path>] List objects - call <path> <method> [<message>] Call an object method - listen [<path>...] Listen for events - send <type> [<message>] Send an event - wait_for <object> [<object>...] Wait for multiple objects to appear on ubus - monitor Monitor ubus traffic |
list
要找出当前在总线上运行的哪些服务,只需使用ubus列表命令。这将显示在RPC服务器上注册的所有名称空间的完整列表:
root@OpenWrt:~# ubus list dhcp dnsmasq file iwinfo log luci luci-rpc network network.device network.interface network.interface.lan network.interface.loopback network.interface.wan network.interface.wan6 network.rrdns network.wireless service session system uci |
您可以通过指定一个服务路径来筛选该列表:
root@OpenWrt:~# ubus list network.interface.* network.interface.lan network.interface.loopback network.interface.wan network.interface.wan6 |
通过-v参数可以参数某一个对象的调用参数:
root@OpenWrt:~# ubus -v list network.interface.lan 'network.interface.lan' @099f0c8b "up": { } "down": { } "status": { } "prepare": { } "add_device": { "name": "String" } "remove_device": { "name": "String" } "notify_proto": { } "remove": { } "set_data": { } |
call
调用给定名称空间内的给定过程,并可选地向其传递参数:
root@OpenWrt:~# ubus call network.interface.wan status { "up": true, "pending": false, "available": true, "autostart": true, "uptime": 86017, "l3_device": "eth1", "device": "eth1", "address": [ { "address": "178.25.65.236", "mask": 21 } ], "route": [ { "target": "0.0.0.0", "mask": 0, "nexthop": "178.25.71.254" } ], "data": { } } |
参数必须是一个有效的JSON字符串,并根据函数签名设置键和值:
root@OpenWrt:~# ubus call network.device status '{ "name": "eth0" }' { "type": "Network device", "up": true, "link": true, "mtu": 1500, "macaddr": "c6:3d:c7:90:aa:da", "txqueuelen": 1000, "statistics": { "collisions": 0, "rx_frame_errors": 0, "tx_compressed": 0, "multicast": 0, "rx_length_errors": 0, "tx_dropped": 0, "rx_bytes": 0, "rx_missed_errors": 0, "tx_errors": 0, "rx_compressed": 0, "rx_over_errors": 0, "tx_fifo_errors": 0, "rx_crc_errors": 0, "rx_packets": 0, "tx_heartbeat_errors": 0, "rx_dropped": 0, "tx_aborted_errors": 0, "tx_packets": 184546, "rx_errors": 0, "tx_bytes": 17409452, "tx_window_errors": 0, "rx_fifo_errors": 0, "tx_carrier_errors": 0 } } |
listen
设置侦听套接字并监控传入事件:
root@OpenWrt:~# ubus listen & root@OpenWrt:~# ubus call network.interface.wan down { "network.interface": { "action": "ifdown", "interface": "wan" } } root@OpenWrt:~# ubus call network.interface.wan up { "network.interface": { "action": "ifup", "interface": "wan" } } { "network.interface": { "action": "ifdown", "interface": "he" } } { "network.interface": { "action": "ifdown", "interface": "v6" } } { "network.interface": { "action": "ifup", "interface": "he" } } { "network.interface": { "action": "ifup", "interface": "v6" } } |
send
发送事件通知:
root@OpenWrt:~# ubus listen & root@OpenWrt:~# ubus send foo '{ "bar": "baz" }' { "foo": { "bar": "baz" } } |
ubus http客户端
有一个叫做uhttpd-mod-ubus的uhttpd插件,它允许ubus call使用HTTP协议。例如,在LuCI2中可以通过/ubus URL(除非被ubus_prefix选项更改)来发送POST请求。
当通过ssh登录时,您可以直接、完全地访问ubus。然而,当您在uhttpd中访问/ubus url时,uhttpd首先查询您的呼叫是否被允许使用,以及提供ubus会话的人。*名称空间负责实现访问控制:
ubus call session access '{ "ubus_rpc_session": "xxxxx", "object": "requested-object", "function": "requested-method" }' |
ubus Lua 客户端
这甚至可以在lua脚本中使用ubus。当然,在lua中不可能直接使用本机库,因此已经创建了一个额外的模块。它只是称为ubus,是lua脚本和ubus之间的一个简单接口(它内部使用libubus)。

LUCI客户端

ubus vs dbus
D-Bus非常臃肿,它的C API使用起来非常烦人,并且需要编写大量的样板代码。事实上,纯C API非常烦人,以至于它自己的API文档说:“如果你直接使用这个低级别的API,你就会注册一些痛苦。”
ubus很小,其优点是易于使用常规的C代码,并且自动使所有导出的API功能也可以用于shell脚本,无需额外的努力。