这两个库都是为异步 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 会根据某个未知的 future 基准时间来安排计时器,而您却不知道。 libev 可以提前告诉你它将使用什么基本时间来调度计时器,这允许程序同时使用 libevent 方法和 libev 方法。此外,libevent 有时会提前到期,具体取决于后端。前者是 API 问题,后者是可修复的(并且可能已经修复了 - 我没有检查)。
至于 IOCP 支持 - 我认为它无法完成,因为 IOCP 根本不够强大。一方面,他们需要一种特殊的套接字类型,这将进一步限制 Windows 上允许的句柄集(例如,perl 使用的 sopcket 是 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 - libev 和 libevent 有什么区别?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9433864/