简介
ubus是新openwrt引入的一个消息总线,主要作用是实现不同应用程序之间的信息交互。
ubus启动后会在后台运行ubusd进程,该进程监听一个unix套接字用于与其他应用程序通信。其他应用程序可基于libubox提供的接口(或自己实现)与其通信。
使用ubus的方式主要有:1、向其注册消息或控制接口。2、向其调用其他应用程序的消息或控制接口。3、向其注册监听关心的事件。4、向其发送事件消息。
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参数用以显示各个接口的详细信息。示例如下:
ubus list -v
'dhcp' @26b45f5d
"ipv4leases":{}
"ipv6leases":{}
'hostapd.wlan0' @5e03d420
"get_clients":{}
"del_client":{"addr":"String","reason":"Integer","deauth":"Boolean","ban_time":"Integer"}
ubus call 该命令用于调用ubus中当前注册的接口。示例如下:
ubus call dhcp ipv6leases
{
"device": {
"br-lan": {
"leases": [
{
"duid": "0001000119660ee***4e543***3c70",
"iaid": 3***72***5,
"hostname": "*******-PC",
"assigned": 3900,
"length": 128,
"ipv6": [
"fd23:a6ed:f19b::f3c"
],
"valid": -38000
}
]
}
}
}
ubus listen 用于监听ubus相关事件,如果不指定事件名则监听所有事件。(支持通配符*)
ubus send 用于发送事件
ubus wait_for 用于等待指定项的注册到ubus中。
libubus开发说明
libubus与需要与libubox配合使用,先贴出调用libubus的实例代码。
ubus.h
#ifndef UBUS_H_
#define UBUS_H_
#include <libubox/blob.h>
int ubus_send(const char *type, struct blob_attr *data);
int ubus_call(const char *path, const char *method,
struct blob_attr *data, struct blob_attr **ret);
int ubus_init(void);
void ubus_destory();
#endif
ubus.c
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <libubus.h>
#include <libubox/uloop.h>
#include <libubox/blobmsg_json.h>
#include <arpa/inet.h>
#include "ubus.h"
#include "test.h"
#include "debug.h"
#include "pubinfo.h"
struct ubus_context *ubus_ctx = NULL;
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
enum {GET_TYPE_FLOW, GET_TYPE_SPEED};
#define _unused __attribute__((unused))
#define _packed __attribute__((packed))
static struct blob_buf b;
/**********************************************************************
* pub policy
*********************************************************************/
enum {
UBUS_test_PUB_TOPIC,
UBUS_test_PUB_MSG,
__UBUS_test_PUB_MAX
};
static const struct blobmsg_policy test_pub_policy[] ={
[UBUS_test_PUB_TOPIC] = { .name = "topic", .type = BLOBMSG_TYPE_STRING },
[UBUS_test_PUB_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_TABLE },
};
/**********************************************************************
* Stats policy
*********************************************************************/
enum {
UBUS_STATS_OBJS,
__UBUS_STATS_MAX
};
static const struct blobmsg_policy stats_pub_policy[] ={
[UBUS_STATS_OBJS] = { .name = "obj", .type = BLOBMSG_TYPE_ARRAY },
};
/**********************************************************************
* sub policy
*********************************************************************/
enum {
UBUS_test_SUB_TOPICS,
__UBUS_test_SUB_MAX
};
static const struct blobmsg_policy test_sub_policy[] ={
[UBUS_test_SUB_TOPICS] = { .name = "topics", .type = BLOBMSG_TYPE_ARRAY },
};
/**********************************************************************
* subscribe method: subscribe a list of topics
*********************************************************************/
static int ubus_test_sub(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
unsigned ret=0;
struct blob_attr *tb[__UBUS_test_SUB_MAX];
blobmsg_parse(test_sub_policy, __UBUS_test_SUB_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[UBUS_test_SUB_TOPICS]){
debug(MSG_ERROR, "ubus test sub: no arguments!");
goto out;
}
update_test_topic_list(tb[UBUS_test_SUB_TOPICS]);
ret=1;
out:
blob_buf_init(&b, 0);
blobmsg_add_u8(&b, "result", ret);
ubus_send_reply(ctx, req, b.head);
return 0;
}
/**********************************************************************
* publish method: publish messages
*********************************************************************/
static int ubus_test_pub(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int ret=0;
struct blob_attr *tb[__UBUS_test_PUB_MAX];
char *message="", *topic;
blobmsg_parse(test_pub_policy, __UBUS_test_PUB_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[UBUS_test_PUB_TOPIC]) {
goto out;
}
topic=blobmsg_get_string(tb[UBUS_test_PUB_TOPIC]);
if (tb[UBUS_test_PUB_MSG]!=NULL) {
message=(char*)blobmsg_data(tb[UBUS_test_PUB_MSG]);
}
test_pub_msg(topic, message);
debug(MSG_INFO, "PUB: topic=%s msg=%s\n",topic,message);
ret=1;
out:
blob_buf_init(&b, 0);
blobmsg_add_u8(&b, "result", ret);
ubus_send_reply(ctx, req, b.head);
return 0;
}
/**********************************************************************
* publish method: simple publish messages
*********************************************************************/
static int ubus_test_spub(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int ret=0;
struct blob_attr *tb[__UBUS_test_PUB_MAX];
char *message="", *cmd;
blobmsg_parse(test_pub_policy, __UBUS_test_PUB_MAX, tb, blob_data(msg), blob_len(msg));
if (!tb[UBUS_test_PUB_TOPIC]){
debug(MSG_ERROR, "ubus call spub without topic");
goto out;
}
cmd=blobmsg_get_string(tb[UBUS_test_PUB_TOPIC]);
if (tb[UBUS_test_PUB_MSG]!=NULL){
message=blobmsg_format_json(tb[UBUS_test_PUB_MSG], true);
}
simple_pub_msg(cmd, message, 1);
ret=1;
out:
blob_buf_init(&b, 0);
blobmsg_add_u8(&b, "result", ret);
ubus_send_reply(ctx, req, b.head);
return 0;
}
/**********************************************************************
* list method: list current subscribe topic
*********************************************************************/
static int ubus_test_list(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
get_topic_list(&b);
ubus_send_reply(ctx, req, b.head);
return 0;
}
/**********************************************************************
* ubus method: ubus_pub_stats
*********************************************************************/
static int ubus_pub_stats(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int ret = 0;
struct blob_attr *tb[__UBUS_STATS_MAX];
blobmsg_parse(stats_pub_policy, __UBUS_STATS_MAX, tb, blob_data(msg), blob_len(msg));
if (tb[UBUS_STATS_OBJS]) {
pub_info(tb[UBUS_STATS_OBJS]);
ret = 1;
}
blob_buf_init(&b, 0);
blobmsg_add_u8(&b, "result", ret);
ubus_send_reply(ctx, req, b.head);
return 0;
}
/**********************************************************************
* list method: list current subscribe topic
*********************************************************************/
static int ubus_test_test(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
struct blob_attr *msg)
{
int status;
get_topic_list(&b);
debug(MSG_DEBUG, "==>begin wait status");
wait(&status);
debug(MSG_DEBUG, "==>after wait status:%d", status);
ubus_send_reply(ctx, req, b.head);
return 0;
}
/**********************************************************************
* test method
*********************************************************************/
static const struct ubus_method test_methods[] = {
UBUS_METHOD("pub",ubus_test_pub,test_pub_policy),
UBUS_METHOD("spub",ubus_test_spub,test_pub_policy),
UBUS_METHOD("sub",ubus_test_sub,test_sub_policy),
UBUS_METHOD("pubstats",ubus_pub_stats, stats_pub_policy),
UBUS_METHOD_NOARG("lsub",ubus_test_list),
UBUS_METHOD_NOARG("test",ubus_test_test),
};
/**********************************************************************
* test object
*********************************************************************/
static struct ubus_object_type test_object_type =
UBUS_OBJECT_TYPE("test", test_methods);
static struct ubus_object test_object = {
.name = "test",
.type = &test_object_type,
.methods = test_methods,
.n_methods = ARRAY_SIZE(test_methods),
};
static void ubus_connect_handler(struct ubus_context *ctx)
{
ubus_ctx = ctx;
debug(MSG_DEBUG, "ubus now connected.");
ubus_add_uloop(ctx);
ubus_add_object(ctx, &test_object);
return;
}
static struct ubus_auto_conn conn;
static void receive_ubus_data(struct ubus_request *req, int type, struct blob_attr *msg)
{
struct blob_attr **ret = (struct blob_attr **)req->priv;
*ret = blob_memdup(msg);
}
int ubus_send(const char *type, struct blob_attr *data)
{
if (!ubus_ctx || !type || !data) {
return -1;
}
return ubus_send_event(ubus_ctx, type, data);
}
int ubus_call(const char *path, const char *method,
struct blob_attr *data, struct blob_attr **ret)
{
uint32_t id;
int _ret;
if (ubus_ctx == NULL) {
return -1;
}
_ret = ubus_lookup_id(ubus_ctx, path, &id);
if (_ret) {
debug(MSG_ERROR, "lookup stats id error!");
return -1;
}
return ubus_invoke(ubus_ctx, id, method, data, receive_ubus_data, ret, 1000);
}
int ubus_init(void)
{
conn.cb = ubus_connect_handler;
ubus_auto_connect(&conn);
return 0;
}
void ubus_destory()
{
/*
ubus_remove_object(ubus, &main_object);
ubus_free(ubus);
*/
}
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。