Libevent工作流程

Libevent工作流程:
//使用默认的event_base配置  
struct event_base *base = event_base_new();  
struct event *cmd_ev = event_new(base, STDIN_FILENO,EV_READ | EV_PERSIST, cmd_cb, NULL);  
event_add(cmd_ev, NULL); //没有超时  
event_base_dispatch(base); 


//使用自己的event_base,创建event结构体
event_new(struct event_base *base, evutil_socket_t fd, short events, void (*cb)(evutil_socket_t, short, void *), void *arg)
//使用默认的event_base
event_set(struct event *ev, evutil_socket_t fd, short events,void (*callback)(evutil_socket_t, short, void *), void *arg)
//创建event_base
event_base_new
//将event_base和event关联
event_base_set


一个event被加入多个队列的原因:
同一个文件描述符或者信号值对应的多个event会被连在一起,
所有的被加入到event_base的event(加入event_base的event应该都是被注册的)也会连在一起,
所有被激活的event也会被连在一起


创建event_base
event_base_new函数。它是由event_base_new_with_config函数实现的。
struct event_base *  event_base_new_with_config(const struct event_config *cfg) 
这个函数主要是对event_base进行一些配置,另外还讲到了怎么使用选择一个多IO复用函数,evsel->init()。


创建event
event_new函数的工作只是创建一个struct event结构体,然后把它的参数原封不动地传给event_assign,event_assign将even_base赋值给event中的even_base
int  event_assign(struct event *ev, struct event_base *base, evutil_socket_t fd,   
             short events, void (*callback)(evutil_socket_t, short, void *), void *arg)


将event加入到event_base中,实质是将事件加入到不同的队列中
event_add()->event_add_internal(){evmap_io_add(),evmap_signal_add(),event_queue_insert(,,EVLIST_INSERTED)}
在event_base这个结构体中有一个event_io_map类型的成员变量io,它就是一个哈希表。
evmap_io_add函数三个功能,每个功能对应下面的三个函数
第一,把要监听的fd或者sig添加到多路IO复用函数中,使得其是可以监听的。
第二,当一个监听读或者写操作的event,将其插入到event_base中时
第三,把event插入到inserted(已注册队列中)
evsel->add(base, ev->ev_fd,old, (ev->ev_events & EV_ET) | res, extra);
TAILQ_INSERT_TAIL(&ctx->events, ev, ev_io_next);
event_queue_insert();这个函数是把event添加到不同的队列中(注册,激活,定时)


进入主循环,开始监听event
event_base_dispatch()->event_base_loop(){evsel->dispatch(),event_process_active()}
在event_base_loop函数内部会进行加锁,这是因为这里要对event_base里面的多个队列进行一些数据操作(增删操作)
evsel->dispatch:调用多路IO复用函数,对event进行监听,并且把满足条件的event放到event_base的激活队列中
event_process_active:遍历这个激活队列的所有event,逐个调用对应的回调函数。


深入看看Libevent是怎么把event添加到激活队列的。
dispatch是一个函数指针,它的实现都包含是一个多路IO复用函数。这里选择poll这个多路IO复用函数来作分析
在evmap_io_add函数里面,有一个evsel->add调用,它会把数据(fd和对应的监听类型)放到pollfd数组中。
当主线程从poll返回时,没有错误的话,就说明有些监听的事件发生了。
在函数的后面,它会遍历这个pollfd数组,查看哪个fd是有事件发生。如果事件发生,就调用evmap_io_active
poll_dispatch()->evmap_io_active()->event_active_nolock->event_queue_insert(,,EVLIST_ACTIVE);
遍历激活数组队列,把所有激活的event都处理即可,从高到低优先级遍历激活event优先级数组。
event_process_active()->event_process_active_single_queue()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值