libubox analysis

libubox analysis

libubox

utils.h

提供了一些简单的实用工具函数。比如大小端转换,位图操作,编译器属性的封装,连续内存申请函数calloc_a,静态计算数组大小的宏,断言/调试的实用工具,苹果兼容的时钟获取时间的封装,base64编解码。

  1. /* 


  2. *  


  3. * calloc_a(size_t len, [void **addr, size_t len,…], NULL) 


  4. * 申请一个足够大内存块来保存多个对齐的对象。 


  5. * 返回一个指针,指针指向全部对象(以第一个块开始)注意:释放这个指针将释放所有全部对象的内存 


  6. * 所有其它指针被保存在额外的addr参数指向的位置。 


  7. * 最后一个参数必须是NULL指针 


  8. */ 



  9. #define calloc_a(len, …) __calloc_a(len, ##VA_ARGS, NULL) 

  1. * * * 
  1. void *__calloc_a(size_t len, …); 
  1. * * * 

calloc_a示例:

  1. #include <string.h> 


  2. #include <libubox/utils.h> 



  3. struct sleeper { 


  4. int aa; 


  5. int bb; 


  6. }; 



  7. #define NAME_LEN 32 


  8. int main(int argc, char **argv) 

  1. * * * 
  1. * * * 
  1. struct sleeper *s; 
  1. * * * 
  1. char *name; 
  1. * * * 
  1. int *a1; 
  1. * * * 
  1. s = (struct sleeper *)calloc_a(sizeof(*s), &name, NAME_LEN, &a1, sizeof(*a1)); 
  1. * * * 
  1. s->aa = 0x10101010; 
  1. * * * 
  1. s->bb = 0x20202020; 
  1. * * * 
  1. strncpy(name, “SSSSSSSSSSSSSSSSSSSSSSSS”, NAME_LEN-1); 
  1. * * * 
  1. name[NAME_LEN-1] = ‘\0’; 
  1. * * * 
  1. *a1 = 0xaaaaaaaa; 
  1. * * * 
  1. free(s); 
  1. * * * 
  1. return 0; 
  1. * * * 
  1. * * * 

  1. (gdb) x/20x s 

  1. * * * 
  1. 0x602010:       0x10101010      0x20202020      0x53535353      0x53535353 
  1. * * * 
  1. 0x602020:       0x53535353      0x53535353      0x53535353      0x53535353 
  1. * * * 
  1. 0x602030:       0x00000000      0x00000000      0xaaaaaaaa     0x00000000 
  1. * * * 


20f3b93b793885d2ade1e00e2624ed48.png

  1. /* 


  2. * 计算数组大小 


  3. */ 


  4. #ifndef ARRAY_SIZE 


  5. #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 


  6. #endif 


  7. /* 


  8. * BUILD_BUG_ON基于一个GCC不支持负数数组,在编译时报错 


  9. * 但是4.4后GCC支持变长数组,不会引起编译器报错。 


  10. * 加入GCC优化选项后,编译时不会错,但是链接时会有找不到符号__BUILD_BUG_ON_CONDITION_FAILED的错误 


  11. */ 


  12. #define __BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) 



  13. #ifdef OPTIMIZE 


  14. extern int __BUILD_BUG_ON_CONDITION_FAILED; 


  15. #define BUILD_BUG_ON(condition)                                 \ 

  1. * * * 
  1. do {                                                    \ 
  1. * * * 
  1. __BUILD_BUG_ON(condition);                      \ 
  1. * * * 
  1. if (condition)                                  \ 
  1. * * * 
  1. __BUILD_BUG_ON_CONDITION_FAILED = 1;    \ 
  1. * * * 
  1. } while(0) 
  1. * * * 
  1. #else 
  1. * * * 
  1. #define BUILD_BUG_ON __BUILD_BUG_ON 
  1. * * * 
  1. #endif 
  1. * * * 

