libev笔记

libev是一个开源库,实现了一个reactor模式事件驱动任务调度库。代码非常精简,包含所有实现的.c文件只有不到5000行。

支持的事件类型:

ev_io

ev_timer

ev_periodic

ev_signal

ev_child

ev_stat

ev_idle

ev_prepare  and ev_check

ev_embed

ev_fork

ev_cleanup

ev_async

常用的事件类型:

ev_io,io就绪事件

ev_timer,定时器事件

ev_signal,信号事件

官方使用例子

ev_io

   static void    stdin_readable_cb (struct ev_loop *loop, ev_io *w, int revents)    {       ev_io_stop (loop, w);      .. read from stdin here (or from w->fd) and handle any I/O errors    }     ...    struct ev_loop *loop = ev_default_init (0);    ev_io stdin_readable;    ev_io_init (&stdin_readable, stdin_readable_cb, STDIN_FILENO, EV_READ);    ev_io_start (loop, &stdin_readable);    ev_run (loop, 0);

ev_timer

   static void    one_minute_cb (struct ev_loop *loop, ev_timer *w, int revents)    {      .. one minute over, w is actually stopped right here    }     ev_timer mytimer;    ev_timer_init (&mytimer, one_minute_cb, 60., 0.);    ev_timer_start (loop, &mytimer);
   static void    timeout_cb (struct ev_loop *loop, ev_timer *w, int revents)    {      .. ten seconds without any activity    }     ev_timer mytimer;    ev_timer_init (&mytimer, timeout_cb, 0., 10.); /* note, only repeat used */    ev_timer_again (&mytimer); /* start timer */    ev_run (loop, 0);     // and in some piece of code that gets executed on any "activity":    // reset the timeout to start ticking again at 10 seconds    ev_timer_again (&mytimer);

ev_signal

   static void    sigint_cb (struct ev_loop *loop, ev_signal *w, int revents)    {      ev_break (loop, EVBREAK_ALL);    }     ev_signal signal_watcher;    ev_signal_init (&signal_watcher, sigint_cb, SIGINT);    ev_signal_start (loop, &signal_watcher);

关键代码分析


ev.h

核心h文件

typedef struct ev_watcher

{

EV_WATCHER (ev_watcher)

} ev_watcher;

/* shared by all watchers */

#define EV_WATCHER(type)            \

int active; /* private */            \

int pending; /* private */            \

EV_DECL_PRIORITY /* private */        \

EV_COMMON /* rw */                \

EV_CB_DECLARE (type) /* private */

libev中的基础数据类型是ev_watcher,所有的事件都可以通过(W)watcher转换成ev_watcher,ev_watcher提供通用的抽象接口ev_start、ev_stop

ev_watcher是一种c方式实现的继承、多态、封装,ev_start和ev_stop就是基类ev_watcher提供的抽象接口

ev_io/ev_timer/ev_async都继承自ev_watcher

ev.c

核心c代码

struct ev_loop

{

ev_tstamp ev_rt_now;

#define ev_rt_now ((loop)->ev_rt_now)

#define VAR(name,decl) decl;

#include "ev_vars.h"

#undef VAR

};

reactor的核心结构体,因为成员变量众多,把详细的定义包含在ev_vars.h中。

ev_vars.h

io事件处理器列表,文件描述符fd作为数组下标

fd关注的事件发生后,查找anfds[fd]的事件处理器,检查触发事件并调用fd所有关联的处理函数。

ANFD * anfds;

ANFD的定义在ev.c中

/*保存fd事件信息的结构*/

//loop初始化的时候会初始化一个ANFD数组,每个ANFD表示一个fd对应的这个fd的所有事件信息

typedef struct

{

//每个fd可以有多个事件

WL head;

unsigned char events; /* 事件的类型 */

unsigned char reify;  /*  (EV_ANFD_REIFY, EV__IOFDSET) */

unsigned char emask;  /* epoll后端的实际内核mask */

unsigned char unused;

//不同多路复用API的专用变量

//epoll

#if EV_USE_EPOLL

unsigned int egen;    /* generation counter to counter epoll bugs */

#endif

//windows平台

#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP

SOCKET handle;

#endif

#if EV_USE_IOCP

OVERLAPPED or, ow;

#endif

} ANFD;

ev_io的观察列表,ev_io_start把事件处理器注册到ev_loop的fdchanges列表。

int* fdchanges;

ev_wrap.h

包装器头文件,简化了代码量,也增加了代码的阅读难度

抽几个关键的宏贴出来

#define fdchanges ((loop)->fdchanges)

#define anfds ((loop)->anfds)

这些宏是有益还是有害,仁者见仁智者见智

事件主循环

int ev_run(ev_loop *loop, int flags)

