ubus是OpenWrt中的进程间通信机制,类似于桌面版linux的dbus,Android的binder。ubus相当于简化版的dbus,ubus基于unix socket实现,socket绑定到一个本地文件,具有较高的效率;
unix socket是C/S模型,建立一个socket连接,server端和client端分别要做如下步骤:
1. 建立一个socket server端,绑定到一个本地socket文件,监听client的连接;
2. 建立一个或多个socket client端,连接到server端;
3. client端和server端相互发送消息;
4. client端或server端收到对方消息后,针对具体消息进行相应处理。
如下图所示:
ubus同样基于这套流程,其中ubusd实现server,其他进程实现client,例如ubus(cli)、netifd、procd;
两个client通信需要通过server转发。
ubusd
ubusd作为ubus的server端,已经由OpenWrt实现好了,不需要做任何修改,下面来分析一下ubusd的工作流程;
1. 通过usock来创建server端socket,且socket bind到文件”/var/run/ubus.sock”,开启listen,等到client的连接;
2. 将socket添加到uloop中poll,触发条件是read,也就是说server socket可读,则触发poll回调server_cb,server_fd的回调函数是server_cb;
static struct uloop_fd server_fd ={
.cb=server_cb,
};
server_cb中通过accept来接受client的连接,套接字函数accept执行退出之后会创建一个新的socket,新的socket的fd为accept函数值,而旧的socket不变,也就是accept之后,server端存在两个socket了,旧的socket依然用来listen,新的socket与client建立pair,用于和client的通讯;
根据新的socket的fd(int client_fd)来构建一个ubus_client对象,ubus_client的uloop回调函数是client_cb,将ubus_client插入到avl树中(struct avl_tree clients),每个向ubusd注册的client都在对应到avl树中的一个ubus_client;
ubusd_send_hello,向client端的socket发送一个字符串”hello”;
将ubus_client中的socket fd添加到uloop中去轮询监听,触发条件是read,回调函数是client_cb,也就是client发消息到server,则触发回调client_cb;
client_cb通过write或sendmsg来发消息给client,通过read或recvmsg来接收来自client的消息&#