面试题答案
一键面试事件注册
- 初始化:首先需要创建一个
event_base
对象,这是Libevent的核心数据结构,用于管理所有事件。通过event_base_new()
函数来创建,此函数会初始化一些内部数据结构,包括事件队列、时间堆等。 - 创建事件:使用
event_new()
函数创建具体的事件对象。该函数需要传入event_base
指针、文件描述符(如套接字描述符)、事件类型(如读事件EV_READ
、写事件EV_WRITE
)、事件处理回调函数以及传递给回调函数的参数。例如:
struct event *ev;
ev = event_new(base, fd, EV_READ|EV_PERSIST, my_event_callback, (void*)arg);
这里my_event_callback
是自定义的事件处理函数,arg
是传递给该函数的参数,EV_PERSIST
表示事件触发后不会自动删除,会一直存在直到手动删除。
3. 添加事件:通过event_add()
函数将创建好的事件添加到event_base
中。此函数会将事件插入到相应的事件队列中,等待被处理。例如:
event_add(ev, NULL);
NULL
表示使用默认的超时时间。
事件分发
- 事件循环:Libevent通过
event_base_dispatch()
函数进入事件循环。在这个循环中,它会不断检查是否有事件发生。 - 等待事件:使用操作系统提供的多路复用机制(如
select
、poll
、epoll
等,具体取决于系统和Libevent的配置)来等待事件发生。这些多路复用函数会阻塞当前线程,直到有事件就绪或者超时。 - 获取就绪事件:当多路复用函数返回时,它会告知Libevent哪些文件描述符上有事件发生。Libevent根据这些信息,从事件队列中找到对应的事件对象。
事件处理
- 调用回调函数:Libevent找到就绪的事件后,会调用该事件注册时指定的回调函数。例如,在前面创建事件时指定的
my_event_callback
函数会被调用。在回调函数中,可以进行具体的业务逻辑处理,如读取套接字数据、处理网络请求等。 - 事件删除(可选):如果事件在创建时没有指定
EV_PERSIST
标志,那么在事件处理完毕后,Libevent会自动将该事件从event_base
中删除。如果需要手动删除事件,可以使用event_del()
函数。例如:
event_del(ev);
这样就可以在合适的时机手动删除不再需要的事件。