OpenWrt开发必备软件模块——系统总线ubus

一、ubus模块介绍

  • OpenWrt 提供了一个系统总线ubus,它类似于Linux桌面操作系统的d-Bus,目标是提供系统级的进程间通信(IPC)功能。ubus在设计理念上与d-Bus基本保持一致,提供了系统级总线功能,与d-Bus相比减少了系统内存占用空间,这样可以适应于嵌入式Linux操作系统的低内存和低端CPU性能的特殊环境。
  • ubus是OpenWrt的RPC工具,是OpenWrt的微系统总线架构,是在2011年加入OpenWrt中的。为了提供各种后台进程和应用程序之间的通信机制,ubus工程被开发出来。
  • ubus模块由3部分组成:
    • ubusd精灵进程。
    • ubus接口库(libubus.so)。
    • ubus命令行工具。
  • ubus代码基于LGPL2.1发布,代码地址为http://git.openwrt.org/project/ubus.git,在OpenWrt 12.09版开始正式使用。

二、ubusd精灵进程

  • ubus模块的核心是ubusd精灵进程,它提供了一个总线层,在系统启动时运行,负责进程间的消息路由和传递。其他进程注册到 ubusd进程进行消息的发送和接收。这个接口是用Linux文件socket和TLV(类型-长度-值)收发消息来实现的。每一个进程在指定命名空间下注册自己的路径。每一个路径都可以提供带有各种参数的多个函数处理过程,函数处理过程程序可以在完成处理后返回消息。
  • /etc/init.d/ubus:ubusd精灵进程是由/etc/init.d/ubus启动的,ubusd精灵进程在系统进程启动完成之后立即启动。它是在网络进程 netifd之前启动的,该进程监听一个文件套接字接口和其他应用程序通信。
  • 当ubusd精灵进程启动之后:其他应用程序可基于libubus提供的接口或使用ubus命令行程序来和ubusd进程进行通信。
  • ubus是为进程间发送消息而设计的,不适合传输大量数据(进程间传输大量数据应采用共享内存)。

原理

  • ubus是一个总线型消息服务器,任何消息均通过ubusd进程传递,因此多个进程在相互通信时,均通过ubus收发消息。

ubus提供的功能主要有以下4个方面

  • 提供注册对象和方法供其他实体调用。
  • 调用其他应用程序提供的注册对象的控制接口。
  • 在特定对象上注册监听事件。
  • 向特定对象发送事件消息。

对象与方法

  • ubus将消息处理抽象为对象(object)和方法(method)的概念。一个对象中包含多个方法。对象和方法都有自己的名字,发送请求方在消息中指定要调用的对象和方法名字即可。

订阅的概念

  • ubus的另外一个概念是订阅(subscriber)。客户端需要向服务器注册收到特定消息时的处理方法。这样当服务器在状态发生改变时会通过ubus总线来通知给客户端。

传递的消息格式TLV

  • ubus可用于两个进程之间的通信,进程之间以TLV格式传递消息,用户不用关心消息的实际传输格式。
  • ubus能够以JSON格式和用户进行数据交换。

ubusd精灵进程的两种应用场景

  • ①客户端/服务器模式:即进程A提供一些逻辑较复杂的记忆状态的服务,并且常 驻内存中。进程 B 以命令行工具或函数 API 形式调用这些服务。
  • ②订阅通知模式:即设计模式中的观察者模式。定义了对象间的一种一对多的依赖 关系,以便当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并自动更新。 即进程 A 作为服务器,当对象状态改变时通知给它所有的订阅者。

三、ubus接口库(libubus.so)

  • libubus提供的接口函数如表:
函数含义
ubus_add_object将对象加入的ubus空间中,即客户端可以访问对象。
ubus_register_subscriber增加订阅通知。
ubus_connect连接指定的路径,创建并返回路径所代表的ubus上下文。
ubus_send_reply执行完成方法调用后发送响应。
ubus_notify给对象所有的订阅者发送通知。
ubus_lookup查找对象,参数path为对象的路径,如果为空则查找所有的对象。cb为回调函数,对查找结果进行处理。
ubus_lookup_id查找对象的id,并将id参数在指针中返回。
ubus_invoke调用对象的方法。
ubus_register_event_handler注册事件处理句柄。
ubus_send_event发送事件消息。
  • 例如:netifd模块就是通过libubus动态链接库提供的API接口向ubus总线注册了很多对象和方法。

四、ubus命令行工具

  • ubus命令行工具也使用libubus提供的API接口来和ubusd服务器交互。这在调试注册的命名空间对象和编写shell脚本时非常有用。ubus调用参数和返回响应都使用非常友好的JSON格式。ubus提供5种命令来进行消息通信。
  • 命令格式如下:

list命令

  • list命令在默认情况下,输出所有注册到ubus RPC服务器的对象。
  • list命令是通过调用ubus_lookup接口函数来列出所有的服务器对象的。返回信息由传入ubus_lookup函数的第三个参数receive_list_result处理,这个参数是一个回调函数,负责将结果输出到屏幕上。
  • 如果使用-v参数:指定对象(命名空间路径)的所有方法和参数将全部输出屏幕中。
  • 案例:下面输出所有注册到ubus RPC服务器的对象。
ubus list

  • 案例:下面列出了局域网接口对象的所有方法和参数(但是这个命令运行时出错,下面只给出了书中的截图)。
ubus list network.interface.lan -v 

call命令

  • Call命令在指定对象里调用指定的方法并传递消息参数。
  • Call命令首先调用ubus_ lookup_id函数找到指定对象的ID,然后通过ubus_invoke函数调用来请求服务器,返回的结果使用 receive_call_result_data来处理。
  • 消息格式必须是合法的JSON字符串格式,根据函数签名来传递正确的JSON字符串作为方法参数。
  • 案例:
ubus call network.device status '{"name":"eth0"}'

listen

  • listen命令设置一个监听套接字来接收服务器发出的消息。
  • listen 命令是通过ubus_register_event_handler函数来注册事件回调处理函数的。
  • 案例:所示的代码是在一 个终端窗口启动监听,在另外一个窗口执行调用down和up方法,然后就会在第一个窗口上观察到对象状态发生改变。
  • 第一步:设置一个监听套接字,之后窗口属于阻塞。

  • 第二步:我们开启另一个窗口来用ubus的call命令来设置“network.interface.lan”对象属性为down,设置完成之后因为lan网络接口的服务关闭了,因此我们的SSH服务也断开了。

  • 但是在另一个窗口仍然可以接收到提示信息。

  • 第三步:因为SSH服务断开,因此我们来到源主机中使“network.interface.lan”对象属性为up。

  • 此时,在监听端可以看到,又接收到了一条信息。

send命令

  • send命令用于发出一个通知事件,这个事件可以使用listen命令监听到。
  • send 命令是 通过调用ubus_send_event函数来实现的。
  • 命令行的发送数据格式必须为JSON格式,在程序中通过调用 blobmsg_add_json_from_string函数转换为ubus的TLV格式。
  • 如果有多个监听客户端,多个监听客户端会同时收到事件。
  • 发送通知事件通常需要两个参数,第一个参数为指定对象,第二个参数为事件消息内容。
  • 案例:下面首先在第一个终端启动监听hello对象的事件消息,然后在第二个终端使用send命令向hello对象发送通知消息。
  • 第一步:一个窗口监听。

  • 第二步:另一个窗口发送通知消息。

  • 第三步:可以看到监听窗口收到了消息。

wait_for命令

  • wait_for 命令用于等待多个对象注册到ubus中,当等待的对象注册成功后即退出。

  • 我是小董,V公众点击"笔记白嫖"解锁更多OpenWrt资料内容。

相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页