OpenWrt开发必备软件模块——libubox

一、libubox软件模块

  • libubox是在2011年加入OpenWrt的代码库的。它是OpenWrt中的一个核心库,封装了一系列基础实用功能。
  • 提供的功能:主要提供事件循环、二进制块格式处理、Linux链表实现和一些JSON辅助处理。
  • 它的目的是以动态链接库方式来提供可重用的通用功能,给其他模块提供便利和避免再造轮子。
  • 这个软件由许多独立的功能组成,主要划分为3个软件包libubox、 jshn和libblobmsg-json。

二、libubox库

  • libubox软件包是OpenWrt 12.09版本之后增加到新版本中的一个基础库,在Open Wrt 15.07中有很多应用程序是基于libubox开发的,如ubus、netifd和freecwmp等。
  • 这样带来了一些好处:我们不用关注底层基础功能,可以基于libubox提供的稳定API来进行进一步的功能开发。
  • libubox主要提供以下三部分功能:
    • 提供多种基础通用功能接口,包含链表、平衡二叉树、二进制块处理、key-value链表、MD5等。
    • 提供多种sock接口封装。
    • 提供一套基于事件驱动的机制及任务队列管理功能。

libubox库的安装

  • 第一步:下载Libubox的软件包。
got clone https://github.com/yubo/libubox.git

  • 第二步:使用cmake生成Makefile。
    • 命令最后的一个点,代表当前路径。
    • 设置了两个编译开关(BUILD_LUA:BOOL、BUILD_EXAMPLES:BOLL)为 OFF,这两个分别是lua和使用示例,我们不进行编译,因此把编译选项关闭。
cmake -D BUILD_LUA:BOOL=OFF -D BUILD_EXAMPLES:BOLL=OFF .

  • 第三步: 进行编译(make)、安装(make install)。
    • 在进行编译时,编译过程中会输出编译进度百分比。
    • 编译完成之后进行安装,安装到系统目录中,需要使用管理员权限并输入密码,因此会加上sudo命令。
    • 安装内容包含头文件和动态链接库文件。头文件默认安装在/usr/local/include/libubox目录下,动态链接库libubox.so和 libubox.a安装在/usr/local/lib/目录下。
make;
sudo make install;

utils.h

  • utils.h提供简单实用功能,包括字节序转换、位操作、编译器属性包装、连续的内存分配函数、静态数组大小的宏、断言/错误的实用功能和 base64 编码解码等功能。

blob.h

  • blob.h提供二进制数据处理功能。有几种支持的数据类型,并可以创建块数据在socket上发送。整形数字会在libubox库内部转换为网络字节序进行处理。二进制块的处理方法是创建一个TLV(类型-长度-值)链表数据,支持嵌套类型数据,并提供设置和获取数据接口。Blobmsg 位于 blob.h 的上层,提供表格和数组等数据类型的处理。
  • TLV 是用于表示可变长度的数据格式,Type 表示数据的类型,Length 表示数据的长度, Value 存储着数据值。类型和长度的占用空间是固定的,在 libubox 库中共占用 4 个字节。 Value 的长度由 Length 指定。这样可以存储和传输任何类型的数据,只需预先定义服务器 和客户端之间的 TLV 的类型和长度的空间大小即可。在 DHCP 协议中也是采用 TLV 数据 类型来传输扩展数据的。

usock.h

  • usock.h 是一个非常简单的 socket 对象封装,以避免所有这些套接字接口库复杂调用。 可以创建 TCP、UDP 和 UNIX 套接字,包含客户端和服务器端、IPv4/IPv6、阻塞/非阻塞 等。可以通过 usock 函数来返回所创建的文件描述符。

uloop.h

  • uloop.h 是提供事件驱动机制接口,是基于epoll接口来实现的。uloop是一个I/O循环调度,将不同的文件描述符添加到轮询中。文件描述符fd的管理由 uloop_fd 结构来设置。仅需设置 fd 和事件发生时的回调函数,数据结构的其他部分供内部使用。超时管理 部分由 uloop_timeout 结构来管理,在定时时间到了之后调用回调函数,定时时间单位为 毫秒。
  • libubox常用uloop接口函数如表所示:
接 口 名 称含 义
uloop_fd_add将一个新文件描述符增加到事件处理循环中
uloop_fd_delete从事件处理循环中删除指定的文件描述符
uloop_init初始化 uloop.内部将调用 epoll_create 函数来创建 epoll 对象
uloop_run进入事件处理循环中
uloop_done反初始化 uloop,即释放内部 epoll 对象,删除内部的超时和 process 对象
uloop_end设置 uloop 内部结束循环标志
uloop_timeout_set设置定时器超时时间,并增加到链表中

