文章目录
libhv简介
libhv是一个跨平台的类似libevent、libev、libuv的异步事件驱动库,但提供了更加接近原生的API接口和更加丰富的协议。
libhv已广泛实用在公司的IOT平台、http API服务之中,正确性、稳定性、可扩展性、性能都有保证,完全开源,请放心使用。
项目地址:https://github.com/ithewei/libhv.git
码云镜像:https://gitee.com/ithewei/libhv.git
QQ技术交流群:739352073
注:libhv每日一学博文为QQ群里的libhv每日一学技术分享整理所得,方便新老朋友查阅学习,该博文每隔几日会同步更新一次。
libhv应用程序框架
libhv提供了命令行解析、INI配置文件解析、日志文件、pid文件、信号处理等创建一个应用程序的常用模块
以main.cpp.tmpl
为例,讲解这些模块使用方法
测试示例:
make test
bin/test -h
bin/test -v
bin/test -t
bin/test -d
ps aux | grep test
bin/test -s status
bin/test -s stop
ps aux | grep test
bin/test -s start -d
ps aux | grep test
bin/test -s restart -d
ps aux | grep test
流程图:
libhv事件循环使用入门
参考examples/loop.c
、examples/timer.c
、examples/tcp.c
、examples/udp.c
、examples/nc.c
make loop timer tcp udp nc
bin/loop
bin/timer
bin/tcp 1111
bin/nc 127.0.0.1 1111
bin/udp 2222
bin/nc -u 127.0.0.1 2222
流程图:
libhv日志模块介绍
libhv如何实现跨平台的
主要靠两个文件:
1、./configure
生成的hconfig.h
configure脚本中检测头文件、函数是否存在定义相应宏(如HAVE_PTHREAD_H
、HAVE_GETTIMEOFDAY
)
2、base/hplatform.h
中
操作系统宏:(如_WIN32
、__linux__
等)
编译器宏:(如__GNUC__
、__clang__
、_MSC_VER
等)
CPU体系结构宏:(如__i386__
、__x86_64__
、__arm__
、__aarch64__
等)
编程语言宏:__cplusplus
以获取当前本地日期时间为例,见base/htime.c
libhv中的宏艺术
C语言宏基础知识
宏是C/C++语言的一大特色,它将一个标识符定义为一个字符串,在预处理阶段源程序中的该标识符均以指定的字符串来代替,使用宏可以使代码更加简洁和增强可读性。
#define <宏名> (<参数表>) <宏体>
#undef <宏名>
#ifdef <宏名>
...
#else
...
#endif
//define中的三个特殊符号:#,##,#@
#define STRCAT(x,y) x##y //连接x和y成一个字符串
#define TOCHAR(x) #@x //给x加上单引号
#define TOSTR(x) #x //给x加上双引号
以base/herr.h
、base/herr.c
中对错误码定义为例:
#define FOREACH_ERR_COMMON(F) \
F(0, OK, "OK") \
F(1000, UNKNOWN, "Unknown error") \
\
F(1001, NULL_PARAM, "Null parameter") \
F(1002, NULL_POINTER, "Null pointer") \
F(1003, NULL_DATA, "Null data") \
F(1004, NULL_HANDLE, "Null handle") \
\
F(1011, INVALID_PARAM, "Invalid parameter")\
F(1012, INVALID_POINTER, "Invalid pointer") \
F(1013, INVALID_DATA, "Invalid data") \
F(1014, INVALID_HANDLE, "Invalid handle") \
F(1015, INVALID_JSON, "Invalid json") \
F(1016, INVALID_XML, "Invalid xml") \
F(1017, INVALID_FMT, "Invalid format") \
F(1018, INVALID_PROTOCOL, "Invalid protocol") \
F(1019, INVALID_PACKAGE, "Invalid package") \
#define FOREACH_ERR(F) \
FOREACH_ERR_COMMON(F) \
FOREACH_ERR_FUNC(F) \
FOREACH_ERR_SERVICE(F) \
FOREACH_ERR_GRPC(F) \
#undef ERR_OK // prevent conflict
enum {
#define F(errcode, name, errmsg) ERR_##name = errcode,
FOREACH_ERR(F)
#undef F
};
// errcode => errmsg
const char* hv_strerror(int err) {
if (err > 0 && err <= SYS_NERR) {
return strerror(err);
}
switch (err) {
#define F(errcode, name, errmsg) \
case errcode: return errmsg;
FOREACH_ERR(F)
#undef F
default:
return "Undefined error";
}
}
hv_strerror
中宏替换后实际上是很多个case errcode: return errmsg;
,添加一个错误码定义只需在头文件见中添加即可,无需改动源文件,代码更简洁,可扩展性更好
libhv多线程同步相关知识
见base/hthread.h
base/hmutex.h
unittest/hmutex_test.c
pthread和hmutex对应的宏就不贴出来了,请自行查阅base/hmutex.h
编译运行单元测试
make unittest
bin/hmutex
c语言如何实现c++的继承
使用宏即可实现,原理如下
libhv中就应用了这种技巧,见event/hloop.h
、event/hevent.h
libevent、libev、libuv、libhv、boost.asio、poco、muduo七种echo-server实现对比
https://github.com/ithewei/libhv/tree/master/echo-servers中包含libevent、libev、libuv、libhv、boost.asio、poco、muduo
七种echo-server实现,感兴趣的可以看看
编译参考README.md 中的echo-servers/benchmark
make libhv
make webbench
# ubuntu16.04
sudo apt-get install libevent-dev libev-dev libuv1-dev libboost-dev libasio-dev libpoco-dev
# muduo install => https://github.com/chenshuo/muduo.git
make echo-servers
sudo echo-servers/benchmark.sh
压力测试结果图:
注:客户端和服务端位于同一台电脑,有一定随机性,仅供参考,总的来说,这几个库性能接近,各有千秋吧
libhv事件循环逻辑
int hloop_run(hloop_t* loop) {
loop->status = HLOOP_STATUS_RUNNING;
while (loop->status != HLOOP_STATUS_STOP) {
if (loop->status == HLOOP_STATUS_PAUSE) {
msleep(PAUSE_TIME);
hloop_update_time(loop);
continue;
}
++loop->loop_cnt;
if (loop->nactives == 0) break;
hloop_process_events(loop);
if (loop->flags & HLOOP_FLAG_RUN_ONCE) {
break;
}
}
loop->status = HLOOP_STATUS_STOP;
loop->end_hrtime = gethrtime();
if (loop->flags & HLOOP_FLAG_AUTO_FREE) {
hloop_cleanup(loop);
SAFE_FREE(loop);
}
return 0;
}
调用hloop_run
后,我们就进入了libhv的事件循环,很简单,就是while循环中调用hloop_process_events
处理各类事件
具体各类事件是如何处理的,感兴趣的可以研究源码