这两个库都是为异步 i/o 调度而设计的,并且都在 linux 上使用 epoll,在 FreeBSD 上使用 kqueue 等。
除了表面上的差异,我的意思是这两个库之间真正的区别是什么?关于建筑,或设计理念?
至于设计理念,创建 libev 是为了改进 libevent 中的一些架构决策,例如,全局变量的使用使得在多线程环境中难以安全地使用 libevent,观察器结构很大,因为它们结合了 I/O、时间和信号处理程序合二为一,诸如 http 和 dns 服务器之类的额外组件遭受了糟糕的实现质量和由此产生的安全问题,并且计时器不精确并且不能很好地应对时间跳跃。
Libev 试图通过不使用全局变量而是对所有函数使用循环上下文,通过对每种事件类型使用小型观察程序(I/O 观察程序在 x86_64 上使用 56 个字节,而在 libevent 上使用 136 个字节)来改进其中的每一个,允许额外的事件类型,例如基于挂钟与单调时间的计时器、线程间中断、准备和检查观察者以嵌入其他事件循环或被嵌入等等。
额外的组件问题通过根本没有它们来“解决”,因此 libev 可以小而高效,但您还需要在其他地方寻找 http 库,因为 libev 根本没有(例如,有一个非常相关的 libeio 库,它做异步 I/O,可以独立使用,也可以与 libev 一起使用,所以你可以混合搭配)。
所以简而言之,libev 只尝试做一件事(POSIX 事件库),并且以最有效的方式。Libevent 试图为您提供完整的解决方案(事件库、非阻塞 I/O 库、http 服务器、DNS 客户端)。
或者,甚至更短,libev 试图遵循 UNIX 工具箱的哲学,即只做一件事,尽可能好。
请注意,这是设计理念,我可以权威地声明,因为我设计了 libev。这些设计目标是否真的达到了,或者哲学是否基于合理的原则,由你来判断。
2017 年更新:
我多次被问到我指的是什么计时器不精确,以及为什么 libev 不支持 Windows 上的 IOCP。
至于计时器,libevent 会根据未来某个未知的基准时间安排计时器,而您并不知道。Libev 可以提前告诉您它将使用什么基准时间来安排计时器,这允许程序同时使用 libevent 方法和 libev 方法。此外,libevent 有时会提前过期计时器,具体取决于后端。前者是 API 问题,后者是可修复的(并且可能已经修复 - 我没有检查)。
至于 IOCP 支持——我不认为它可以做到,因为 IOCP 根本不够强大。一方面,他们需要一种特殊的套接字类型,这将进一步限制 Windows 上允许的句柄集(例如,perl 使用的套接字是 IOCP 的“错误”类型)。此外,IOCP 根本不支持 I/O 就绪事件,它们只能执行实际的 I/O。有一些句柄类型的变通方法,例如进行虚拟 0 字节读取,但同样,这会限制您可以在 Windows 上使用的句柄类型,而且会依赖可能未由所有套接字提供程序共享的未记录行为.
据我所知,没有其他事件库支持 Windows 上的 IOCP。libevent 所做的是,除了事件库之外,它还允许您将读/写操作排队,然后可以通过 IOCP 完成。由于 libev 不会为您执行 I/O,因此无法在 libev 本身中使用 IOCP。
这确实是设计使然——libev 试图做到小型且类似于 POSIX,而 Windows 根本没有有效的方法来获取 POSIX 样式的 I/O 事件。如果 IOCP 很重要,您要么必须自己使用它们,要么确实使用为您执行 I/O 的许多其他框架中的一些,因此可以使用 IOCP。
libevent对我来说最大的优势是内置的 OpenSSL 支持。Bufferevent 接口,在 2.0 版本的libevent API 中引入,为开发人员几乎轻松地处理安全连接。可能是我的知识已经过时了,但似乎libev不支持这一点。