最近一个项目需要使用到 libubox 开发,然而在开发过程中却遇到了几个问题,便有了学习libubox的契机,打算记录下来与大家一起分享交流。
目录
1、blob_buf_init(&g_swgwd_devinfo_buff, 0);
2、msgtab = blobmsg_open_table(&g_swgwd_devinfo_buff, "swgwd.devinfo");
3、blobmsg_add_string(&g_swgwd_devinfo_buff, "ipaddr", “192.168.1.1”);
4、blobmsg_add_string(&g_swgwd_devinfo_buff, "mac", “aa:bb:cc:11:22:33”);
5、blobmsg_close_table(&g_swgwd_devinfo_buff, msgtab);
一、源码下载
git clone https://github.com/yubo/libubox.git
二、熟悉结构体
从 blob.h、blobmsg.h 入手。
1、struct blob_attr 中的 d_len 占 32bits,分为三个域
高1位,31bit:是否为 extended。(当 data 包含头部 blobmsg_hdr 时为 1)
高7位,24 ~ 30 bits:id,或者说数据的类型(如 table,string,int ...)
低24位,0~23 bits:data 变长数组的长度
struct blob_attr {
uint32_t d_len;
char data[];
} __packed;
2、struct blob_buf 的 buf 便是多个 struct blob_attr 属性的连接与嵌套。
grow 为扩容函数,用于分配空间给 buf。
buflen 为 grow 分为空间的大小。
head 用于辅助操作,动态指向 buf 中的某个 struct blob_attr 节点。
struct blob_buf {
struct blob_attr *head;
bool (*grow)(struct blob_buf *buf, int minlen);
int buflen;
void *buf;
};
3、用于拓展 struct blob_attr 的 data。
比如:struct blob_attr *attr1 = xxx;
(struct blobmsg_hdr *)attr1 -> namelen = strlen("mac");
strcpy((struct blobmsg_hdr *)attr1 ->name, "mac");
strcpy(blobmsg_data(attr1), "aa:bb:cc:11:22:33");
这个时候 attr1 -> data 分为两部分,一部分是 struct blobmsg_hdr,另一部分是真实的数据。
struct blobmsg_hdr {
uint16_t namelen;
uint8_t name[];
} __packed;
三、剖析 blobmsg_buf
按照如下代码流程,逐段分析 blobmsg_buf 的内存变化:
struct blob_buf g_swgwd_devinfo_buff = {0};
blob_buf_init(&g_swgwd_devinfo_buff, 0);
msgtab = blobmsg_open_table(&g_swgwd_devinfo_buff, "swgwd.devinfo");
blobmsg_add_string(&g_swgwd_devinfo_buff, "ipaddr", “192.168.1.1”);
blobmsg_add_string(&g_swgwd_devinfo_buff, "mac", “aa:bb:cc:11:22:33”);
blobmsg_close_table(&g_swgwd_devinfo_buff, msgtab);
1、blob_buf_init(&g_swgwd_devinfo_buff, 0);
- (&g_swgwd_devinfo_buff)->brow = blob_buffer_grow,默认扩容函数
- 使用默认的扩容函数 calloc 了 256 字节空间,赋值给 (&g_swgwd_devinfo_buff)->buf
- (&g_swgwd_devinfo_buff)->buflen = 256
- new 一个 struct blob_attr blob_attr1,只使用了 .d_len
- (&g_swgwd_devinfo_buff)->head = (&g_swgwd_devinfo_buff)->buf
2、msgtab = blobmsg_open_table(&g_swgwd_devinfo_buff, "swgwd.devinfo");
- 找到 (&g_swgwd_devinfo_buff)->head->data 作为插入位置 pos
- new 一个 struct blob_attr blob_attr2,填充 .d_len 和 .data
- 更新 (&g_swgwd_devinfo_buff)->head 指向 blob_attr2
- 返回值 msgtab 用于后面的 blobmsg_open_close(msgtab) 时找到 blob_attr1 位置,然后更新其 .d_len。(msgtab 就是 buf->head - buf->buf 的 offsets,再加上 blob_cookie)

3、blobmsg_add_string(&g_swgwd_devinfo_buff, "ipaddr", “192.168.1.1”);
- 找到 (&g_swgwd_devinfo_buff)->head->data 作为插入位置 pos
- new 一个 struct blob_attr blob_attr3,填充 .d_len 和 .data
- 更新 (&g_swgwd_devinfo_buff)->head->d_len,也就是 blob_attr2->d_len

4、blobmsg_add_string(&g_swgwd_devinfo_buff, "mac", “aa:bb:cc:11:22:33”);
- 找到 (&g_swgwd_devinfo_buff)->head->data 作为插入位置 pos
- new 一个 struct blob_attr blob_attr4,填充 .d_len 和 .data
- 更新 (&g_swgwd_devinfo_buff)->head->d_len,也就是 blob_attr2->d_len

5、blobmsg_close_table(&g_swgwd_devinfo_buff, msgtab);
- 根据 msgtab 找到 "swgwd.devinfo" 的前一个 attr,即 blob_attr1。更新其 .d_len
- (&g_swgwd_devinfo_buff) -> head 指向 blob_attr1

6、补充
