【问题标题】:Libev - I/O callbacksLibev - I/O 回调
【发布时间】:2012-02-26 09:15:13
【问题描述】:

我在 C/Linux 中有一个使用 TCP 套接字的聊天服务器。使用 libev 时,我可以为套接字的读取事件创建一个 ev_io 观察程序。比如:

ev_io* new_watcher = (ev_io*)malloc(sizeof(ev_io));

//initialize the watcher
ev_init(new_watcher, read_cb);

//set the fd and event to fire on write
ev_io_set(new_watcher, watcher->fd, EV_READ);

//start watching
ev_io_start(loop, new_watcher);

这很好用,因为只有在有数据要读取时才会触发读取事件。但是,我必须以不同的方式处理写入事件,因为即使我没有要写入的数据,它们也会不断触发。为了解决这个问题,我让我的 read_callback 创建一个 ev_io 观察者,仅当有数据准备好写入时才写入数据,然后 write_callback 将在发送消息后删除观察者。

这意味着每次我需要处理消息时,我都在分配、初始化、设置、观察、取消观察和解除分配写观察者。我担心我可能会不正确且低效地处理这个问题。

在 libev 中处理 write_callback 事件的最佳方法是什么?

提前致谢。

【问题讨论】:

    标签: c linux sockets libev


    【解决方案1】:

    很简单,还有 ev_io_stop,所以你要做的不是启动 write watcher,除非你有什么要写的,在回调中,当你写完整个缓冲区后调用 ev_io_stop。

    在您很少溢出写入缓冲区的常见情况下(因为您的数据很小并且您不会经常写入),您可以通过尝试直接写入数据来提高效率(如果观察者不活动) 并且仅在无法完全写入数据时缓冲数据并启动写入观察程序。

    根据上述假设,这意味着您几乎不需要启动写入观察程序。缺点是代码要复杂得多,因此在许多情况下,最好从简单的“将数据追加到写入缓冲区,启动观察程序,如果缓冲区已写满则在观察程序内部停止”逻辑开始。

    【讨论】:

      【解决方案2】:

      分配会增加一些开销,您可以使用静态变量而不是 malloc,或者 malloc 一次并且仅在事件循环完成后释放。 您只需要在写入之前设置并在成功后取消设置。但是,是的,这就是它需要完成的方式。

      【讨论】:

        【解决方案3】:

        我解决这种情况的方法是有一个写入数据的函数,该函数接受指向缓冲区的指针和长度。它将指针和长度存储在队列数据结构中并启用写事件。

        当写入事件回调触发时,它会检查写入队列以查看是否有任何待处理的写入。如果有,它将获取队列中的下一个挂起写入并将其写入文件描述符。然后就在写回调退出之前,它检查挂起的写队列是否为空。如果是这样,那么它会禁用写事件。

        如果您将读/写事件对象设为全局变量,那么它们只会被分配和释放一次。只要知道有数据要写入,就启用 write 事件,一旦没有数据要写入,就禁用它。

        我的代码比上面的描述要复杂一些,但我会在此处发布一个链接,以便您查看。我说的具体代码在aiofd.h和aiofd.c(aiofd ==异步I/O文件描述符)中:https://bitbucket.org/wookie/cutil/

        我希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-05-24
          • 1970-01-01
          • 2016-11-18
          • 2021-09-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多