ubus使用例程

/*
 * Copyright (C) 2011-2014 Felix Fietkau <nbd@openwrt.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <unistd.h>
#include <signal.h>

#include <libubox/blobmsg_json.h>
#include "libubus.h"
#include "count.h"

static struct ubus_context *ctx;
static struct ubus_subscriber test_event;
static struct blob_buf b;

enum {
	HELLO_ID,
	HELLO_MSG,
	__HELLO_MAX
};

static const struct blobmsg_policy hello_policy[] = {
	[HELLO_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
	[HELLO_MSG] = { .name = "msg", .type = BLOBMSG_TYPE_STRING },
};

struct hello_request {
	struct ubus_request_data req;
	struct uloop_timeout timeout;
	int fd;
	int idx;
	char data[];
};

static void test_hello_fd_reply(struct uloop_timeout *t)
{
	struct hello_request *req = container_of(t, struct hello_request, timeout);
	char *data;

	data = alloca(strlen(req->data) + 32);
	sprintf(data, "msg%d: %s\n", ++req->idx, req->data);
	if (write(req->fd, data, strlen(data)) < 0) {
		close(req->fd);
		free(req);
		return;
	}

	uloop_timeout_set(&req->timeout, 1000);
}

static void test_hello_reply(struct uloop_timeout *t)
{
	struct hello_request *req = container_of(t, struct hello_request, timeout);
	int fds[2];

	blob_buf_init(&b, 0);
	blobmsg_add_string(&b, "message", req->data);
	ubus_send_reply(ctx, &req->req, b.head);

	if (pipe(fds) == -1) {
		fprintf(stderr, "Failed to create pipe\n");
		return;
	}
	ubus_request_set_fd(ctx, &req->req, fds[0]);
	ubus_complete_deferred_request(ctx, &req->req, 0);
	req->fd = fds[1];

	req->timeout.cb = test_hello_fd_reply;
	test_hello_fd_reply(t);
}

static int test_hello(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg)
{
	struct hello_request *hreq;
	struct blob_attr *tb[__HELLO_MAX];
	const char format[] = "%s received a message: %s";
	const char *msgstr = "(unknown)";

	blobmsg_parse(hello_policy, ARRAY_SIZE(hello_policy), tb, blob_data(msg), blob_len(msg));

	if (tb[HELLO_MSG])
		msgstr = blobmsg_data(tb[HELLO_MSG]);

	size_t len = sizeof(*hreq) + sizeof(format) + strlen(obj->name) + strlen(msgstr) + 1;
	hreq = calloc(1, len);
	if (!hreq)
		return UBUS_STATUS_UNKNOWN_ERROR;

	snprintf(hreq->data, len, format, obj->name, msgstr);
	ubus_defer_request(ctx, req, &hreq->req);
	hreq->timeout.cb = test_hello_reply;
	uloop_timeout_set(&hreq->timeout, 1000);

	return 0;
}

enum {
	WATCH_ID,
	WATCH_COUNTER,
	__WATCH_MAX
};

static const struct blobmsg_policy watch_policy[__WATCH_MAX] = {
	[WATCH_ID] = { .name = "id", .type = BLOBMSG_TYPE_INT32 },
	[WATCH_COUNTER] = { .name = "counter", .type = BLOBMSG_TYPE_INT32 },
};

static void
test_handle_remove(struct ubus_context *ctx, struct ubus_subscriber *s,
                   uint32_t id)
{
	fprintf(stderr, "Object %08x went away\n", id);
}

static int
test_notify(struct ubus_context *ctx, struct ubus_object *obj,
	    struct ubus_request_data *req, const char *method,
	    struct blob_attr *msg)
{
#if 0
	char *str;

	str = blobmsg_format_json(msg, true);
	fprintf(stderr, "Received notification '%s': %s\n", method, str);
	free(str);
#endif

	return 0;
}

static int test_watch(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg)
{
	struct blob_attr *tb[__WATCH_MAX];
	int ret;

	blobmsg_parse(watch_policy, __WATCH_MAX, tb, blob_data(msg), blob_len(msg));
	if (!tb[WATCH_ID])
		return UBUS_STATUS_INVALID_ARGUMENT;

	test_event.remove_cb = test_handle_remove;
	test_event.cb = test_notify;
	ret = ubus_subscribe(ctx, &test_event, blobmsg_get_u32(tb[WATCH_ID]));
	fprintf(stderr, "Watching object %08x: %s\n", blobmsg_get_u32(tb[WATCH_ID]), ubus_strerror(ret));
	return ret;
}

enum {
    COUNT_TO,
    COUNT_STRING,
    __COUNT_MAX
};

static const struct blobmsg_policy count_policy[__COUNT_MAX] = {
    [COUNT_TO] = { .name = "to", .type = BLOBMSG_TYPE_INT32 },
    [COUNT_STRING] = { .name = "string", .type = BLOBMSG_TYPE_STRING },
};

static int test_count(struct ubus_context *ctx, struct ubus_object *obj,
		      struct ubus_request_data *req, const char *method,
		      struct blob_attr *msg)
{
	struct blob_attr *tb[__COUNT_MAX];
	char *s1, *s2;
	uint32_t num;

	blobmsg_parse(count_policy, __COUNT_MAX, tb, blob_data(msg), blob_len(msg));
	if (!tb[COUNT_TO] || !tb[COUNT_STRING])
		return UBUS_STATUS_INVALID_ARGUMENT;

	num = blobmsg_get_u32(tb[COUNT_TO]);
	s1 = blobmsg_get_string(tb[COUNT_STRING]);
	s2 = count_to_number(num);
	if (!s1 || !s2) {
		free(s2);
		return UBUS_STATUS_UNKNOWN_ERROR;
	}
	blob_buf_init(&b, 0);
	blobmsg_add_u32(&b, "rc", strcmp(s1, s2));
	ubus_send_reply(ctx, req, b.head);
	free(s2);

	return 0;
}

static const struct ubus_method test_methods[] = {
	UBUS_METHOD("hello", test_hello, hello_policy),
	UBUS_METHOD("watch", test_watch, watch_policy),
	UBUS_METHOD("count", test_count, count_policy),
};

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 server_main(void)
{
	int ret;

	ret = ubus_add_object(ctx, &test_object);
	if (ret)
		fprintf(stderr, "Failed to add object: %s\n", ubus_strerror(ret));

	ret = ubus_register_subscriber(ctx, &test_event);
	if (ret)
		fprintf(stderr, "Failed to add watch handler: %s\n", ubus_strerror(ret));

	uloop_run();
}

int main(int argc, char **argv)
{
	const char *ubus_socket = NULL;
	int ch;

	while ((ch = getopt(argc, argv, "cs:")) != -1) {
		switch (ch) {
		case 's':
			ubus_socket = optarg;
			break;
		default:
			break;
		}
	}

	uloop_init();
	signal(SIGPIPE, SIG_IGN);

	ctx = ubus_connect(ubus_socket);
	if (!ctx) {
		fprintf(stderr, "Failed to connect to ubus\n");
		return -1;
	}

	ubus_add_uloop(ctx);

	server_main();

	ubus_free(ctx);
	uloop_done();

	return 0;
}

ubus_subscribe用来向服务端注册订阅。

<think>好的,我需要帮助用户了解如何使用ubus,并提供示例教程和文档。首先,ubus是OpenWrt中的一个进程间通信系统,基于JSON-RPC。用户可能需要知道基本概念、安装步骤、常用命令以及示例。 首先,我应该解释ubus是什么,它的架构和组件,比如ubusd守护进程、ubus命令行工具,以及API库。然后,确保用户已经安装了必要的包,比如ubus、libubus等,并提供安装命令。 接下来,常用命令部分需要详细说明ubus list、call、send等命令的用法,并给出具体示例,比如获取网络接口信息或重启服务。此外,提供简单的客户端和服务端脚本示例会很有帮助,用户可以通过这些示例理解如何编写自己的ubus服务。 然后,用户可能需要了解如何查看官方文档,比如通过OpenWrt的Wiki或源代码。最后,生成相关问题,帮助用户进一步深入学习,比如性能分析、权限管理或与其他RPC框架的对比。 需要确保所有数学公式和代码块都符合格式要求,使用正确的LaTeX语法,并添加引用标识。同时,回答要结构清晰,分步骤说明,保持自然的中文表达。</think>### 如何使用 ubus:示例教程与文档 ubus 是 OpenWrt 系统中用于进程间通信的轻量级框架,基于 JSON-RPC 协议。以下从基础使用到示例的详细说明: --- #### 1. **ubus 基础概念** - **架构**:ubus 包含三个核心组件: - `ubusd`:守护进程,管理通信通道。 - `ubus`:命令行工具,用于交互。 - `libubus`:开发库,支持自定义服务[^1]。 - **通信模式**:支持发布/订阅、同步调用等。 --- #### 2. **安装与配置** 确保 OpenWrt 系统中已安装以下包: ```bash opkg update opkg install ubus ubus-cli libubus libblobmsg-json ``` --- #### 3. **常用命令与示例** - **列出所有可用服务**: ```bash ubus list ``` 输出示例:`network.interface.lan`(网络接口服务)。 - **调用服务方法**: ```bash ubus call network.interface.lan status ``` 返回 LAN 接口的详细状态(IP 地址、数据包统计等)。 - **监听事件**: ```bash ubus listen hostapd ``` 监听 Wi-Fi 热点(如 `hostapd`)的状态变化事件。 --- #### 4. **编写自定义服务(Python 示例)** - **服务端**(注册方法): ```python import ubus def hello(ctx, name="world"): return {"message": f"Hello, {name}!"} ubus.connect() ubus.register("demo", {"hello": hello}) ubus.loop() ``` - **客户端调用**: ```bash ubus call demo hello '{"name": "OpenWrt"}' ``` 输出:`{"message": "Hello, OpenWrt!"}` --- #### 5. **调试与文档** - **调试命令**: ```bash ubus -v call network.device status '{"name":"eth0"}' ``` `-v` 参数显示详细通信过程。 - **官方文档**: - OpenWrt Wiki:[UBus 文档](https://openwrt.org/docs/techref/ubus) - 源码参考:`/usr/share/libubus` 或 [ubus.h 头文件](https://git.openwrt.org/?p=project/ubus.git) ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值