libevent - event_base_loop() 是不是应该重复获取事件?

Posted

技术标签:

【中文标题】libevent - event_base_loop() 是不是应该重复获取事件?【英文标题】:libevent - event_base_loop() should it get events repeatly?libevent - event_base_loop() 是否应该重复获取事件? 【发布时间】:2016-02-02 04:31:28 【问题描述】:

这是一个在linux上使用libevent的简单程序,它跟踪stdout fd,当它可写时,回调将打印一些信息到stdout


代码

hello_libevent.c:

// libevent hello
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>

#include <event2/event.h>
#include <event2/thread.h>


void event_callback(evutil_socket_t fd, short events, void *arg) 
    if(events | EV_WRITE) 
        write(fd, "hello\n", 7);
    

    sleep(1);


int libevent_test() 
    int opr;

    // enable pthread
    if(evthread_use_pthreads() == -1) 
        printf("error while evthread_use_pthreads(): %s\n", strerror(errno));
        return -1;
    

    // create event_base
    struct event_base* eb;
    if((eb = event_base_new()) == NULL) 
        printf("error while event_base_new(): %s\n", strerror(errno));
        return -1;
    

    // create event
    int fd_stdout = fileno(stdout);
    struct event* event_stdout;
    event_stdout = event_new(eb, fd_stdout, EV_WRITE, &event_callback, NULL);

    // add event as pending
    struct timeval timeout = 10, 0;
    if(event_add(event_stdout, &timeout) == -1) 
        printf("error while event_add(): %s\n", strerror(errno));
        return -1;
    

    // dispatch
    if((opr = event_base_loop(eb, EVLOOP_NONBLOCK)) == -1) 
        printf("error while event_base_dispatch(): %s\n", strerror(errno));
        return -1;
     else if(opr == 1) 
        printf("no more events\n");
     else 
        printf("exit normally\n");
    

    // free event
    event_free(event_stdout);

    return 0;


int main(int argc, char * argv[]) 
    return libevent_test();

编译:

gcc -Wall hello_libevent.c -levent -levent_pthreads

执行结果:

hello
no more events

问题:

在测试中,事件只发生一次,这是预期的行为吗?或者它应该循环获取更多事件直到超时? 如何让它连续获取事件?是否有必要在循环中调用event_base_loop,而它已经是loop

【问题讨论】:

你读过这个reference @SelçukCihan 刚读完,我更新了问题,你能帮忙吗? 关于你的第一个问题,是的,它会在它被处理(发生)后被删除,我相信这是相当合理的。至于第二个问题,返回值 1 在某种意义上也是成功,因为它表示一切顺利,但是没有更多的事件未决。 如果您不想自己循环,请尝试设置 EVLOOP_NO_EXIT_ON_EMPTY,这样即使没有未决事件,libevent 循环也不会退出。 【参考方案1】:

我认为event.h File Reference 中提到的事件标志EV_PERSIST 可能会有所帮助。

持久事件:激活后不会自动删除。

当一个具有超时的持久事件被激活时,它的超时时间被重置为 0。

代替

//...
event_stdout = event_new(eb, fd_stdout, EV_WRITE, &event_callback, NULL);
//...

您可以将此标志传递给event_new

//...
event_stdout = event_new(eb, fd_stdout, EV_WRITE|EV_PERSIST, &event_callback, NULL);
//...

和其他部分代码保持不变。此时您创建并添加一次事件,无需在循环中调用 event_base_loop。 编译后的程序只是保持打印“hello”行直到它被终止。

顺便说一句,我注意到了变化

write(fd, "hello\n", 7);

进入

write(fd, "hello\n", 6);

消除每行的前导字符“\0”。

【讨论】:

是的,它确实解决了所描述的问题。似乎\0 仅在内存中表示字符串时才需要,而不是在文件中。【参考方案2】:

从http://www.wangafu.net/~nickm/libevent-book/Ref3_eventloop.html 看来,您可以在循环中调用event_base_loopevent_base_dispatch

while (1) /* This schedules an exit ten seconds from now. */ event_base_loopexit(base, &ten_sec);`` event_base_dispatch(base); puts("Tick");

事件的主要目的是通知一些繁忙的线程关于在别处发生的一些事件。所以,这看起来合乎逻辑。

【讨论】:

以上是关于libevent - event_base_loop() 是不是应该重复获取事件?的主要内容,如果未能解决你的问题,请参考以下文章

如何编译和安装libevent

Libevent源码分析--- libevent事件机制

Libevent源码分析--- libevent事件机制

libevent学习笔记(参考libevent深度剖析)

libevent网络编程汇总

Libevent 学习笔记 ——Libevent 2.0安装与简单演示样例