FIXUP for BUILD_BUG_ON:

  1. /* Force a compilation error if condition is true */ 


  2. -#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) 


  3. +#define BUILD_BUG_ON(condition) ((void)BUILD_BUG_ON_ZERO(condition)) 



  4. +/* Force a compilation error if condition is constant and true */ 


  5. +#define MAYBE_BUILD_BUG_ON(cond) ((void)sizeof(char[1 - 2 * !!(cond)])) 



  6. /* Force a compilation error if condition is true, but also produce a 


  7. result (of value 0 and type size_t), so the expression can be used 


  8. e.g. in a structure initializer (or where-ever else comma expressions 

  1. * * * 
  1. aren’t permitted). */ 
  1. * * * 
  1. -#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1) 
  1. * * * 
  1. +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:-!!(e); })) 
  1. * * * 
  1. +#define BUILD_BUG_ON_NULL(e) ((void *)sizeof(struct { int:-!!(e); })) 
  1. * * * 
  1. /* 


  2. * CLOCK_REALTIME:这种类型的时钟可以反映wall clock time, 


  3. * 用的是绝对时间,当系统的时钟源被改变, 


  4. * 或者系统管理员重置了系统时间之后,这种类型的时钟可以得到相应的调整, 


  5. * 也就是说,系统时间影响这种类型的timer。 


  6. * CLOCK_MONOTONIC:用的是相对时间,他的时间是通过jiffies值来计算的。 


  7. *该时钟不受系统时钟源的影响,只受jiffies值的影响。 


  8. * clock_gettime比gettimeofday更加精确 


  9. * clock_gettime( ) 提供了纳秒的精确度 


  10. */ 

  1. * * * 
  1. #ifdef APPLE 
  1. * * * 

  1. #define CLOCK_REALTIME  0 

  1. * * * 
  1. #define CLOCK_MONOTONIC 1 
  1. * * * 

  1. void clock_gettime(int type, struct timespec *tv); 

  1. * * * 

  1. #endif 

  1. * * * 
  1. /* 


  2. * 大小端转换 


  3. */ 


  4. #ifdef GNUC 


  5. #define _GNUC_MIN_VER(maj, min) (((GNUC << 8) + GNUC_MINOR) >= (((maj) << 8) + (min))) 


  6. #else 


  7. #define _GNUC_MIN_VER(maj, min) 0 


  8. #endif 



  9. #if defined(linux) || defined(CYGWIN

  1. * * * 
  1. #include <byteswap.h> 
  1. * * * 
  1. #include <endian.h> 
  1. * * * 

  1. #elif defined(APPLE

  1. * * * 
  1. #include <machine/endian.h> 
  1. * * * 
  1. #include <machine/byte_order.h> 
  1. * * * 
  1. #define bswap_32(x) OSSwapInt32(x) 
  1. * * * 
  1. #define bswap_64(x) OSSwapInt64(x) 
  1. * * * 
  1. #elif defined(FreeBSD
  1. * * * 
  1. #include <sys/endian.h> 
  1. * * * 
  1. #define bswap_32(x) bswap32(x) 
  1. * * * 
  1. #define bswap_64(x) bswap64(x) 
  1. * * * 
  1. #else 
  1. * * * 
  1. #include <machine/endian.h> 
  1. * * * 
  1. #define bswap_32(x) swap32(x) 
  1. * * * 
  1. #define bswap_64(x) swap64(x) 
  1. * * * 
  1. #endif 
  1. * * * 

  1. #ifndef __BYTE_ORDER 

  1. * * * 
  1. #define __BYTE_ORDER BYTE_ORDER 
  1. * * * 
  1. #endif 
  1. * * * 
  1. #ifndef __BIG_ENDIAN 
  1. * * * 
  1. #define __BIG_ENDIAN BIG_ENDIAN 
  1. * * * 
  1. #endif 
  1. * * * 
  1. #ifndef __LITTLE_ENDIAN 
  1. * * * 
  1. #define __LITTLE_ENDIAN LITTLE_ENDIAN 
  1. * * * 
  1. #endif 
  1. * * * 

  1. #define __u_bswap16(x) ({ uint16_t val = (x); ((uint16_t)(((val >> 8) & 0xffu) | ((val & 0xffu) << 8))); }) 

  1. * * * 

  1. #if _GNUC_MIN_VER(4, 2) 

  1. * * * 
  1. #define __u_bswap32(x) __builtin_bswap32(x) 
  1. * * * 
  1. #define __u_bswap64(x) __builtin_bswap64(x) 
  1. * * * 
  1. #else 
  1. * * * 
  1. #define __u_bswap32(x) bswap_32(x) 
  1. * * * 
  1. #define __u_bswap64(x) bswap_64(x) 
  1. * * * 
  1. #endif 
  1. * * * 

  1. #if __BYTE_ORDER == __LITTLE_ENDIAN 

  1. * * * 

  1. #define cpu_to_be64(x) __u_bswap64(x) 

  1. * * * 
  1. #define cpu_to_be32(x) __u_bswap32(x) 
  1. * * * 
  1. #define cpu_to_be16(x) __u_bswap16((uint16_t) (x)) 
  1. * * * 

  1. #define be64_to_cpu(x) __u_bswap64(x) 

  1. * * * 
  1. #define be32_to_cpu(x) __u_bswap32(x) 
  1. * * * 
  1. #define be16_to_cpu(x) __u_bswap16((uint16_t) (x)) 
  1. * * * 

  1. #define cpu_to_le64(x) (x) 

  1. * * * 
  1. #define cpu_to_le32(x) (x) 
  1. * * * 
  1. #define cpu_to_le16(x) (x) 
  1. * * * 

  1. #define le64_to_cpu(x) (x) 

  1. * * * 
  1. #define le32_to_cpu(x) (x) 
  1. * * * 
  1. #define le16_to_cpu(x) (x) 
  1. * * * 

  1. #else /* __BYTE_ORDER == __LITTLE_ENDIAN */ 

  1. * * * 

  1. #define cpu_to_le64(x) __u_bswap64(x) 

  1. * * * 
  1. #define cpu_to_le32(x) __u_bswap32(x) 
  1. * * * 
  1. #define cpu_to_le16(x) __u_bswap16((uint16_t) (x)) 
  1. * * * 

  1. #define le64_to_cpu(x) __u_bswap64(x) 

  1. * * * 
  1. #define le32_to_cpu(x) __u_bswap32(x) 
  1. * * * 
  1. #define le16_to_cpu(x) __u_bswap16((uint16_t) (x)) 
  1. * * * 

  1. #define cpu_to_be64(x) (x) 

  1. * * * 
  1. #define cpu_to_be32(x) (x) 
  1. * * * 
  1. #define cpu_to_be16(x) (x) 
  1. * * * 

  1. #define be64_to_cpu(x) (x) 

  1. * * * 
  1. #define be32_to_cpu(x) (x) 
  1. * * * 
  1. #define be16_to_cpu(x) (x) 
  1. * * * 

  1. #endif 

  1. * * * 
  1. /* 


  2. * GCC支持的属性 


  3. */ 


  4. #ifndef __packed 


  5. #define __packed attribute((packed)) 


  6. #endif 



  7. /* 


  8. * bitmap接口 


  9. */ 


  10. #ifndef BITS_PER_LONG 


  11. #define BITS_PER_LONG (8 * sizeof(unsigned long)) 


  12. #endif 



  13. static inline void bitfield_set(unsigned long *bits, int bit) 



  14. bits[bit / BITS_PER_LONG] |= (1UL << (bit % BITS_PER_LONG)); 

  1. * * * 
  1. * * * 

  1. static inline bool bitfield_test(unsigned long *bits, int bit) 

  1. * * * 
  1. * * * 
  1. return !!(bits[bit / BITS_PER_LONG] & (1UL << (bit % BITS_PER_LONG))); 
  1. * * * 
  1. * * * 

  1. #endif 

  1. * * * 

