• libev


    libev是一个**事件驱动库**,它需要循环探测事件是否发生,在Linux上实际是封装了epoll等系统调用。

    其循环过程由ev_loop( )函数设置,循环体是ev_loop结构。

    //创建事件循环
    void ev_loop( ev_loop* loop, int flags )
    

    libev支持多种事件类型,常用的如I/O,定时器,信号等。详细的可以去看官网教程的WATCHER TYPES章节。

    每种事件都有具体结构来表示,如ev_io表示一个I/O事件。事件通过ev_io_init()函数初始化。

    //初始化一个事件
    void ev_io_init(ev_io *io, callback, int fd, int events)
    

    初始化内容包括了,探测的fd,事件类型,回调函数等。如初始化一个fdx的可读事件:


    ev_io_init(accept_event, acceept_callback, fdx, EV_READ);

    普通网络程序中,一般阻塞在accept(socket_fd),在连接到达后返回一个connect_fd继续等待。而事件驱动模型中,则变为探测socket_fd是否可读。在callback回调中去执行accept,不再阻塞。

    现在我们要做的只是将初始化好的accept_event这个事件加入到事件循环中去。

    将事件添加到事件循环,或将事件从事件循环删去,是通过ev_io_start()和ev_io_stop函数完成(这里示例I/O事件):

    void ev_io_start( ev_loop *loop, ev_io* io ) 
    void ev_io_stop( EV_A_* )
    

    虽然很多细节未考虑,但一个简单的事件驱动的服务器模型已经有了。其中屏蔽了很多裸写epoll要处理的细节。

    简单总结下步骤:

    1、创建一个事件循环

    struct ev_loop *loop = EV_DEFAULT;

    2、初始化一个待探测的事件,这个事件由fd(I/O为例),回调函数,事件类型(读/写)等组成

    ev_io stdin_watcher;

    ev_io_init (&stdin_watcher, callback, /*STDIN_FILENO*/ 0, EV_READ);

    3、将事件加入到事件循环

    ev_io_start (loop, &stdin_watcher);

    4、启动事件循环

    ev_run (loop, 0);

    我们可以随时向事件循环中加入事件,或从中删除某事件。

    完整示例:

       // 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);
    
         // break was called, so exit
         return 0;
       }
  • 相关阅读:
    【BZOJ1345】[Baltic2007] 序列问题(单调栈大水题)
    【BZOJ2940】[POI2000] 条纹(Multi-SG)
    【BZOJ4589】Hard Nim(FWT+快速幂)
    【CF438E】The Child and Binary Tree(生成函数+多项式开根)
    【洛谷5205】【模板】多项式开根
    【BZOJ4036】[HAOI2015] 按位或(Min-Max容斥+FWT)
    【BZOJ4381】[POI2015] ODW(设阈值+倍增)
    【BZOJ3328】PYXFIB(矩乘+单位根反演)
    【BZOJ2674】Attack(整体二分+树状数组套线段树)
    单纯看懂公式的单位根反演
  • 原文地址:https://www.cnblogs.com/gm-201705/p/9863908.html
Copyright © 2020-2023  润新知