blob blobmsg blobmsg_json什么意思

在openwrt的libubox中提供了blobmsg的库,这是一种什么样的消息呢?下面我们先了解一下下面几个概念。

  1. Blob

二进制大对象,是“Binary Large Object”的缩写。

blob提供二进制数据处理能力。有几种支持的数据类型,并可以创建块数据在socket上发送。整型数字会在libubox库内部转换为网络字节序进行处理。

二进制块的处理方法是创建一个TLV(类型-长度-值)链表数据,支持嵌套类型数据,并提供设置和获取数据接口。blob定义在blob.h中。

blob用于二进制对象序列化;blob主要在一些系统级组件(ubox/libubox/ubus/netifd)内部使用,一般应用不需要使用blob封装,blob用数据结构blob_attr表示。

blob_buf用于管理(多个)二进制大对象。

// blob_attr数据结构

struct blob_attr {

uint32_t id_len; //id占用最高字节,msb用于扩展,len占用低3个字节

char data[];

} __packed;

blob调用API

int main()

{

static struct blob_buf b;

struct blob_attr *attr1,*attr2;

char * str,*str1;

void *ptr;

struct blob_attr * pos;

int rem=0;

blob_buf_init(&b, 0);---初始化一块blob buf

//设置blob数据

attr1=blob_put_string(&b, 1, "hello");---存入一个字符串

attr2=blob_put_u8(&b, 2, 100);------存储一个字节的数字

//获取blob数据

str=blob_get_string(attr1);

int a1=blob_get_u8(attr2);

//打印数据

printf("str=%s\n",str);

printf("a1=%d\n",a1);

//输出有效数据地址 和 id

ptr=blob_data(attr1); // blob_data

printf("ptr=%p\n",ptr);

printf("id =%d",blob_id(attr1)); //blob_id

rem=12;

__blob_for_each_attr(pos,attr1,rem) //遍历

{

str1=blob_get_string(pos);

printf("str1 =%s\n",str1);

}

return 0;

}

  1. blobmsg

blobmsg用于二进制对象网络序列化。嵌套在blob数据结构(blob_attr)的data区。因此形成:blob_buff <- blob_attr -< blobmsg,blob_buff可存储管理多个blob_attr,每个blob_attr又可存储管理一个blogmsg。且可存储在线性数据区,不需要链表指针。

blobmsg_policy用于解析和缓存blobmsg列表,一般声明为一个静态数组,用于指导消息解析。

blobmsg默认使用id为table。array类似C语言的数组,table类似C的结构。

struct blobmsg_hdr {

uint16_t namelen;

uint8_t name[];

} __packed;

// 解析blobmsg列表

struct blobmsg_policy {

constchar *name; // 与blobmsg_hdr->name对应

enum blobmsg_type type; // 策略值的类型,数据打包解包时作为blob_attr id

};

blobmsg根节点是一个纯粹的blob,所以blobmsg解析时需要注意:

(1)第一层解析,data必须取值为blob_data(root_blob),len必须取值为blob_len(root_blob)

(2)第二层及以上解析,data必须取值为blobmsg_data(sub_blob),len必须取值为blobmsg_data_len(sub_blob)

所以,应避免混合使用blob和blobmsg语义,比如第一层使用blob语义,第二层使用blobmsg语义。

  1. blobmsg_json

blobmsg_json用于json对象的序列化,json提供脚本级消息发送机制,如果应用需要脚本配合,则需要使用json。

示例

UCI配置文件: /etc/config/test

config policy test

option name 'test'

option enable '1'

option dns '1.1.1.1 2.2.2.2'

定义参数列表

enum {

POLICY_ATTR_NAME, /** name */

POLICY_ATTR_ENABLE, /** enable */

POLICY_ATTR_DNS, /** dns */

__POLICY_ATTR_MAX

};

staticconststruct blobmsg_policy policy_attrs[__POLICY_ATTR_MAX] = {

[POLICY_ATTR_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING },

[POLICY_ATTR_ENABLE] = { .name = "enable", .type = BLOBMSG_TYPE_BOOL },

[POLICY_ATTR_DNS] = { .name = "dns", .type = BLOBMSG_TYPE_ARRAY },

};

/** 定义BLOBMSG_TYPE_ARRAY类型参数的实际数据类型 */staticconststruct uci_blob_param_info policy_attr_info[__POLICY_ATTR_MAX] = {

[POLICY_ATTR_DNS] = { .type = BLOBMSG_TYPE_STRING },

};

staticconststruct uci_blob_param_list policy_attr_list = {

.n_params = __POLICY_ATTR_MAX,

.params = policy_attrs,

.info = policy_attr_info,

};

