libev事件库

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

下面是一个简单的例子。网络

#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, 启动一个定时器至关简单函数

  1. 定义ev_timer结构体。
  2. 定时器设置,主要是回调函数,首次触发时间和以后的出发间隔。
  3. 经过ev_timer_start将定时事件加入到事件循环中。
  4. 随时能够经过ev_timer_stop注销事件。

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

#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事件的处理,相关的API与定时器事件相似,不过IO事件会区分读和写。下面是一个简单的例子。性能

#include<stdio.h>
#include<ev.h>

ev_io   stdin_watcher;
char    buf[4096];

void io_action(struct ev_loop *loop, ev_io *w, int revents)
{   
    if (revents & EV_READ) {
        fgets(buf, 4096, stdin);

        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", buf);
        ev_io_stop(loop, w);

    }
    return;
}

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

    ev_io_init(&stdin_watcher, io_action, /* STDIN_FILENO */ 0, EV_READ);
    ev_io_start(loop, &stdin_watcher);

    ev_run(loop, 0);
    
    return 0;
}

这是一个IO事件的例子,程序启动后等待用户输入,对于可读事件(revents & EV_READ),fgets获取用户输入,对于可写事件(revents & EV_WRITE),进行输出。指针

这里为了简单使用是终端的输入输出操做,实际编程中libev库更多的是用来处理网络IO事件。code

程序处理中,大多数IO事件都会设置超时机制,避免无限期等待下去,尤为是网络IO中,创建链接,读取数据,发送数据都要设置超时时间以避免已经破坏的链接一直占用系统资源。对这种状况须要将定时器事件与IO事件结合起来。IO事件超时后执行定时器事件,将IO事件撤销,一样IO事件执行成功要将定时器事件撤销。为此须要一个结构体存放IO事件和定时器事件的信息。事件

在ev_io和ev_timer等全部事件的结构体中都有一个void指针,能够存储相应的数据。资源

以下面的例子,5秒后若是终端没有接受到任何输入就会注销IO事件。

#include<stdio.h>
#include<ev.h>


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);

        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;

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


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

    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;
}
相关文章
相关标签/搜索