libubox analysis
libubox analysis
libubox
utils.h
提供了一些简单的实用工具函数。比如大小端转换,位图操作,编译器属性的封装,连续内存申请函数calloc_a,静态计算数组大小的宏,断言/调试的实用工具,苹果兼容的时钟获取时间的封装,base64编解码。
-
/*
-
*
-
* calloc_a(size_t len, [void **addr, size_t len,…], NULL)
-
* 申请一个足够大内存块来保存多个对齐的对象。
-
* 返回一个指针,指针指向全部对象(以第一个块开始)注意:释放这个指针将释放所有全部对象的内存
-
* 所有其它指针被保存在额外的addr参数指向的位置。
-
* 最后一个参数必须是NULL指针
-
*/
-
-
#define calloc_a(len, …) __calloc_a(len, ##VA_ARGS, NULL)
- * * *
- void *__calloc_a(size_t len, …);
- * * *
calloc_a示例:
-
#include <string.h>
-
#include <libubox/utils.h>
-
-
struct sleeper {
-
int aa;
-
int bb;
-
};
-
-
#define NAME_LEN 32
-
int main(int argc, char **argv)
- * * *
- {
- * * *
- struct sleeper *s;
- * * *
- char *name;
- * * *
- int *a1;
- * * *
- s = (struct sleeper *)calloc_a(sizeof(*s), &name, NAME_LEN, &a1, sizeof(*a1));
- * * *
- s->aa = 0x10101010;
- * * *
- s->bb = 0x20202020;
- * * *
- strncpy(name, “SSSSSSSSSSSSSSSSSSSSSSSS”, NAME_LEN-1);
- * * *
- name[NAME_LEN-1] = ‘\0’;
- * * *
- *a1 = 0xaaaaaaaa;
- * * *
- free(s);
- * * *
- return 0;
- * * *
- }
- * * *
-
-
(gdb) x/20x s
- * * *
- 0x602010: 0x10101010 0x20202020 0x53535353 0x53535353
- * * *
- 0x602020: 0x53535353 0x53535353 0x53535353 0x53535353
- * * *
- 0x602030: 0x00000000 0x00000000 0xaaaaaaaa 0x00000000
- * * *
![20f3b93b793885d2ade1e00e2624ed48.png](https://images2015.cnblogs.com/blog/964632/201704/964632-20170426105459365-2028379308.png)
-
/*
-
* 计算数组大小
-
*/
-
#ifndef ARRAY_SIZE
-
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
#endif
-
/*
-
* BUILD_BUG_ON基于一个GCC不支持负数数组,在编译时报错
-
* 但是4.4后GCC支持变长数组,不会引起编译器报错。
-
* 加入GCC优化选项后,编译时不会错,但是链接时会有找不到符号__BUILD_BUG_ON_CONDITION_FAILED的错误
-
*/
-
#define __BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
-
-
#ifdef OPTIMIZE
-
extern int __BUILD_BUG_ON_CONDITION_FAILED;
-
#define BUILD_BUG_ON(condition) \
- * * *
- do { \
- * * *
- __BUILD_BUG_ON(condition); \
- * * *
- if (condition) \
- * * *
- __BUILD_BUG_ON_CONDITION_FAILED = 1; \
- * * *
- } while(0)
- * * *
- #else
- * * *
- #define BUILD_BUG_ON __BUILD_BUG_ON
- * * *
- #endif
- * * *
FIXUP for BUILD_BUG_ON:
-
/* Force a compilation error if condition is true */
-
-#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
-
+#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition))
-
+
-
+/* Force a compilation error if condition is constant and true */
-
+#define MAYBE_BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2 * !!(cond)]))
-
-
/* Force a compilation error if condition is true, but also produce a
-
result (of value 0 and type size_t), so the expression can be used
-
e.g. in a structure initializer (or where-ever else comma expressions
- * * *
- aren’t permitted). */
- * * *
- -#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
- * * *
- +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); }))
- * * *
- +#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); }))
- * * *
-
/*
-
* CLOCK_REALTIME:这种类型的时钟可以反映wall clock time,
-
* 用的是绝对时间,当系统的时钟源被改变,
-
* 或者系统管理员重置了系统时间之后,这种类型的时钟可以得到相应的调整,
-
* 也就是说,系统时间影响这种类型的timer。
-
* CLOCK_MONOTONIC:用的是相对时间,他的时间是通过jiffies值来计算的。
-
*该时钟不受系统时钟源的影响,只受jiffies值的影响。
-
* clock_gettime比gettimeofday更加精确
-
* clock_gettime( ) 提供了纳秒的精确度
-
*/
- * * *
- #ifdef APPLE
- * * *
-
-
#define CLOCK_REALTIME 0
- * * *
- #define CLOCK_MONOTONIC 1
- * * *
-
-
void clock_gettime(int type, struct timespec *tv);
- * * *
-
-
#endif
- * * *
-
/*
-
* 大小端转换
-
*/
-
#ifdef GNUC
-
#define _GNUC_MIN_VER(maj, min) (((GNUC << 8) + GNUC_MINOR) >= (((maj) << 8) + (min)))
-
#else
-
#define _GNUC_MIN_VER(maj, min) 0
-
#endif
-
-
#if defined(linux) || defined(CYGWIN)
- * * *
- #include <byteswap.h>
- * * *
- #include <endian.h>
- * * *
-
-
#elif defined(APPLE)
- * * *
- #include <machine/endian.h>
- * * *
- #include <machine/byte_order.h>
- * * *
- #define bswap_32(x) OSSwapInt32(x)
- * * *
- #define bswap_64(x) OSSwapInt64(x)
- * * *
- #elif defined(FreeBSD)
- * * *
- #include <sys/endian.h>
- * * *
- #define bswap_32(x) bswap32(x)
- * * *
- #define bswap_64(x) bswap64(x)
- * * *
- #else
- * * *
- #include <machine/endian.h>
- * * *
- #define bswap_32(x) swap32(x)
- * * *
- #define bswap_64(x) swap64(x)
- * * *
- #endif
- * * *
-
-
#ifndef __BYTE_ORDER
- * * *
- #define __BYTE_ORDER BYTE_ORDER
- * * *
- #endif
- * * *
- #ifndef __BIG_ENDIAN
- * * *
- #define __BIG_ENDIAN BIG_ENDIAN
- * * *
- #endif
- * * *
- #ifndef __LITTLE_ENDIAN
- * * *
- #define __LITTLE_ENDIAN LITTLE_ENDIAN
- * * *
- #endif
- * * *
-
-
#define __u_bswap16(x) ({ uint16_t val = (x); ((uint16_t)(((val >> 8) & 0xffu) | ((val & 0xffu) << 8))); })
- * * *
-
-
#if _GNUC_MIN_VER(4, 2)
- * * *
- #define __u_bswap32(x) __builtin_bswap32(x)
- * * *
- #define __u_bswap64(x) __builtin_bswap64(x)
- * * *
- #else
- * * *
- #define __u_bswap32(x) bswap_32(x)
- * * *
- #define __u_bswap64(x) bswap_64(x)
- * * *
- #endif
- * * *
-
-
#if __BYTE_ORDER == __LITTLE_ENDIAN
- * * *
-
-
#define cpu_to_be64(x) __u_bswap64(x)
- * * *
- #define cpu_to_be32(x) __u_bswap32(x)
- * * *
- #define cpu_to_be16(x) __u_bswap16((uint16_t) (x))
- * * *
-
-
#define be64_to_cpu(x) __u_bswap64(x)
- * * *
- #define be32_to_cpu(x) __u_bswap32(x)
- * * *
- #define be16_to_cpu(x) __u_bswap16((uint16_t) (x))
- * * *
-
-
#define cpu_to_le64(x) (x)
- * * *
- #define cpu_to_le32(x) (x)
- * * *
- #define cpu_to_le16(x) (x)
- * * *
-
-
#define le64_to_cpu(x) (x)
- * * *
- #define le32_to_cpu(x) (x)
- * * *
- #define le16_to_cpu(x) (x)
- * * *
-
-
#else /* __BYTE_ORDER == __LITTLE_ENDIAN */
- * * *
-
-
#define cpu_to_le64(x) __u_bswap64(x)
- * * *
- #define cpu_to_le32(x) __u_bswap32(x)
- * * *
- #define cpu_to_le16(x) __u_bswap16((uint16_t) (x))
- * * *
-
-
#define le64_to_cpu(x) __u_bswap64(x)
- * * *
- #define le32_to_cpu(x) __u_bswap32(x)
- * * *
- #define le16_to_cpu(x) __u_bswap16((uint16_t) (x))
- * * *
-
-
#define cpu_to_be64(x) (x)
- * * *
- #define cpu_to_be32(x) (x)
- * * *
- #define cpu_to_be16(x) (x)
- * * *
-
-
#define be64_to_cpu(x) (x)
- * * *
- #define be32_to_cpu(x) (x)
- * * *
- #define be16_to_cpu(x) (x)
- * * *
-
-
#endif
- * * *
-
/*
-
* GCC支持的属性
-
*/
-
#ifndef __packed
-
#define __packed attribute((packed))
-
#endif
-
-
/*
-
* bitmap接口
-
*/
-
#ifndef BITS_PER_LONG
-
#define BITS_PER_LONG (8 * sizeof(unsigned long))
-
#endif
-
-
static inline void bitfield_set(unsigned long *bits, int bit)
-
{
-
bits[bit / BITS_PER_LONG] |= (1UL << (bit % BITS_PER_LONG));
- * * *
- }
- * * *
-
-
static inline bool bitfield_test(unsigned long *bits, int bit)
- * * *
- {
- * * *
- return !!(bits[bit / BITS_PER_LONG] & (1UL << (bit % BITS_PER_LONG)));
- * * *
- }
- * * *
-
-
#endif
- * * *
usock.h
封装来提供一个统一接口创建各种socket,例如创建TCP,UDP,UNIX sockets,客户端,服务器端,IPv4, IPv6和阻塞,非阻塞等。主要目的是调用usock(),返回你需要的fd.
-
/*
-
* AI_NUMERICHOST当此标志置位时,此标志表示调用中的节点名必须是一个数字地址字符串
-
*/
-
#define USOCK_TCP 0
-
#define USOCK_UDP 1
-
-
#define USOCK_SERVER 0x0100
-
#define USOCK_NOCLOEXEC 0x0200
-
#define USOCK_NONBLOCK 0x0400
-
#define USOCK_NUMERIC 0x0800
- * * *
- #define USOCK_IPV6ONLY 0x2000
- * * *
- #define USOCK_IPV4ONLY 0x4000
- * * *
- #define USOCK_UNIX 0x8000
- * * *
-
-
int usock(int type, const char *host, const char *service);
- * * *
用法例如:创建一个server socket:
-
server.fd = usock(USOCK_TCP | USOCK_SERVER | USOCK_IPV4ONLY | USOCK_NUMERIC, “127.0.0.1”, port);
uloop.h
Uloop部分是一个i/o的loop runner。负责轮询添加进来的不同的文件描述。
负责运行timer,帮助管理子进程。支持epoll和kqueue作为事件运行后端。
fd管理部分是用uloop_fd结构来创建的,只是添加fd和事件处理的回调函数。
结构体其它域给内部使用。
timeout管理部分,runqueue.h是在uloop之上实现了一些功能
timeout结构应该只初始化callback和pending=false(timeout={.cb=cb_func}可工作).使用uloop_timeout_set()添加uloop,不要使用_add(), _set()内部使用_add().
进程管理部分,
-
/*
-
* uloop的初始化,运行和结束
-
*/
-
int uloop_init(void);
-
void uloop_run(void);
-
void uloop_done(void);
-
/*
-
* EPOLL for linux
-
*/
-
#if defined(APPLE) || defined(FreeBSD)
-
#define USE_KQUEUE
-
#else
-
#define USE_EPOLL
-
#endif
-
/*
-
* event flag,读,写,边沿触发,或阻塞,或读写
- * * *
- */
- * * *
- #define ULOOP_READ (1 << 0)
- * * *
- #define ULOOP_WRITE (1 << 1)
- * * *
- #define ULOOP_EDGE_TRIGGER (1 << 2)
- * * *
- #define ULOOP_BLOCKING (1 << 3)
- * * *
-
-
#define ULOOP_EVENT_MASK (ULOOP_READ | ULOOP_WRITE)
- * * *
-
/*
-
* 文件描述符管理,初始化fd和uloop_fd_handler,然后使用
-
* uloop_add_fd()添加入uloop, flag表示哪些事件, READ/WRITE
-
*/
-
typedef void (*uloop_fd_handler)(struct uloop_fd *u, unsigned int events);
-
struct uloop_fd
-
{
-
uloop_fd_handler cb;
-
int fd;
-
bool eof;
- * * *
- bool error;
- * * *
- bool registered;
- * * *
- uint8_t flags;
- * * *
- };
- * * *
- int uloop_fd_add(struct uloop_fd *sock, unsigned int flags);
- * * *
- int uloop_fd_delete(struct uloop_fd *sock);
- * * *
-
/*
-
* timeout管理,初始化uloop_timeout_handler和time,使用
-
* uloop_timeout_add添加入uloop.
-
*/
-
typedef void (*uloop_timeout_handler)(struct uloop_timeout *t);
-
struct uloop_timeout
-
{
-
struct list_head list;
-
bool pending;
-
-
uloop_timeout_handler cb;
- * * *
- struct timeval time;
- * * *
- };
- * * *
-
-
int uloop_timeout_add(struct uloop_timeout *timeout);
- * * *
- int uloop_timeout_set(struct uloop_timeout *timeout, int msecs);
- * * *
- int uloop_timeout_cancel(struct uloop_timeout *timeout);
- * * *
- int uloop_timeout_remaining(struct uloop_timeout *timeout);
- * * *
-
/*
-
* 进程管理部分,初始化uloop_process_handler和pid,然后使用
-
* uloop_process_add添加入uloop
-
*/
-
-
typedef void (*uloop_process_handler)(struct uloop_process *c, int ret);
-
-
struct uloop_process
-
{
-
struct list_head list;
- * * *
- bool pending;
- * * *
-
-
uloop_process_handler cb;
- * * *
- pid_t pid;
- * * *
- };
- * * *
-
-
int uloop_process_add(struct uloop_process *p);
- * * *
- int uloop_process_delete(struct uloop_process *p);
- * * *
![98e6b29c3ffb220d7ea0c1ce5124022a.png](https://images2015.cnblogs.com/blog/964632/201704/964632-20170426105459865-1072597223.png)
blob.h
帮助以二进制传递数据。支持多种数据类型,创建的blobs可以在任何socket上发送。
大小端问题已经在库里解决了。
方法是创建一个type-value chained数据,支持嵌套数据,在blogmsg.h里有使用。
-
struct blob_attr {
-
uint32_t id_len; /** 高1位为extend标志,高7位存储id,
-
* 低24位存储data的内存大小 */
-
char data[]; /** 每个data按照256字节对齐 通过长度来索引下个data位置. */
-
} __packed;
-
-
struct blob_buf {
-
struct blob_attr head; /* 在嵌套时使用 */
-
bool (*grow)(struct blob_buf *buf, int minlen);
-
int buflen; /** 总buf长度 */
- * * *
- void buf; /* 指向第一个data(blob_attr)的基地址 */
- * * *
- };
- * * *
-
-
extern int blob_buf_init(struct blob_buf *buf, int id);
- * * *
![images/2187162543-54768f7f86bed.jpg](https://images2015.cnblogs.com/blog/964632/201704/964632-20170426105500084-1244656871.png)
2187162543-54768f7f86bed.jpg
![images/231588333-54769026b0c34.jpg](https://images2015.cnblogs.com/blog/964632/201704/964632-20170426105501365-906599681.png)
231588333-54769026b0c34.jpg