openwrt ubus简介以及libubus开发说明

转载:http://gofly.blog.51cto.com/4344767/1685199

简介

    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参数用以显示各个接口的详细信息。示例如下:       

1
2
3
4
5
6
7
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中当前注册的接口。示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

1
2
3
4
5
6
7
8
9
10
11
12
13
#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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
#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);
     */
}




本文出自 “记录点滴收获成长” 博客,请务必保留此出处http://gofly.blog.51cto.com/4344767/1685199

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值