版本 | 作者 | 日期 | 备注 |
---|---|---|---|
0.1 | ZY | 2019.5.31 | 初稿 |
这个是基于官网资料以及这里
https://segmentfault.com/a/1190000006173864
基本上ev_loop你可以理解为一个大的循环,之前我们需要自己在线程里创建一个while循环,然后做一些多路复用监听等等,而这里的ev_loop你可以简单理解为就是代替这个循环的,当它开始之后,它会监听你设置的之前我们截图的watcher到这个loop中,该loop代替那个循环来监听你之前需要循环监听的事件,当该事件发生时,就会调用你在注册这个事件时绑定的回调函数。
下面这个是官网的描述:
下面是参考网址中的内容:
event loop 用一个结构体struct ev_loop *描述。Libev 支持两类 loop,一是 default loop,支持 child process event;动态创建的 event loops 就不支持这个功能
struct ev_loop *ev_default_loop (unsigned int flags);
初始化 default loops。如果已经初始化了,那么直接返回并且忽略 flags。注意这个函数并不是线程安全的。只有这个 loop 可以处理ev_child事件。
struct ev_loop *ev_loop_new (unsigned int flags);
这个函数是线程安全的。一般而言,每个 thread 使用一个 loop。以下说明 flag 项的各个值:
void ev_loop_destroy (struct ev_loop *loop);
销毁ev_loop。注意这里要将所有的 IO 清除光之后再调用,因为这个函数并不中止所有活跃(active)的 IO。部分 IO 不会被清除,比如 signal。这些需要手动清除。这个函数一般和ev_loop_new一起出现在同一个线程中。
void ev_loop_fork (struct ev_loop *loop);
这个函数导致ev_run的子过程重设已有的 backend 的 kernel state。重用父进程创建的 loop。可以和pthread_atfork()配合使用。
对于上面flag值的选用其实就是我之前说要有一定socket、多路复用等基础知识的原因了,如果你不是很清楚的话,使用默认值即可。
上面基本上已经说得很清晰了,你有child且要在子进程使用libev那你只能使用默认的loop,而如果你的进程需要在多线程中分别使用loop,那么最好在各个线程中创建各自的loop来保证线程安全。我一般使用子进程的情况较少,多是多线程方式使用,所以我一般的用法如下:
static void timeout_upload_cb(EV_P_ ev_timer *w_, int revents)
{
...
}
static void *thread_device_info_upload()
{
g_loop = ev_loop_new(EVFLAG_AUTO);
ev_timer_init(&g_timer_watcher, timeout_upload_cb, TIMEOUT, TEST_REPEAT_TIME);
ev_timer_start(g_loop, &g_timer_watcher);
ev_run(g_loop, 0);
return NULL;
}
其中g_loop就是我在该线程下创建的loop:static struct ev_loop *g_loop = NULL;
为了保证退出时调用ev_break(g_loop, EVBREAK_ALL); 所以一般是将loop设为全局变量。
当然,你也可以像
https://www.cnblogs.com/wunaozai/p/3950249.html
里面的例子这样来使用:
#include
#include
#include
#include
#include
void io_action(struct ev_loop *main_loop,ev_io *io_w,int e)
{
int rst;
char buf[1024];
memset(buf,0,sizeof(buf));
puts("In IO action");
read(STDIN_FILENO,buf,sizeof(buf));
buf[1023]='\0';
printf("String: %s\n",buf);
ev_io_stop(main_loop,io_w);
}
void timer_action(struct ev_loop *main_loop,ev_timer *time_w,int e)
{
puts("In Time action");
ev_timer_stop(main_loop,time_w);
}
void signal_action(struct ev_loop *main_loop,ev_signal *signal_w,int e)
{
puts("In Signal action");
ev_signal_stop(main_loop,signal_w);
ev_break(main_loop,EVBREAK_ALL);
}
int main(int argc,char **argv)
{
ev_io io_w;
ev_timer timer_w;
ev_signal signal_w;
struct ev_loop *main_loop = ev_default_loop(0);
ev_init(&io_w,io_action);
ev_io_set(&io_w,STDIN_FILENO,EV_READ);
ev_init(&timer_w,timer_action);
ev_timer_set(&timer_w,2,0);
ev_init(&signal_w,signal_action);
ev_signal_set(&signal_w,SIGINT);
ev_io_start(main_loop,&io_w);
ev_timer_start(main_loop,&timer_w);
ev_signal_start(main_loop,&signal_w);
ev_run(main_loop,0);
return 0;
}