1.ev_io结构
typedef struct ev_io{
EV_WATCHER_LIST (ev_io)
int fd; /* 文件描述符 */
int events; /* 事件类型 */
} ev_io;
2 . 作用
ev_io是我们最常用的一个watcher。因为项目中,时间循环的应用场景大部分也都集中在io的读写方面。
从ev_io的声明中我们可以看到它继承了WATCHER_LIST,并且有两个新字段,fd和events。不难理解fd就是用来保存所监听的文件描述符的,而events则是记录了我们所要监听的时间,一般为读、写。
3 .相关函数
ev_init (ev_io *ev,callback) ;
ev_io_set(ev_io *ev, int fd, int events);
ev_io_init(ev_io *ev, callback,int fd, int events);
ev_io_init等价于调用ev_init,再调用ev_io_set。其功能是将回调函数、文件描述符以及所监听的事件绑定到watcher上。
根据实践经验,我觉得最好还是少调用ev_io_init。因为ev_init只能对watcher执行一次,但我们却可能经常需要重置watcher,这时如果我们再次调用ev_io_init而不是调用ev_io_set对watcher进行重置,就可能会使程序core掉。我会在以后提到这个问题。
ev_io_start(EV_P_ ev_io * w);
ev_io_start的作用就是将已经初始化好的watcher绑定到事件监听主循环ev_loop上。在这个过程中:
l 首先会检查正确性,在这里用到了一个宏EV_FREQUENT_CHECK,其具体内容就是进行各种检查,就不仔细讨论了。
l 调用ev_start将监视器active置为启动,同时设置优先级等。
l 调用array_needsize检查anfds的大小是否足够放入新的fd,如果不够realloc。
l 调用wlist_add将fd插入anfds中。
l 最后调用fd_change注册行为改变的函数,改函数把所有新的fd或者所监听的事件有改变的fd存放到fdchanges数组中,在适当的时候调用底层事件模型进行修改。
ev_io_stop(EV_P_ ev_io * w);
ev_io_stop的作用正好与ev_io_start相反,就是把watcher从ev_loop中去除。起流程基本如下:
l 首先从pendings中清楚watcher对应的即将被触发的事件。
l 调用EV_FREQUENT_CHECK进行检查。
l 调用wlist_del从anfds中清除相关fd。
l 调用ev_stop将watcher的active置为0。
l 调用fd_change注册fd行为变化。