usock.h

封装来提供一个统一接口创建各种socket,例如创建TCP,UDP,UNIX sockets,客户端,服务器端,IPv4, IPv6和阻塞,非阻塞等。主要目的是调用usock(),返回你需要的fd.

  1. /* 


  2. * AI_NUMERICHOST当此标志置位时,此标志表示调用中的节点名必须是一个数字地址字符串 


  3. */ 


  4. #define USOCK_TCP 0 


  5. #define USOCK_UDP 1 



  6. #define USOCK_SERVER            0x0100 


  7. #define USOCK_NOCLOEXEC 0x0200 


  8. #define USOCK_NONBLOCK          0x0400 


  9. #define USOCK_NUMERIC           0x0800 

  1. * * * 
  1. #define USOCK_IPV6ONLY          0x2000 
  1. * * * 
  1. #define USOCK_IPV4ONLY          0x4000 
  1. * * * 
  1. #define USOCK_UNIX                      0x8000 
  1. * * * 

  1. int usock(int type, const char *host, const char *service); 

  1. * * * 

用法例如:创建一个server socket:

  1. 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().
进程管理部分,

  1. /* 


  2. * uloop的初始化,运行和结束 


  3. */ 


  4. int uloop_init(void); 


  5. void uloop_run(void); 


  6. void uloop_done(void); 


  7. /* 


  8. * EPOLL for linux 


  9. */ 


  10. #if defined(APPLE) || defined(FreeBSD


  11. #define USE_KQUEUE 


  12. #else 


  13. #define USE_EPOLL 


  14. #endif 


  15. /* 


  16. * event flag,读,写,边沿触发,或阻塞,或读写 

  1. * * * 
  1. */ 
  1. * * * 
  1. #define ULOOP_READ              (1 << 0) 
  1. * * * 
  1. #define ULOOP_WRITE             (1 << 1) 
  1. * * * 
  1. #define ULOOP_EDGE_TRIGGER      (1 << 2) 
  1. * * * 
  1. #define ULOOP_BLOCKING          (1 << 3) 
  1. * * * 

  1. #define ULOOP_EVENT_MASK        (ULOOP_READ | ULOOP_WRITE) 

  1. * * * 
  1. /* 


  2. * 文件描述符管理,初始化fd和uloop_fd_handler,然后使用 


  3. * uloop_add_fd()添加入uloop, flag表示哪些事件, READ/WRITE 


  4. */ 


  5. typedef void (*uloop_fd_handler)(struct uloop_fd *u, unsigned int events); 


  6. struct uloop_fd 



  7. uloop_fd_handler cb; 


  8. int fd; 


  9. bool eof; 

  1. * * * 
  1. bool error; 
  1. * * * 
  1. bool registered; 
  1. * * * 
  1. uint8_t flags; 
  1. * * * 
  1. }; 
  1. * * * 
  1. int uloop_fd_add(struct uloop_fd *sock, unsigned int flags); 
  1. * * * 
  1. int uloop_fd_delete(struct uloop_fd *sock); 
  1. * * * 
  1. /* 


  2. * timeout管理,初始化uloop_timeout_handler和time,使用 


  3. * uloop_timeout_add添加入uloop. 


  4. */ 


  5. typedef void (*uloop_timeout_handler)(struct uloop_timeout *t); 


  6. struct uloop_timeout 



  7. struct list_head list; 


  8. bool pending; 



  9. uloop_timeout_handler cb; 

  1. * * * 
  1. struct timeval time; 
  1. * * * 
  1. }; 
  1. * * * 

  1. int uloop_timeout_add(struct uloop_timeout *timeout); 

  1. * * * 
  1. int uloop_timeout_set(struct uloop_timeout *timeout, int msecs); 
  1. * * * 
  1. int uloop_timeout_cancel(struct uloop_timeout *timeout); 
  1. * * * 
  1. int uloop_timeout_remaining(struct uloop_timeout *timeout); 
  1. * * * 
  1. /* 


  2. * 进程管理部分,初始化uloop_process_handler和pid,然后使用 


  3. * uloop_process_add添加入uloop 


  4. */ 



  5. typedef void (*uloop_process_handler)(struct uloop_process *c, int ret); 



  6. struct uloop_process 



  7. struct list_head list; 

  1. * * * 
  1. bool pending; 
  1. * * * 

  1. uloop_process_handler cb; 

  1. * * * 
  1. pid_t pid; 
  1. * * * 
  1. }; 
  1. * * * 

  1. int uloop_process_add(struct uloop_process *p); 

  1. * * * 
  1. int uloop_process_delete(struct uloop_process *p); 
  1. * * * 