三、jshn库

  • jshn是封装JSON对象的转换库,用于脚本语言生成JSON对象和将JSON对象数据取出。
  • jshn软件包含两个文件分别为:jshn和jshn.sh。

①jshn命令工具

  • 工具jshn提供以下两部分功能:
    • ①读取JSON格式的字符串,并组合为json_add_*命令导出到标准输出(stdout)中。
    • ②将环境变量中的设置组合为JSON字符串,并输出到标准输出中。
  • 常用选项:
    • -r:通过该选项来读取JSON格式字符串,并按照类型和名称导出到标准输出中。
    • -w:可以读取环境变量设置来生成JSON对象字符串。

②jshn.sh脚本

  • jshn.sh是利用jshn工具对JSON的操作进行的更为便利的封装。这样其他模块可以更方便地进行操作。
  • 主要提供以下三部分功能:
    • ①将JSON格式的字符串在环境变量中导入和导出。
    • ②将配置内容设置到环境变量中。
    • ③从环境变量中查询配置设置的值。
  • jshn.sh定义了大量的函数来对JSON数据进行编程操作。其内部实现是将定义的变量存储在shell空间中,这样可以用函数来操作每一个JSON对象。在操作完成后调用json_dump函数输出所有的内容。
  • 备注:在使用jshn.sh中的函数之前,需要使用source命令来执行jshn.sh。source命令是在当前环境下执行的,其设置的环境变量对其后面的命令都有效。 source命令和点命令“. ”等效(下面的演示案例有介绍)。
函 数 命 令含 义
json_init初始化JSON对象
json_add_string增加字符串数据类型,例如 json_add_string name zhang
json_dump以 JSON 格式输出所有增加的 JSON 内容
json_add_int增加整型数据,例如 json_add_int age 36
json_add_boolean增加布尔类型数据
json_set_namespace定义命名空间,即定义设置变量的前缀,这样变量就可以区分开来
json_load将所有内容读入到 JSON 对象中,并将这些对象设置到环境变量中
json_get_var从环境变量中读取 JSON 对象的值,例如 json_get_var ifdev device 获取 device 的 值并赋值给 ifdev 变量
json_get_type从环境变量中读取指定 JSON 对象的类型,例如 json_get_type iftype device 获取 device 的类型并赋值给 iftype 变量
json_get_keys从环境变量中读取 JSON 对象的所有名称,例如 json_get_keys keys 获取所有的名 称并赋值给 keys 变量
json_get_values从环境变量中读取 JSON 对象的所有值,例如 json_get_values values 将获取所有 的值并赋值给 values 变量
json_select

选择JSON对象。因为 JSON 对象会嵌套 JSON 对象,因此在操作内部嵌套对象 时首先选择所操作的 JSON 对象

例如:

  • 选择111这个对象进行操作:json_select 111
  • 选择上一层JSON对象:json_select ..
json_add_object增加对象,其后的操作均在该对象内部进行操作,该命令不需要参数
json_close_object完成对象的增加
json_add_array增加顺序数组,例如 json_add_array study,数组的内容后续通过 json_add_string 来增加
json_close_array完成顺序数组的增加
json_cleanup清除jshn所有设置的环境变量
  • 演示案例:下面是从netifd-proto.sh中摘出部分代码组织为一个独立的可执行脚本,该脚本将输出要执行的动作命令和参数。

source /usr/share/libubox/jshn.sh  #导出json_开头的函数,使后续可以调用

json_init                          #初始化

json_add_int action 2             #增加执行动作

json_add_int signal 9             #增加信号量

json_add_string "interface" "wan"  #增加操作的接口

env                                #这时将所有 JSON 字符串保存到环境变量中。可以使用该命令查看环境变量

json_dump                          #输出前面设置的所有 JSON 字符串

json_cleanup                       #jshn所有设置的环境变量

env                                #再次查看消失
  • 执行的效果图如下:

JSON与JSON结构介绍

  • JSON(JavaScript Object Notation)是一个轻量级的数据交换格式,易于人阅读和编写, 对程序来说也容易解析和产生。JSON是一个独立于语言的文本格式,使用各种语言都非常方便转换。
  • JSON有以下两种结构:
    • ①“名称/值”对集合对象。由顺序无关的“名称/值”对组成,以左花括号开始,以 右花括号结束。“名称/值”对之间由逗号分割,每一个名称后面跟着冒号。
    • ②有序的列表值,在大多数语言中,是一个数组、向量、链表或序列等。JSON 中 以数组形式来顺序存储。数组以左中括号开始,以右中括号结束,数据值以逗号分隔。
  • 以下为两种典型结构示例:
{ "action": "ifdown", "interface": "wan" }

{"dns_server": ["58.30.131.33 ", "211.99.143.33"] }

  • 我是小董,V公众点击"笔记白嫖"解锁更多OpenWrt资料内容。

相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页