没有合适的资源?快使用搜索试试~ 我知道了~
异步IO、APC、IO完成端口、线程池与高性能服务器.doc
4星 · 超过85%的资源 需积分: 9 78 下载量 174 浏览量
2009-05-17
11:53:36
上传
评论
收藏 369KB DOC 举报
温馨提示
试读
28页
异步IO、APC、IO完成端口、线程池与高性能服务器相关的五个文档整理在一个文档中,方便各位学习参考。
资源推荐
资源详情
资源评论
《异步IO、APC、IO完成端口、线程池与高性能服务
器》
异步IO、APC、IO完成端口、线程池与高性能服务器(一) 异步IO...................1
异步IO、APC、IO完成端口、线程池与高性能服务器之(二) APC....................2
异步IO、APC、IO完成端口、线程池与高性能服务器(三) IO完成端口................4
异步IO、APC、IO完成端口、线程池与高性能服务器(四) 线程池...................7
异步IO、APC、IO完成端口、线程池与高性能服务器(五) 服务器的性能指标..........14
四种进程或线程同步互斥的控制方法.........................................16
异步IO、APC、IO完成端口、线程池与高性能服务器(一) 异步IO
背景:轮询 PIO DMA 中断
早期IO设备的速度与CPU相比,还不是太悬殊。CPU定时轮询一遍IO设备,看看有无处理要
求,有则加以处理,完成后返回继续工作。至今,软盘驱动器还保留着这种轮询工作方式。
随着CPU性能的迅速提高,这种效率低下的工作方式浪费了大量的CPU时间。因此,中断工作
方式开始成为普遍采用的技术。这种技术使得IO设备在需要得到服务时,能够产生一个硬件中断
迫使CPU放弃目前的处理任务,进入特定的中断服务过程,中断服务完成后,再继续原先的处理。
这样一来,IO设备和CPU可以同时进行处理,从而避免了CPU等待IO完成。
早期数据的传输方式主要是PIO(程控IO)方式。通过对IO地址编程方式的方式来传输数据
比如串行口,软件每次往串行口上写一个字节数据,串口设备完成传输任务后,将会产生一个中断
然后软件再次重复直到全部数据发送完成。性能更好的硬件设备提供一个FIFO(先进先出缓冲部
件),可以让软件一次传输更多的字节。
显然,使用PIO方式对于高速IO设备来说,还是占用了太多的CPU时间(因为需要通过CPU编
程控制传输)。而DMA(直接内存访问)方式能够极大地减少CPU处理时间。CPU仅需告诉DMA控
制器数据块的起始地址和大小,以后DMA控制器就可以自行在内存和设备之间传输数据,其间CPU
可以处理其他任务。数据传输完毕后将会产生一个中断。
同步文件IO和异步文件IO
下面摘抄于MSDN《synchronous file I/O and asynchronous file I/O》。
有两种类型的文件IO同步:同步文件IO和异步文件IO。异步文件IO也就是重叠IO。
在同步文件IO中,线程启动一个IO操作然后就立即进入等待状态,直到IO操作完成后才醒来继续
执行。而异步文件IO方式中,线程发送一个IO请求到内核,然后继续处理其他的事情,内核完成
IO请求后,将会通知线程IO操作完成了。
如果IO请求需要大量时间执行的话,异步文件IO方式可以显著提高效率,因为在线程等待的
这段时间内,CPU将会调度其他线程进行执行,如果没有其他线程需要执行的话,这段时间将会浪
费掉(可能会调度操作系统的零页线程)。如果IO请求操作很快,用异步IO方式反而还低效,还
不如用同步IO方式。
同步IO在同一时刻只允许一个IO操作,也就是说对于同一个文件句柄的IO操作是序列化的,
即使使用两个线程也不能同时对同一个文件句柄同时发出读写操作。重叠IO允许一个或多个线程
同时发出IO请求。
异步IO在请求完成时,通过将文件句柄设为有信号状态来通知应用程序,或者应用程序通过
GetOverlappedResult察看IO请求是否完成,也可以通过一个事件对象来通知应用程序。
1
异步IO、APC、IO完成端口、线程池与高性能服务器之(二) APC
Alertable IO(告警IO)提供了更有效的异步通知形式。ReadFileEx / WriteFileEx在发出
IO请求的同时,提供一个回调函数(APC过程),当IO请求完成后,一旦线程进入可告警状态,
回调函数将会执行。
以下五个函数能够使线程进入告警状态:
SleepEx
WaitForSingleObjectEx
WaitForMultipleObjectsEx
SignalObjectAndWait
MsgWaitForMultipleObjectsEx
线程进入告警状态时,内核将会检查线程的APC队列,如果队列中有APC,将会按FIFO方式
依次执行。如果队列为空,线程将会挂起等待事件对象。以后的某个时刻,一旦APC进入队列,线
程将会被唤醒执行APC,同时等待函数返回WAIT_IO_COMPLETION。
QueueUserAPC可以用来人为投递APC,只要目标线程处于告警状态时,APC就能够得到执
行。
使用告警IO的主要缺点是发出IO请求的线程也必须是处理结果的线程,如果一个线程退出时
还有未完成的IO请求,那么应用程序将永远丢失IO完成通知。然而以后我们将会看到IO完成端口
没有这个限制。
下面的代码演示了QueueUserAPC的用法。
/***********************************************************/
/*APC Test.*/
/***********************************************************/
DWORD WINAPI WorkThread(PVOID pParam)
{
HANDLE Event = (HANDLE)pParam;
for(;;)
{
DWORD dwRet = WaitForSingleObjectEx(Event, INFINITE, TRUE);
if(dwRet == WAIT_OBJECT_0)
break;
else if(dwRet == WAIT_IO_COMPLETION)
printf("WAIT_IO_COMPLETION\n");
}
return 0;
}
VOID CALLBACK APCProc(DWORD dwParam)
{
printf("%s", (PVOID)dwParam);
2
}
void TestAPC(BOOL bFast)
{
HANDLE QuitEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
HANDLE hThread = CreateThread(NULL,
0,
WorkThread,
(PVOID)QuitEvent,
0,
NULL);
Sleep(100); // Wait for WorkThread initialized.
for(int i=5; i>0; i--)
{
QueueUserAPC(APCProc, hThread, (DWORD)(PVOID)"APC here\n");
if(!bFast)
Sleep(1000);
}
SetEvent(QuitEvent);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
3
异步IO、APC、IO完成端口、线程池与高性能服务器(三) IO完成端口
IO完成端口
下面摘抄于MSDN《I/O Completion Ports》, smallfool翻译,原文请参考CSDN文档中心
文章《I/O Completion Ports》, http://dev.csdn.net/Develop/article/29%5C29240.shtm 。
I/O完成端口是一种机制,通过这个机制,应用程序在启动时会首先创建一个线程池,然后该应用
程序使用线程池处理异步I/O请求。这些线程被创建的唯一目的就是用于处理I/O请求。对于处理
大量并发异步I/O请求的应用程序来说,相比于在I/O请求发生时创建线程来说,使用完成端口
(s)它就可以做的更快且更有效率。
CreateIoCompletionPort函数会使一个I/O完成端口与一个或多个文件句柄发生关联。当与一
个完成端口相关的文件句柄上启动的异步I/O操作完成时,一个I/O完成包就会进入到该完成端口
的队列中。对于多个文件句柄来说,这种机制可以用来把多文件句柄的同步点放在单个对象中。
(言下之意,如果我们需要对每个句柄文件进行同步,一般而言我们需要多个对象(如:Event来
同步),而我们使用IO Complete Port 来实现异步操作,我们可以同多个文件相关联,每当
一个文件中的异步操作完成,就会把一个complete package放到队列中,这样我们就可以使用
这个来完成所有文件句柄的同步)
调用GetQueuedCompletionStatus函数,某个线程就会等待一个完成包进入到完成端口的队列
中,而不是直接等待异步I/O请求完成。线程(们)就会阻塞于它们的运行在完成端口(按照后进
先出队列顺序的被释放)。这就意味着当一个完成包进入到完成端口的队列中时,系统会释放最近
被阻塞在该完成端口的线程。
调用GetQueuedCompletionStatus,线程就会将会与某个指定的完成端口建立联系,一直延续
其该线程的存在周期,或被指定了不同的完成端口,或者释放了与完成端口的联系。一个线程只能
与最多不超过一个的完成端口发生联系。
完成端口最重要的特性就是并发量。完成端口的并发量可以在创建该完成端口时指定。该并发量限
制了与该完成端口相关联的可运行线程的数目。当与该完成端口相关联的可运行线程的总数目达到
了该并发量,系统就会阻塞任何与该完成端口相关联的后续线程的执行,直到与该完成端口相关联
的可运行线程数目下降到小于该并发量为止。最有效的假想是发生在有完成包在队列中等待,而没
有等待被满足,因为此时完成端口达到了其并发量的极限。此时,一个正在运行中的线程调用
GetQueuedCompletionStatus时,它就会立刻从队列中取走该完成包。这样就不存在着环境的
切换,因为该处于运行中的线程就会连续不断地从队列中取走完成包,而其他的线程就不能运行了
对于并发量最好的挑选值就是您计算机中CPU的数目。如果您的事务处理需要一个漫长的计算时间
一个比较大的并发量可以允许更多线程来运行。虽然完成每个事务处理需要花费更长的时间,但更
多的事务可以同时被处理。对于应用程序来说,很容易通过测试并发量来获得最好的效果。
PostQueuedCompletionStatus函数允许应用程序可以针对自定义的专用I/O完成包进行排队
而无需启动一个异步I/O操作。这点对于通知外部事件的工作者线程来说很有用。
在没有更多的引用针对某个完成端口时,需要释放该完成端口。该完成端口句柄以及与该完成端口
相关联的所有文件句柄都需要被释放。调用CloseHandle可以释放完成端口的句柄。
下面的代码利用IO完成端口做了一个简单的线程池。
/*********************************************************/
/*Test IOCompletePort.*/
/********************************************************/
4
剩余27页未读,继续阅读
资源评论
- BobLiu2013-05-14很好,楼主集结了这5篇,用心了
- zhangjiepeng04052012-10-07很好,楼主集结了这5篇,用心了。
tongbaby
- 粉丝: 0
- 资源: 5
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功