1.簡介
openWRT提供了一個系統總線ubus,提供系統級的進程間通信(IPC)功能。
2.ubus命令使用說明
ubus list [-v] 該命令用於顯示當前ubus中注冊的接口,其中-v參數用以顯示各個接口的詳細信息。
ubus call 該命令用於調用ubus中當前注冊的接口。
bus listen 用於監聽ubus相關事件,如果不指定事件名則監聽所有事件。
ubus send 用於發送事件。
ubus wait_for 用於等待指定項的注冊到ubus中。
3.實現框架
ubus實現的基礎是unix socket,建立一個unix socket服務器和客戶端一般需要4步:creat server bind socket -> creat client to connect -> send msg -> handle msg.
ubus實現上這個框架並對msg傳輸和處理進行了封裝:
1.ubus提供了一個socket server:ubusd
2. ubus提供了創建socket client端的接口(提供了C、Shell、LUA三種現成的客戶端)
3.消息必須封裝位json格式
4.Client對消息的處理為{對象}{方法}的結構,發送請求方只需在消息中指定要調用的對象和方法的名字即可
使用ubus時需要引用一些動態庫,主要包括:
1.libubus.so(例如創建socket,進行監聽和連接,發送消息等接口函數)
2.libubox.so(ubus向外部提供的編程接口,例如等待和讀取消息)
3.libblobmsg.so(提供了封裝和解析json數據的接口)
4.實現原理
先舉個例子:
1. client1向ubusd注冊了兩個對象:“interface”和“dotalk”,其中“interface”對象中注冊了兩個method:“getlanip”和“setlanip”,對應的處理函數分別為func1()和func2()。“dotalk”對象中注冊了兩個method:“sayhi”和“saybye”,對應的處理函數分別為func3()和func4()。
2. 接着創建一個client2用來與client1通信,注意,兩個client之間不能直接通信,需要經ubusd(server)中轉。
3. client2就是在前面講到的shell/lua/C客戶端。假設這里使用shell客戶端,在終端輸入以下命令:
ubus的call命令帶三個參數:請求的對象名,需要調用的方法名,要傳給方法的參數。ubus call interface setlanip ‘{“ip”:“10.0.0.1”, “mask”:24}’
4. 消息發到server后,server根據對象名找到應該將請求轉發給client1,然后將消息發送到client1,client1進而調用func2()接受參數並處理,如果處理完成后需要回復client2,則發送回復消息。
5.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。如果不得不這樣做,需要在調用過程中避免全局變量的重用問題。