`
iunknown
  • 浏览: 410168 次
社区版块
存档分类
最新评论

集成 IOCP 到 Libevent

阅读更多
集成 IOCP 到 Libevent

完整的代码在
http://spserver.googlecode.com/files/libevent-1.4.4-iocp-3.zip

2008.08.23
http://spserver.googlecode.com/files/libevent-1.4.5-stable-iocp-2.zip
增加了 non-blocking connect 的支持。

IOCP 是真正的异步 IO ,Libevent 提供的是一个 event-driven 的接口。

异步 IO 和 event-driven 的区别:
1.对于 event-driven,需要等待内核通知我们去启动一个IO操作,然后直接得到IO操作的结果
2.对于异步IO,我们可以随时无阻塞地启动 IO,然后由内核通知我们 IO 操作何时完成

要把 IOCP 集成到 libevent ,基本的思路是用 IOCP 模拟 event-driven 接口。
在 IOCP 中有一个特性,刚好可以用来模拟 event-driven 的接口:zero byte buffer recv/send。

当我们发起 WSARecv,WSASend 的时候,需要用 WSABUF 传递一个 buffer 进去。
如果我们把这个 buffer 设置为 zero byte ,那么当 socket 可读,或者可写的时候,
通过 GQCS 同样可以得到结果。这样就等于是模拟了 event-driven 的接口。

另一方面,Windows 的 WSAEventSelect 函数提供了一个 event-driven 的 accept 功能。

...
WSAEventSelect( listenFd, hEvent, FD_ACCEPT );
...


问题在于如何把 IOCP 和 WSAEventSelect 集成起来。

通过查看 WSARecv,WSASend 的接口,可以注意到这两个接口都需要提供一个 OVERLAPPED 的结构体。
在这个结构体里有一个 hEvent 的成员。如果设置了这个 hEvent 参数,那么当这个 IO 请求完成的时候,
hEvent 将会被 signal 。详细信息可以参考下面这个 URL :

http://msdn.microsoft.com/en-us/library/ms742203(VS.85).aspx
引用
If the lpCompletionRoutine parameter is NULL, the hEvent parameter of lpOverlapped is signaled when the overlapped operation completes if it contains a valid event object handle. An application can use WSAWaitForMultipleEvents or WSAGetOverlappedResult to wait or poll on the event object.


这样看起来可以通过 WSAWaitForMultipleEvents 来集成 IOCP 和 WSAEventSelect 。
1.用 WSAEventSelect 来处理 accept event
2.用 IOCP 来处理 recv/send event ,发起 recv/send 请求的时候,设置 OVERLAPPED 的 hEvent 参数
3.把 WSAEventSelect 的 hEvent 和 IOCP 的 hEvent 收集起来,用 WSAWaitForMultipleEvents 统一处理

需要注意的时候,上述的第二步中,不需要为每个 recv/send 请求生成一个新的 hEvent,
而是所有的 recv/send 共用一个 hEvent 就行了。

在下面这个 URL 中提到,对于一个 hEvent 如果已经是 signal ,再次 signal ,不会有副作用。
http://msdn.microsoft.com/en-us/library/ms686211(VS.85).aspx
引用
Setting an event that is already set has no effect.



用代码来描述上面的这个思路,大概是下面这样。
首先创建 64 个 hEvent ,其中的 objects[0] 就用于 IOCP 中所有的 IO 操作。
其他剩余的 63 个 hEvent ,就可以用于 accept event 。
程序首先调用 WSAWaitForMultipleEvents 来等待 event 发生。
如果发现是 objects[0] 有事件,那么是 IOCP 的 IO 操作已经有完成的,就调用 GQCS 来处理。
如果发现是其他的 objects 有事件,那么就是有 accept event 发生。

/* objects[0] for iocp operations, object[1..63] for accept */
HANDLE objects[64];
struct event * accepts[64];
 
struct win32iocp_event event1;
event1.overlapped.hEvent = objects[0];
WSARecv( ..., &event1.overlapped, ... );
....
 
struct win32iocp_event event2;
event2.overlapped.hEvent = objects[0];
WSASend( ..., &event2.overlapped, ... );
...
 
WSAEventSelect( ev1->ev_fd, objects[1], FD_ACCEPT );
accepts[1] = ev1;
...
 
WSAEventSelect( ev2->ev_fd, objects[2], FD_ACCEPT );
accepts[2] = ev2;
...
 
int index = WSAWaitForMultipleEvents( 64, objects, FALSE, timeout, FALSE );
index = index - WSA_WAIT_EVENT_0;
 
if( index > 0 ) {
 struct event * event = win32iocp_op->accepts[index];
 event_active (event, EV_READ | EV_ACCEPT, 1);
}
 
if( index == 0 ) {
 for( ; ; ) {
  GetQueuedCompletionPort( ...... );
 }
}
 
分享到:
评论
9 楼 iunknown 2008-08-23  
http://spserver.googlecode.com/files/libevent-1.4.5-stable-iocp-2.zip

最新的版本使用类似于解决 non-blocking accept 的方法实现了 non-blocking connect。
需要增加一个 EV_CONNECT 的标志位,增加了一个 conn_test 的例子来示范如何使用。
8 楼 iunknown 2008-06-05  
去找了 memcached for win32 的源代码,结果可以顺利编译,并且运行起来也很正常。
http://jehiah.cz/projects/memcached-win32/

修改后的,libevent + iocp + memcached 代码下载
http://spserver.googlecode.com/files/memcached-1.2.1-iocp.zip
http://spserver.googlecode.com/files/libevent-1.4.4-iocp-2.zip
7 楼 iunknown 2008-06-05  
qiezi 写道
GetQueuedCompletionStatusEx也支持超时,用它代替select也可以吧?试试移植一个iocp版本?


GetQueuedCompletionStatusEx 和 GetQueuedCompletionStatus 的差别是前者可以一次得到多个 event 。
GetQueuedCompletionStatus 本身也支持超时的。

这里提到的要用 WSAWaitForMultipleEvents ,主要是解决 IOCP 和 WSAEventSelect 的集成。
在使用 libevent 的场景中,通常都需要把 accept,recv,send 这几个事件在同一个 event_base 里面来跑,因此集成 IOCP 和 WSAEventSelect 是很有必要的。如果不需要集成 accept 事件,那么只需要使用 zero byte buffer 就可以把 IOCP 当作 select 来用了。

这两天对 libevent 1.4.4 里面的单元测试案例进行了测试,发现了一个问题

http://msdn.microsoft.com/en-us/library/ms686358(VS.85).aspx
引用
Synchronization and Overlapped Input and Output

If an event is used, the hEvent member of the OVERLAPPED structure specifies a
handle to the allocated event object. The system sets the state of the event object
to nonsignaled when a call to the I/O function returns before the operation has been completed.


当多个 WSARecv/WSASend 使用同一个 Event 的时候,会产生 race condition 。
后来在 WSAWaitForMultipleEvents 之前,先调用一次 GetQueuedCompletionStatus ,这样可以消除这个 race condition 的影响。目前已经可以通过 regress.c 中大部分测试案例了。少部分失败的案例主要是由于环境的问题,现在是用 vc6 作为开发环境的,libevent 1.4.4 中的部分代码需要更高版本的 vs 。

最新的代码:http://spserver.googlecode.com/files/libevent-1.4.4-iocp-2.zip
6 楼 qiezi 2008-06-05  
GetQueuedCompletionStatusEx也支持超时,用它代替select也可以吧?试试移植一个iocp版本?
5 楼 qiezi 2008-06-05  
linux/solaris上的aio有多种回调/通知方式,可能和libevent结合的最简单方式是signal,因为libevent也支持它,不过我没试过,在linux下用过的是内核线程直接写同步队列然后发送socket通知唤醒libevent去处理。solaris上可以用一个port专门处理aio通知,非常方便。虽然aio大部分时候用于处理文件IO,不过它和iocp应该有相似之处吧?iocp的细节我不清楚,如果是“完成-通知”或“完成-回调”方式,应该都可以和libevent结合。
4 楼 wow 2008-06-04  
SPServer是一个很不错的框架,受到启发,我用boost::asio实现了一个类似的框架,其中的一个特点,就是很容易在单线程和多线程之间切换,好像在您以前的文章中讨论过这个问题,
原理就是实现一个Wrap类,自动实现线程的传递

http://www.cppblog.com/eXile/archive/2008/06/04/51430.html#52178
3 楼 关中刀客 2008-06-03  
iunknown 写道
bigpanda 写道
近来 iunknown 写了很多用 iocp 的东东。请教一下能否比较一下 Linux 的 epoll 和 windows 的 iocp?

据我所知 Linux 是没有异步 IO 的,那么 epoll 应该相当于 iocp 之 socket 版本,能否论证一下?


对于 epoll 和 iocp 都算不上熟悉,只是根据自己的兴趣去找了一下资料来看,然后写了一些代码来验证一下自己的理解。就目前的测试来看,两者在高并发和 IO 性能方面,都是不错的。但依目前的经验,很难说已经测试到了它们各自的最优情况。对于这种高并发的性能测试,对于系统参数的调整也是一个很大的方面。如果要做具体的比较,那么需要列举具体的应用场景,具体把代码实现出来,才能做一个比较客观的对比。

Linux 没有异步 IO 应该说的是没有针对 socket 的异步 IO 吧?对于文件 IO 是有 AIO 这套接口的。

iocp 之 socket 版本?这个描述有点不解。
不过通常都是认为 linux 的 epoll 是和 windows 的 iocp 相对应的一种技术。两者常常会被相提并论,主要应该是两者都对高并发提供了良好的支持。但是从细节的角度来说,两者在 IO 模型上是不同的。epoll api 本身就只支持一种 event-driven 的模型,iocp api 除了 async IO 模型之外,如果使用 zero byte buffer 还可以支持 event-driven 的模型。


原来你就是讨论组内的那位stephen.nil阿
呵呵,真不错
2 楼 iunknown 2008-06-03  
bigpanda 写道
近来 iunknown 写了很多用 iocp 的东东。请教一下能否比较一下 Linux 的 epoll 和 windows 的 iocp?

据我所知 Linux 是没有异步 IO 的,那么 epoll 应该相当于 iocp 之 socket 版本,能否论证一下?


对于 epoll 和 iocp 都算不上熟悉,只是根据自己的兴趣去找了一下资料来看,然后写了一些代码来验证一下自己的理解。就目前的测试来看,两者在高并发和 IO 性能方面,都是不错的。但依目前的经验,很难说已经测试到了它们各自的最优情况。对于这种高并发的性能测试,对于系统参数的调整也是一个很大的方面。如果要做具体的比较,那么需要列举具体的应用场景,具体把代码实现出来,才能做一个比较客观的对比。

Linux 没有异步 IO 应该说的是没有针对 socket 的异步 IO 吧?对于文件 IO 是有 AIO 这套接口的。

iocp 之 socket 版本?这个描述有点不解。
不过通常都是认为 linux 的 epoll 是和 windows 的 iocp 相对应的一种技术。两者常常会被相提并论,主要应该是两者都对高并发提供了良好的支持。但是从细节的角度来说,两者在 IO 模型上是不同的。epoll api 本身就只支持一种 event-driven 的模型,iocp api 除了 async IO 模型之外,如果使用 zero byte buffer 还可以支持 event-driven 的模型。

1 楼 bigpanda 2008-06-03  
近来 iunknown 写了很多用 iocp 的东东。请教一下能否比较一下 Linux 的 epoll 和 windows 的 iocp?

据我所知 Linux 是没有异步 IO 的,那么 epoll 应该相当于 iocp 之 socket 版本,能否论证一下?

相关推荐

    集成windows iocp到libevent

    集成IOCP到libevent是一个复杂的任务,需要深入理解两个技术的内部工作原理。完成后,它将使基于libevent的应用在Windows平台上实现更高效的异步I/O处理,尤其对于高并发服务器,性能提升可能非常显著。文件...

    使用nmake或vs2008集成环境编译libevent-2.0.11-stable

    (3)切换到libevent-2.0.11-stable目录 (4)执行nmake /f Makefile.nmake 2.直接使用我已经建立好在VS2008下的编译工程,如果不熟悉上面的nmake编译方法, 直接编译libevent-2.0.11工程即可生成这个三个库文件。...

    libevent中文参考手册

    1. 在libevent 1.4版之前,只有一个名为`libevent`的库,它包含了当前分散到`libevent_core`和`libevent_extra`中的所有功能。 2. 在2.0版之前,libevent并不支持锁机制,这意味着如果在多线程环境中使用同一结构体...

    libevent C++高并发网络编程

    - **编译前准备**: 下载libevent源码,并解压到本地目录。 - **编译步骤**: 使用CMake进行配置,并通过Visual Studio生成解决方案文件。最后,使用VS2017打开解决方案并编译。 **1.2 使用VS2017编译zlib源码** - *...

    libevent-2.1.10-stable.tar.gz

    由于Coturn依赖于libevent库来处理网络事件,因此libevent的性能直接影响到Coturn服务器的响应速度和处理能力。 libevent的主要特点包括: 1. **多事件机制**:libevent支持多种操作系统提供的事件通知机制,如...

    DameoLibeventServer.7z

    本示例“DameoLibeventServer”正是基于libevent库在Windows 10操作系统和Visual Studio 2019集成开发环境中实现的一个TCP服务端程序。 libevent库的核心功能在于它能够管理大量的异步事件,并且以非阻塞的方式处理...

    开源项目-buguang01-gsframe.zip

    5. **数据库集成**:游戏数据通常存储在数据库中,框架可能集成了常见的数据库接口,如MySQL、PostgreSQL或MongoDB,以便于进行数据读写操作。 6. **状态机设计**:游戏服务器可能使用状态机模式处理不同游戏阶段,...

    C++ 实现WebSocket 服务器 可运行.zip

    6. **事件驱动编程**:如使用libevent或libev等库,可以更高效地处理大量并发连接,当有事件发生时(如新连接、数据到达等),事件驱动框架会通知应用程序进行相应的处理。 7. **错误处理**:在实际开发中,必须...

    Visual C++ 网络

    除了基础的Winsock API,还有许多现成的网络编程框架可供选择,如ACE、Poco、libevent等,它们提供了更高级别的抽象,简化了网络编程的复杂性。 通过以上知识点,开发者可以使用Visual C++创建复杂的网络应用程序,...

    telnet_后端

    4. **异步I/O**:为了进一步提高效率,可以使用异步I/O模型,如Linux的epoll或Windows的IOCP,它们允许程序在等待I/O操作完成时执行其他任务。 5. **事件驱动编程**:另一种处理并发的方式是使用事件驱动编程,如...

Global site tag (gtag.js) - Google Analytics