{

//检查关注fd列表fdchanges,新增加或者修改的fd都保存在这个列表中

//通过fd查找注册的事件处理器ANFD,检查事件处理器的关注事件

fd_reify

调用跨平台的多路复用api,封装过的,epoll的封装在ev_epoll.c

backend_poll

把事件加入待处理列表

ev_feed_event

//调用所有的待处理事件处理器

ev_invoke_pending

}

时间: 2024-12-13 07:02:21

libev笔记的相关文章

Libev学习笔记1

和Libevent相似,Libev是一个高性事件驱动框架,据说性能比Libevent要高,bug比Libevent要少.Libev只是一个事件驱动框架,不是网络库,因为它的内部并没有任何socket编程代码.支持的事件驱动机制包括: select poll epoll kqueue Solaris-specific event port mechanisms 支持的事件类型也很多,下面会全部列出. 官方首页地址:http://software.schmorp.de/pkg/libev.html

Libev学习笔记4

这一节分析Libev的定时器部分.对定时器的使用主要有两个函数: ev_timer_init (&timeout_watcher, timeout_cb, 5.5, 0.); ev_timer_start (loop, &timeout_watcher); 和ev_io类型的watcher类似,timeout_watcher是一个类型为ev_timer的watcher,上面的ev_timer_init函数将它设置为5.5秒之后调用回调函数timeout_cb,最后一个参数0表示定时器不重复

Libev学习笔记3

设置完需要监听的事件之后,就开始event loop了.在Libev中,该工作由ev_run函数完成.它的大致流程如下: int ev_run (EV_P_ int flags) { do { /* 执行EV_FORK类型事件 */ /* 执行EV_PREPARE类型事件 */ /* 遍历fdchanges数组,使用户关注的事件和epoll关注的事件保持一致 */ fd_reify (EV_A); /* 计算epoll阻塞时间 */ /* 事件驱动机制阻塞等待事件发生 */ backend_po

Libev学习笔记2

这一节根据官方文档给出的简单示例,深入代码内部,了解其实现机制.示例代码如下: int main (void) { struct ev_loop *loop = EV_DEFAULT; ev_io_init (&stdin_watcher, stdin_cb, /*STDIN_FILENO*/ 0, EV_READ); ev_io_start (loop, &stdin_watcher); ev_timer_init (&timeout_watcher, timeout_cb, 5

libev事件库使用笔记

源码下载地址:http://dist.schmorp.de/libev/ libev是一个高性能的事件循环库,比libevent库的性能要好. 安装: 1 tar -zxf libev-4.15.tar.gz 2 cd libev-4.15 3 ./configure 4 make 5 make install 设置环境变量: 设置一下环境变量(在文件/etc/profile中添加).然后才可以运行. 1 export LIBDIR=/usr/local/lib 2 export LD_LIBR

libev学习笔记

libev最大的特点是采用了轮询文件描述符(select,poll,epoll,iocp,kqueue)的方式来代替线程调度和切换,省去了线程切换,效率很高. 用小顶堆而不是链表来管理定时器,有以下优势: 1.容器中的元素实现有序排列(当然链表也能做有序排列,但性能不行,参见后面几点),这样在轮询时只需要检查前几个元素,而不需要遍历所有元素. 2.小顶堆的操作,无论是插入,还是删除,时间复杂度都在O(1)~O(logN)之间.有序链表,删除的时间复杂度为O(1),但插入的时间复杂度为O(N/2)

【安全牛学习笔记】

弱点扫描 ╋━━━━━━━━━━━━━━━━━━━━╋ ┃发现弱点                                ┃ ┃发现漏洞                                ┃ ┃  基于端口五福扫描结果版本信息(速度慢)┃ ┃  搜索已公开的漏洞数据库(数量大)      ┃ ┃  使用弱点扫描器实现漏洞管理            ┃ ╋━━━━━━━━━━━━━━━━━━━━╋ [email protected]:~# searchsploit Usage:

51CTO持续更新《通哥的运维笔记》

<通哥的运维笔记>将持续在51CTO网站更新,希望大家多多关注.互相学习,后期,我将会退出<通哥的运维笔记>系列视频教程,希望带给大家最大的收获,帮助大家更好的学习.进步.<通哥的运维笔记>主要从linux系统管理.虚拟化.cloudstack云平台以及网络管理之CCNA.CCNP.CCIE,等等方面深入讲解.

WPF笔记整理 - Bitmap和BitmapImage

项目中有图片处理的逻辑,因此要用到Bitmap.而WPF加载的一般都是BitmapImage.这里就需要将BitmapImage转成Bitmap 1. 图片的路径要用这样的,假设图片在project下的Images目录,文件名XXImage.png. pack://application:,,,/xxx;component/Images/XXImage.png 2. 代码: Bitmap bmp = null; var image = new BitmapImage(new Uri(this.X