转化为blob

staticstruct uci_context *g_uci_ctx;

staticstruct blob_buf *b;

void

transform(constchar *config)

{

struct uci_context *ctx = g_uci_ctx;

struct uci_package *p = NULL;

if (!ctx) {

ctx = uci_alloc_context();

g_uci_ctx = ctx;

uci_set_confdir(ctx, NULL);

} else {

p = uci_lookup_package(ctx, config);

if (p)

uci_unload(ctx, p);

}

if (uci_load(ctx, config, &p))

return;

struct uci_element *e;

struct blob_attr *config = NULL;

uci_foreach_element(&p->sectons, e) {

struct uci_section *s = uci_to_section(e);

blob_buf_init(&b, 0);

uci_to_blob(&b, s, &policy_attr_list);

config = blob_memdup(b.head);

/**

* do something with `config`

* free(config), when not use it

*/

}

}

使用转换后的blob

void

foo(blob_attr *confg)

{

struct blob_attr *tb[__POLICY_ATTR_MAX];

blobmsg_parse(policy_attrs, __POLICY_ATTR_MAX, tb,

blob_data(config), blob_len(config));

/**

* do something with *tb[]

*/

}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
当ubus数据具有多层嵌套的BLOBMSG_TYPE_TABLE或BLOBMSG_TYPE_ARRAY类型时,可以使用递归的方式进行解析。下面是一个示例代码,演示了如何解析多层嵌套的ubus数据: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <libubox/blobmsg_json.h> void parse_blobmsg_table(const struct blob_attr *attr); void parse_blobmsg_array(const struct blob_attr *attr) { int rem; struct blob_attr *tb[BLOBMSG_TYPE_MAX + 1]; struct blob_attr *cur; blobmsg_for_each_attr(cur, attr, rem) { if (blobmsg_type(cur) == BLOBMSG_TYPE_TABLE) { parse_blobmsg_table(cur); } else if (blobmsg_type(cur) == BLOBMSG_TYPE_ARRAY) { parse_blobmsg_array(cur); } else { fprintf(stderr, "Unexpected blobmsg type\n"); } } } void parse_blobmsg_table(const struct blob_attr *attr) { int rem; struct blob_attr *tb[BLOBMSG_TYPE_MAX + 1]; struct blob_attr *cur; blobmsg_parse(tb, BLOBMSG_TYPE_MAX, blobmsg_data(attr), blobmsg_data_len(attr)); if (!tb[0]) { fprintf(stderr, "Failed to parse blobmsg table\n"); return; } blobmsg_for_each_attr(cur, tb[0], rem) { if (blobmsg_type(cur) == BLOBMSG_TYPE_TABLE) { parse_blobmsg_table(cur); } else if (blobmsg_type(cur) == BLOBMSG_TYPE_ARRAY) { parse_blobmsg_array(cur); } else { // Handle individual values // You can access the value using blobmsg_get_type() and blobmsg_get_* functions const char *key = blobmsg_name(cur); int val = blobmsg_get_u32(cur); printf("Key: %s, Value: %d\n", key, val); } } } int main() { // Example ubus data in JSON format const char *json_data = "{\"table\":{\"nested_table\":{\"array\":[1,2,3]},\"value\":123}}"; struct blob_attr *attr; struct blob_buf buf; blob_buf_init(&buf, 0); if (blobmsg_add_json_from_string(&buf, json_data) != 0) { fprintf(stderr, "Failed to parse JSON data\n"); return 1; } attr = buf.head; if (!attr) { fprintf(stderr, "Empty blobmsg data\n"); return 1; } parse_blobmsg_table(attr); return 0; } ``` 在这个示例代码中,我们使用了libubox库中的函数来解析ubus数据。首先,我们将JSON格式的ubus数据转换为blobmsg格式,然后使用parse_blobmsg_table函数进行解析。在解析过程中,如果遇到嵌套的BLOBMSG_TYPE_TABLE类型或BLOBMSG_TYPE_ARRAY类型,就会递归调用相应的解析函数。 在parse_blobmsg_table函数中,我们使用了blobmsg_type和blobmsg_for_each_attr函数来遍历解析后的数据。对于嵌套的BLOBMSG_TYPE_TABLE和BLOBMSG_TYPE_ARRAY类型,我们会分别调用parse_blobmsg_table和parse_blobmsg_array函数进行解析。对于其他类型,我们可以使用blobmsg_get_*函数来获取具体的值。 请注意,这只是一个简单的示例代码,实际的解析过程可能更加复杂,需要根据具体的ubus数据结构和需求进行适当的调整。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

李小白20200202

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值