摘自:https://www.nps.ink/202460.html
參考鏈接:
openwrt中ubus的具體使用
openwrt ubus的wiki
[openwrt] 使用ubus實現進程通信
[openwrt] ubus實現進程間通信舉例
openwrt ubus簡介以及libubus開發說明
ubus [1] – ubusd
ubus [2] – libubus
ubus [3] – cli
libubox組件(1)——usock
libubox組件(2)——blob/blobmsg
libubox組件(3)——uloop
ubus數據結構和接口介紹
ubus簡介
ubus是為了OpenWrt中守護進程和應用程序之間通訊開發的,類似桌面的DBus,設計理念上與DBus基本保持一致,區別是簡化的API和簡練的模型,以適應embeddedrouter的特殊環境。與DBus一樣也是使用socket實現。
核心部分是ubusd守護進程,它提供了其他守護進程將自己注冊以及發送消息的接口。因為這個,接口通過使用Unixsocket來實現,並使用TLV(type-length-value)消息,ubus內部使用Blob_buf,Blob_attr等結構來表示。
ubus有兩種調用,一個是method調用,一個是notification,其中method包括等待函數返回和不用等待返回,notification是廣播和DBus的signal類似。ubus使用是先建立連接,然后把連接加入epollset中。
下面是它的一些調用API。
uloop_init(); 創建epoll句柄,最多監聽32個fd
ubus_connect(); 創建ubus連接
ubus_add_uloop(); 把創建的ubus連接注冊到epoll中。
ubus_add_object(); 注冊對象到的ubus連接。
uloop_run(); 等待I/O事件發生,調用相對應的對象的功能函數。
ubus_free(); 關閉ubus連接
uloop_done(); 關閉epoll句柄
ubusd啟動
屬於procd啟動的一項:
/etc/preinit –> /sbin/init –> /sbin/procd –> /sbin/ubusd
注冊ubus服務的應用
path | Description | Package |
---|---|---|
dhcp | dhcp server | odhcpd |
file | file | rpcd |
hostapd | acesspoints | wpad/hostapd |
iwinfo | wireless informations | rpcd iwinfo |
log | logging | procd |
mdns | mdns avahi replacement | mdnsd |
network | network | netifd |
service | init/service | procd |
session | Session management | rpcd |
system | system misc | procd |
uci | Unified Configuration Interface | rpcd |
ubus客戶端
ubus調試有一個命令行工具叫ubus,ubus可以和ubusd服務器交互(和當前所有已經注冊的服務).它對研究和調試注冊的命名空間以及編寫腳本非常有用。
可以調用帶參數和返回信息的方法,它使用友好的JSON格式。
ubus命令使用說明
ubus命令用於控制調試相關ubus接口,主要命令說明如下:
– 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
ubus list [-v] 該命令用於顯示當前ubus中注冊的接口,其中-v參數用以顯示各個接口的詳細信息。示例如下:
root@uplink:~# ubus list network network.device network.interface.lan network.interface.loopback network.interface.wan
root@uplink:~# 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": { }
ubus call 該命令用於調用ubus中當前注冊的接口。示例如下:
調用無參方法
root@uplink:~# 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": { } }
調用有參方法
root@uplink:~# 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 } }
ubus listen 用於監聽ubus相關事件,如果不指定事件名則監聽所有事件。(支持通配符*)
root@uplink:~# ubus listen & root@uplink:~# ubus call network.interface.wan down { "network.interface": { "action": "ifdown", "interface": "wan" } } root@uplink:~# 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" } }
ubus send 用於發送事件
root@uplink:~# ubus listen & root@uplink:~# ubus send foo '{ "bar": "baz" }' { "foo": { "bar": "baz" } }
ubus wait_for 用於等待指定項的注冊到ubus中。
libubus使用
使用ubus時需要引用一些動態庫,主要包括:
libubus.so:ubus向外部提供的編程接口,例如創建socket,進行監聽和連接,發送消息等接口函數。
libubox.so:ubus向外部提供的編程接口,例如等待和讀取消息。
libblobmsg_json.so,libjson.so:提供了封裝和解析json數據的接口,編程時使用libblobmsg_json.so提供的更靈活的接口函數。
ubus的應用場景和局限性
ubus可用於兩個進程之間的通信,並以類似json格式進行數據交互。ubus的常見場景為:
1)“客戶端–服務器”形式的交互,即進程A注冊一系列的服務,進程B去調用這些服務。
2)ubus支持以“訂閱 — 通知”的方式進行進程通信,即進程A提供訂閱服務,其他進程可以選擇訂閱或退訂該服務,進程A可以向所有訂閱者發送消息。
由於ubus實現方式的限制,在一些場景中不適宜使用ubus:
1)ubus用於少量數據的傳輸,如果數據量很大或是數據交互很頻繁,則不宜用ubus。經過測試,當ubus一次傳輸數據量超過60KB,就不能正常工作了。
2)ubus對多線程支持的不好,例如在多個線程中去請求同一個服務,就有可能出現不可預知的結果。
3)不建議遞歸調用ubus,例如進程A去調用進程B的服務,而B的該服務需要調用進程C的服務,之后C將結果返回給B,然后B將結果返回給A。如果不得不這樣做,需要在調用過程中避免全局變量的重用問題。