98e6b29c3ffb220d7ea0c1ce5124022a.png

blob.h

帮助以二进制传递数据。支持多种数据类型,创建的blobs可以在任何socket上发送。
大小端问题已经在库里解决了。
方法是创建一个type-value chained数据,支持嵌套数据,在blogmsg.h里有使用。

  1. struct blob_attr { 


  2. uint32_t id_len; /** 高1位为extend标志,高7位存储id, 


  3. *  低24位存储data的内存大小 */ 


  4. char data[]; /** 每个data按照256字节对齐 通过长度来索引下个data位置. */ 


  5. } __packed; 



  6. struct blob_buf { 


  7. struct blob_attr head; /* 在嵌套时使用 */ 


  8. bool (*grow)(struct blob_buf *buf, int minlen); 


  9. int buflen; /** 总buf长度 */ 

  1. * * * 
  1. void buf; /* 指向第一个data(blob_attr)的基地址 */ 
  1. * * * 
  1. }; 
  1. * * * 

  1. extern int blob_buf_init(struct blob_buf *buf, int id); 

  1. * * * 


images/2187162543-54768f7f86bed.jpg

2187162543-54768f7f86bed.jpg
231588333-54769026b0c34.jpg

Reference

blob buf, blobmsg接口介绍

nicephil@gmail.com

posted on 2017-01-15 22:37  nicephil  阅读(595)  评论(0编辑  收藏  举报

导航