简介
异步事件框架是通过io复用将事件驱动的任务同步处理转换为异步调用形式的框架。
作用
编码时常需要处理一些事件驱动的周期性或者偶发性任务,例如:Linux看门狗周期性喂狗,NTP周期性同步网络时间,以太网网线偶发性插拔检测,网络IO可偶发性读写等,处理类似任务,以往常见于创建一个独立的线程循环处理,但是如果存在过多的类似任务,会导致创建过多的线程,频繁的线程创建以及切换在嵌入式平台容易导致性能低下。异步事件框架是将相同的部分(事件监控)抽离出来,事件触发后,通过异步通知的方式调用事件处理函数,这样既可以减少线程的创建,也可以减少代码量。异步事件框架常用于网络编程中,因此时常被人称作网络库,但是其它场景中,它的作用也是巨大的。
使用
开源库
网上有名的开源的C/C++异步事件框架有libev,libevent,libuv等;开源库libevent、libev、libuv对比。libev是libevent之后的一个事件驱动的编程框架,其接口和libevent基本类似,据官方介绍,其性能比libevent还要高,bug比libevent还少。libev代码规模较小,更适合资源受限的嵌入式平台,因此我选择它。
libev使用
编译安装
tar -zxf libev-4.24.tar.gz
cd libev-4.24
./configure
make
make install
简单示例(man page自带的libev用法示例)
// a single header file is required
#include <ev.h>
#include <stdio.h> // for puts
// every watcher type has its own typedef’d struct
// with the name ev_TYPE
ev_io stdin_watcher;
ev_timer timeout_watcher;
// all watcher callbacks have a similar signature
// this callback is called when data is readable on stdin
static void stdin_cb (EV_P_ ev_io *w, int revents)
{
puts ("stdin ready");
// for one-shot events, one must manually stop the watcher
// with its corresponding stop function.
ev_io_stop (EV_A_ w);
// this causes all nested ev_run’s to stop iterating
ev_break (EV_A_ EVBREAK_ALL);
}
// another callback, this time for a time-out
static void timeout_cb (EV_P_ ev_timer *w, int revents)
{
puts ("timeout");
// this causes the innermost ev_run to stop iterating
ev_break (EV_A_ EVBREAK_ONE);
}
int main (void)
{
// use the default event loop unless you have special needs
struct ev_loop *loop = EV_DEFAULT;
// initialise an io watcher, then start it
// this one will watch for stdin to become readable
ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ);
ev_io_start (loop, &stdin_watcher);
// initialise a timer watcher, then start it
// simple non-repeating 5.5 second timeout
ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.);
ev_timer_start (loop, &timeout_watcher);
// now wait for events to arrive
ev_run (loop, 0);
// unloop was called, so exit
return 0;
}
编译运行
编译:
gcc example.c -lev -o example
运行:
./example
timeout //不输入,等到5.5秒后超时
./example
a //输入a,所以stdin监测到事件退出
stdin ready