libev事件框架使用示例

以Nginx为代表,IO事件+定时器组成的事件驱动构成了现在高性能网络处理的基础,libev库是继​​libevent之后又一个事件库,为编写事件驱动程序提供底层的封装,相比libevent更加精简,没有附加额外的复杂功能。

简单示例

下面是一个简单的例子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include<stdio.h>
#include<ev.h>

void timer_action(struct ev_loop *loop, ev_timer *w, int e)
{
    printf("Hello World!\n");
}

int main(int argc, char *argv[])
{
    struct ev_loop *loop = ev_default_loop(0);

    ev_timer    w;
    ev_timer_init(&w, timer_action, 5, 2);
    ev_timer_start(loop, &w);

    ev_run(loop, 0);

    return 0;
}

程序启动时设置定时器,5秒后定时器启动输出“Hello World!”,之后每隔2秒输出一次。

对每个事件都要有一个结构体,储存事件相关的信息,对于定时器事件,结构体为ev_timer, 启动一个定时器相当简单

  • 定义ev_timer结构体。
  • 定时器设置,主要是回调函数,首次触发时间和之后的出发间隔。
  • 通过ev_timer_start将定时事件加入到事件循环中。
  • 随时可以通过ev_timer_stop注销事件。

定时器循环

下面的例子中,程序启动1秒后输出“Hello World!”,之后间隔每个增加一秒,输出4次后结束。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include<stdio.h>
#include<ev.h>

int count = 0;
int timeout = 1;

void timer_action(struct ev_loop *loop, ev_timer *w, int e)
{
    printf("Hello World!\n");

    count += 1;
    if (count > 3) {
        ev_timer_stop(loop, w);
        return;
    }

    timeout += 1;
    ev_timer_stop(loop, w);
    ev_timer_set(w, timeout, 0);
    ev_timer_start(loop, w);

}

int main(int argc, char *argv[])
{
    struct ev_loop *loop = ev_default_loop(0);

    ev_timer    w;
    ev_timer_init(&w, timer_action, 1, 0);
    ev_timer_start(loop, &w);

    ev_run(loop, 0);

    return 0;
}

处理IO时间

事件驱动框架中最重要的还是IO事件的处理,相关的API与定时器事件类似,不过IO事件会区分读和写。下面是一个简单的例子。​

```c #include #include

struct io_timer_struct { ev_io io; ev_timer timer; char buf[4096]; };

void io_action(struct ev_loop *loop, ev_io *w, int revents) { struct io_timer_struct *s = (struct io_timer_struct *)w->data; if (revents & EV_READ) { fgets(s->buf, 4096, stdin);

1
2
3
4
5
6
7
8
9
10
11
12
    ev_io_stop(loop, w);
    ev_io_set(w, 0, EV_WRITE);
    ev_io_start(loop, w);

} else if (revents & EV_WRITE) {
    printf("Input:%s\n", s->buf);
    ev_io_stop(loop, w);
}

ev_timer_stop(loop, &s->timer);

return; }

void timer_action(struct ev_loop *loop, ev_timer *w, int revents) { struct io_timer_struct *s = (struct io_timer_struct *)w->data;

1
2
ev_io_stop(loop, &s->io);
return; }

int main(void) { struct ev_loop *loop = ev_default_loop(0);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct io_timer_struct s;
memset(&s, 0, sizeof(s));

s.io.data = &s;
ev_io_init(&s.io, io_action, 0, EV_READ);
ev_io_start(loop, &s.io);

s.timer.data = &s;
ev_timer_init(&s.timer, timer_action, 5, 0);
ev_timer_start(loop, &s.timer);


ev_run(loop, 0);

return 0; }

​```