Inside IO Completion Ports.html 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. <!-- saved from url=(0113)https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml -->
  2. <html><!-- #BeginTemplate "/Templates/template.dwt" --><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  3. <script type="text/javascript" src="./Inside IO Completion Ports_files/analytics.js"></script><style type="text/css"></style>
  4. <script type="text/javascript">archive_analytics.values.server_name="wwwb-app2.us.archive.org";archive_analytics.values.server_ms=250;</script>
  5. <link type="text/css" rel="stylesheet" href="./Inside IO Completion Ports_files/banner-styles.css">
  6. <!-- #BeginEditable "doctitle" -->
  7. <title>Sysinternals Freeware - Information for Windows NT and Windows 2000 - Inside I/O Completion Ports</title>
  8. <!-- #EndEditable -->
  9. <meta http-equiv="Content-Type" content="text/html;">
  10. <script language="JavaScript">
  11. <!--
  12. function MM_swapImgRestore() { //v3.0
  13. var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
  14. }
  15. function MM_preloadImages() { //v3.0
  16. var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
  17. var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
  18. if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
  19. }
  20. function MM_swapImage() { //v3.0
  21. var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
  22. if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
  23. }
  24. function MM_findObj(n, d) { //v4.0
  25. var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
  26. d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  27. if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  28. for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  29. if(!x && document.getElementById) x=document.getElementById(n); return x;
  30. }
  31. //-->
  32. </script>
  33. <link rel="stylesheet" href="./Inside IO Completion Ports_files/default.css" type="text/css">
  34. </head>
  35. <body topmargin="0" leftmargin="0" marginheight="0" marginwidth="0" bgcolor="#ffffff" background="./Inside IO Completion Ports_files/background.gif" onload="MM_preloadImages(&#39;../../images/topmenu_images/otop_menu_resources.gif&#39;,&#39;../../images/topmenu_images/otop_menu_aboutus.gif&#39;,&#39;../../images/topmenu_images/otop_menu_global.gif&#39;,&#39;../../images/sidemenu_images/oside_menu_98_utilities.gif&#39;,&#39;../../images/sidemenu_images/oside_menu_utilities.gif&#39;,&#39;../../images/sidemenu_images/oside_menu_source.gif&#39;,&#39;../../images/sidemenu_images/oside_menu_information.gif&#39;,&#39;../../images/sidemenu_images/oside_menu_98_source.gif&#39;,&#39;../../images/sidemenu_images/oside_menu_98_information.gif&#39;,&#39;../../images/topmenu_images/otop_menu_resources.gif&#39;,&#39;../../images/topmenu_images/otop_menu_sitemap.gif&#39;,&#39;../../images/topmenu_images/otop_menu_licensing.gif&#39;,&#39;../../images/topmenu_images/otop_menu_aboutus.gif&#39;,&#39;../../images/topmenu_images/otop_menu_global.gif&#39;)"><div id="wm-ipp" lang="en" style="display: block;">
  36. <div style="position:fixed;left:0;top:0;width:100%!important">
  37. <div id="wm-ipp-inside">
  38. <table style="width:100%;"><tbody><tr>
  39. <td id="wm-logo">
  40. <a href="https://web.archive.org/web/" title="Wayback Machine home page"><img src="./Inside IO Completion Ports_files/wayback-toolbar-logo.png" alt="Wayback Machine" width="110" height="39" border="0"></a>
  41. </td>
  42. <td class="c">
  43. <table style="margin:0 auto;"><tbody><tr>
  44. <td class="u" colspan="2">
  45. <form target="_top" method="get" action="https://web.archive.org/web/form-submit.jsp" name="wmtb" id="wmtb"><input type="text" name="url" id="wmtbURL" value="http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml" style="width:400px;" onfocus="this.focus();this.select();"><input type="hidden" name="type" value="replay"><input type="hidden" name="date" value="20101031075704"><input type="submit" value="Go"><span id="wm_tb_options" style="display:block;"></span></form>
  46. </td>
  47. <td class="n" rowspan="2">
  48. <table><tbody>
  49. <!-- NEXT/PREV MONTH NAV AND MONTH INDICATOR -->
  50. <tr class="m">
  51. <td class="b" nowrap="nowrap">
  52. <a href="https://web.archive.org/web/20100929175007/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml" title="29 Sep 2010">SEP</a>
  53. </td>
  54. <td class="c" id="displayMonthEl" title="You are here: 7:57:04 Oct 31, 2010">OCT</td>
  55. <td class="f" nowrap="nowrap">
  56. <a href="https://web.archive.org/web/20101218172039/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml" title="18 Dec 2010"><strong>DEC</strong></a>
  57. </td>
  58. </tr>
  59. <!-- NEXT/PREV CAPTURE NAV AND DAY OF MONTH INDICATOR -->
  60. <tr class="d">
  61. <td class="b" nowrap="nowrap">
  62. <a href="https://web.archive.org/web/20100929175007/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml" title="17:50:07 Sep 29, 2010"><img src="./Inside IO Completion Ports_files/wm_tb_prv_on.png" alt="Previous capture" width="14" height="16" border="0"></a>
  63. </td>
  64. <td class="c" id="displayDayEl" style="width:34px;font-size:24px;" title="You are here: 7:57:04 Oct 31, 2010">31</td>
  65. <td class="f" nowrap="nowrap">
  66. <a href="https://web.archive.org/web/20101101112358/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml" title="11:23:58 Nov 1, 2010"><img src="./Inside IO Completion Ports_files/wm_tb_nxt_on.png" alt="Next capture" width="14" height="16" border="0"></a>
  67. </td>
  68. </tr>
  69. <!-- NEXT/PREV YEAR NAV AND YEAR INDICATOR -->
  70. <tr class="y">
  71. <td class="b" nowrap="nowrap">
  72. 2009
  73. </td>
  74. <td class="c" id="displayYearEl" title="You are here: 7:57:04 Oct 31, 2010">2010</td>
  75. <td class="f" nowrap="nowrap">
  76. <a href="https://web.archive.org/web/20111109105607/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml" title="9 Nov 2011"><strong>2011</strong></a>
  77. </td>
  78. </tr>
  79. </tbody></table>
  80. </td>
  81. </tr>
  82. <tr>
  83. <td class="s">
  84. <a class="t" href="https://web.archive.org/web/20101031075704*/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml" title="See a list of every capture for this URL">19 captures</a>
  85. <div class="r" title="Timespan for captures of this URL">26 Jul 10 - 15 Aug 13</div>
  86. </td>
  87. <td class="k">
  88. <a href="" id="wm-graph-anchor">
  89. <div id="wm-ipp-sparkline" title="Explore captures for this URL">
  90. <img id="sparklineImgId" alt="sparklines" onmouseover="__wm.st(1)" onmouseout="__wm.st(0)" onmousemove="__wm.mv(event,this)" width="475" height="27" border="0" src="./Inside IO Completion Ports_files/graph.jsp">
  91. <div class="yt" style="display: none; width: 25px; height: 27px;"></div><div class="mt" style="display: none; width: 2px; height: 27px;"></div></div>
  92. </a>
  93. </td>
  94. </tr></tbody></table>
  95. </td>
  96. <td class="r">
  97. <a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml#close" onclick="__wm.h();return false;" style="background-image:url(/static/images/toolbar/wm_tb_close.png);top:5px;" title="Close the toolbar">Close</a>
  98. <a href="http://faq.web.archive.org/" style="background-image:url(/static/images/toolbar/wm_tb_help.png);bottom:5px;" title="Get some help using the Wayback Machine">Help</a>
  99. </td>
  100. </tr></tbody></table>
  101. </div>
  102. </div>
  103. </div>
  104. <!-- BEGIN WAYBACK TOOLBAR INSERT -->
  105. <script type="text/javascript" src="./Inside IO Completion Ports_files/disclaim-element.js"></script>
  106. <script type="text/javascript" src="./Inside IO Completion Ports_files/graph-calc.js"></script>
  107. <script type="text/javascript" src="./Inside IO Completion Ports_files/jquery.min.js"></script>
  108. <script type="text/javascript">//<![CDATA[
  109. var __wm = (function(){
  110. var wbPrefix = "/web/";
  111. var wbCurrentUrl = "http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml";
  112. var firstYear = 1996;
  113. var imgWidth = 475,imgHeight = 27;
  114. var yearImgWidth = 25,monthImgWidth = 2;
  115. var displayDay = "31";
  116. var displayMonth = "Oct";
  117. var displayYear = "2010";
  118. var prettyMonths = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
  119. var $D=document,$=function(n){return document.getElementById(n)};
  120. var trackerVal,curYear = -1,curMonth = -1;
  121. var yearTracker,monthTracker;
  122. function showTrackers(val) {
  123. if (val===trackerVal) return;
  124. var $ipp=$("wm-ipp");
  125. var $y=$("displayYearEl"),$m=$("displayMonthEl"),$d=$("displayDayEl");
  126. if (val) {
  127. $ipp.className="hi";
  128. } else {
  129. $ipp.className="";
  130. $y.innerHTML=displayYear;$m.innerHTML=displayMonth;$d.innerHTML=displayDay;
  131. }
  132. yearTracker.style.display=val?"inline":"none";
  133. monthTracker.style.display=val?"inline":"none";
  134. trackerVal = val;
  135. }
  136. function getElementX2(obj) {
  137. var $e=jQuery(obj);
  138. return (typeof $e=="undefined"||typeof $e.offset=="undefined")?
  139. getElementX(obj):Math.round($e.offset().left);
  140. }
  141. function trackMouseMove(event,element) {
  142. var eventX = getEventX(event);
  143. var elementX = getElementX2(element);
  144. var xOff = Math.min(Math.max(0, eventX - elementX),imgWidth);
  145. var monthOff = xOff % yearImgWidth;
  146. var year = Math.floor(xOff / yearImgWidth);
  147. var monthOfYear = Math.min(11,Math.floor(monthOff / monthImgWidth));
  148. // 1 extra border pixel at the left edge of the year:
  149. var month = (year * 12) + monthOfYear;
  150. var day = monthOff % 2==1?15:1;
  151. var dateString = zeroPad(year + firstYear) + zeroPad(monthOfYear+1,2) +
  152. zeroPad(day,2) + "000000";
  153. $("displayYearEl").innerHTML=year+firstYear;
  154. $("displayMonthEl").innerHTML=prettyMonths[monthOfYear];
  155. // looks too jarring when it changes..
  156. //$("displayDayEl").innerHTML=zeroPad(day,2);
  157. var url = wbPrefix + dateString + '/' + wbCurrentUrl;
  158. $("wm-graph-anchor").href=url;
  159. if(curYear != year) {
  160. var yrOff = year * yearImgWidth;
  161. yearTracker.style.left = yrOff + "px";
  162. curYear = year;
  163. }
  164. if(curMonth != month) {
  165. var mtOff = year + (month * monthImgWidth) + 1;
  166. monthTracker.style.left = mtOff + "px";
  167. curMonth = month;
  168. }
  169. }
  170. function hideToolbar() {
  171. $("wm-ipp").style.display="none";
  172. }
  173. function bootstrap() {
  174. var $spk=$("wm-ipp-sparkline");
  175. yearTracker=$D.createElement('div');
  176. yearTracker.className='yt';
  177. with(yearTracker.style){
  178. display='none';width=yearImgWidth+"px";height=imgHeight+"px";
  179. }
  180. monthTracker=$D.createElement('div');
  181. monthTracker.className='mt';
  182. with(monthTracker.style){
  183. display='none';width=monthImgWidth+"px";height=imgHeight+"px";
  184. }
  185. $spk.appendChild(yearTracker);
  186. $spk.appendChild(monthTracker);
  187. var $ipp=$("wm-ipp");
  188. $ipp&&disclaimElement($ipp);
  189. }
  190. return{st:showTrackers,mv:trackMouseMove,h:hideToolbar,bt:bootstrap};
  191. })();//]]>
  192. </script>
  193. <style type="text/css">
  194. body {
  195. margin-top:0 !important;
  196. padding-top:0 !important;
  197. min-width:800px !important;
  198. }
  199. </style>
  200. <script type="text/javascript">__wm.bt();</script>
  201. <!-- END WAYBACK TOOLBAR INSERT -->
  202. <table width="770" border="0" cellspacing="0" cellpadding="0">
  203. <tbody><tr>
  204. <td rowspan="4" width="226" valign="top">
  205. <table width="50" border="0" cellspacing="0" cellpadding="0">
  206. <tbody><tr>
  207. <td><a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/index.shtml"><img src="./Inside IO Completion Ports_files/logo.gif" width="227" height="67" border="0"></a></td>
  208. </tr>
  209. <tr valign="top">
  210. <td height="479">
  211. <table width="176" border="0" cellspacing="0" cellpadding="0" height="279">
  212. <tbody><tr valign="top">
  213. <td height="291"><img src="./Inside IO Completion Ports_files/side_menu_top.gif" width="179" height="92" align="top"><br>
  214. <a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/utilities.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image16&#39;,&#39;&#39;,&#39;../../images/sidemenu_images/oside_menu_utilities.gif&#39;,1)"><img name="Image16" border="0" src="./Inside IO Completion Ports_files/side_menu_utilities.gif" width="179" height="23" align="top"></a>
  215. <a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/source.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image11&#39;,&#39;&#39;,&#39;../../images/sidemenu_images/oside_menu_source.gif&#39;,1)"><img name="Image11" border="0" src="./Inside IO Completion Ports_files/side_menu_source.gif" width="179" height="22" align="top"></a>
  216. <a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/information.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image12&#39;,&#39;&#39;,&#39;../../images/sidemenu_images/oside_menu_information.gif&#39;,1)"><img name="Image12" border="0" src="./Inside IO Completion Ports_files/side_menu_information.gif" width="179" height="27" align="top"></a>
  217. <img src="./Inside IO Completion Ports_files/side_menu_middle.gif" width="179" height="50" align="top"><br>
  218. <a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/win9x/98utilities.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image13&#39;,&#39;&#39;,&#39;../../images/sidemenu_images/oside_menu_98_utilities.gif&#39;,1)"><img name="Image13" border="0" src="./Inside IO Completion Ports_files/side_menu_98_utilities.gif" width="179" height="18" align="top"></a>
  219. <a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/win9x/98source.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image14&#39;,&#39;&#39;,&#39;../../images/sidemenu_images/oside_menu_98_source.gif&#39;,1)"><img name="Image14" border="0" src="./Inside IO Completion Ports_files/side_menu_98_source.gif" width="179" height="26" align="top"></a>
  220. <a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/win9x/98information.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image15&#39;,&#39;&#39;,&#39;../../images/sidemenu_images/oside_menu_98_information.gif&#39;,1)"><img name="Image15" border="0" src="./Inside IO Completion Ports_files/side_menu_98_information.gif" width="179" height="24" align="top"></a>
  221. </td>
  222. </tr>
  223. </tbody></table>
  224. </td>
  225. </tr>
  226. </tbody></table>
  227. </td>
  228. <td colspan="2" valign="top">
  229. <table width="50" border="0" cellspacing="0" cellpadding="0">
  230. <tbody><tr>
  231. <td><img src="./Inside IO Completion Ports_files/top_arch.gif" width="581" height="48" align="bottom"></td>
  232. </tr>
  233. <tr valign="top">
  234. <td valign="top"><table width="581" border="0" cellspacing="0" cellpadding="0" height="48">
  235. <tbody><tr valign="top">
  236. <td><a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/othresources.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image7&#39;,&#39;&#39;,&#39;../../images/topmenu_images/otop_menu_resources.gif&#39;,1)"><img name="Image7" border="0" src="./Inside IO Completion Ports_files/top_menu_resources.gif" width="115" height="45" align="top"></a><a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/sitemap.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image8&#39;,&#39;&#39;,&#39;../../images/topmenu_images/otop_menu_sitemap.gif&#39;,1)"><img name="Image8" border="0" src="./Inside IO Completion Ports_files/top_menu_sitemap.gif" width="91" height="45" align="top"></a><a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/licensing.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image9&#39;,&#39;&#39;,&#39;../../images/topmenu_images/otop_menu_licensing.gif&#39;,1)"><img name="Image9" border="0" src="./Inside IO Completion Ports_files/top_menu_licensing.gif" width="75" height="45" align="top"></a><a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/aboutus.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image6&#39;,&#39;&#39;,&#39;../../images/topmenu_images/otop_menu_aboutus.gif&#39;,1)"><img src="./Inside IO Completion Ports_files/filler.gif" width="6" height="45" align="top" border="0"><img name="Image6" border="0" src="./Inside IO Completion Ports_files/top_menu_aboutus.gif" width="75" height="45" align="top"></a><a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/index.shtml" onmouseout="MM_swapImgRestore()" onmouseover="MM_swapImage(&#39;Image192&#39;,&#39;&#39;,&#39;../../images/topmenu_images/otop_menu_home.gif&#39;,1)"><img name="Image192" border="0" src="./Inside IO Completion Ports_files/top_menu_home.gif" width="61" height="45" align="top"></a><img src="./Inside IO Completion Ports_files/top_menu_filler.gif" width="37" height="45" align="top"><img src="./Inside IO Completion Ports_files/top_menu_end.gif" width="121" height="45" align="top"></td>
  237. </tr>
  238. </tbody></table>
  239. <!-- #BeginEditable "Section%20title/logo" --><i><b><img src="./Inside IO Completion Ports_files/comport.gif" alt="Logo" width="445" height="29"><font face="arial" size="2"><a name="top"></a><br>
  240. </font></b></i><b>Copyright © 1998&nbsp;<a href="mailto:mark@sysinternals.com">Mark
  241. Russinovich</a></b><!-- #EndEditable --></td>
  242. </tr>
  243. </tbody></table>
  244. </td>
  245. </tr>
  246. <tr>
  247. <td colspan="2" valign="top">
  248. <table width="570" border="0" cellspacing="0" cellpadding="0">
  249. <tbody><tr valign="top">
  250. <td colspan="3" height="429"><!-- #BeginEditable "Body" -->
  251. <table cellspacing="10" cellpadding="0" width="408">
  252. <tbody><tr valign="top" align="left">
  253. <td colspan="2" width="651" height="3148">
  254. <table width="580" border="0" cellspacing="0" cellpadding="0">
  255. <tbody><tr>
  256. <td valign="top">
  257. <table width="549" border="0" cellspacing="0" cellpadding="0" dwcopytype="CopyTableRow">
  258. <tbody><tr>
  259. <td colspan="3"><b></b></td>
  260. </tr>
  261. <tr>
  262. <td colspan="3" valign="top"><span class="include">Last
  263. updated July 30, 1998</span>
  264. <hr>
  265. </td>
  266. </tr>
  267. <tr>
  268. <td colspan="3" height="40" valign="middle"><span class="sectionheader">Introduction</span>
  269. </td>
  270. </tr>
  271. <tr>
  272. <td valign="TOP" colspan="3" align="left"><font color="#000000">Writing
  273. a high-performance server application requires implementing
  274. an efficient threading model. Having either too
  275. few or too many server threads to process client
  276. requests can lead to performance problems. For example,
  277. if a server creates a single thread to handle all
  278. requests clients can become starved since the server
  279. will be tied up processing one request at a time.
  280. Of course, a single thread could simultaneously
  281. process multiple requests, switching from one to
  282. another as I/O operations are started, but this
  283. architecture introduces significant complexity and
  284. cannot take advantage of multiprocessor systems.
  285. At the other extreme a server could create a big
  286. pool of threads so that virtually every client request
  287. is processed by a dedicated thread. This scenario
  288. usually leads to thread-thrashing, where lots of
  289. threads wake-up, perform some CPU processing, block
  290. waiting for I/O and then after request procesing
  291. is completed block again waiting for a new request.
  292. If nothing else, context-switches are caused by
  293. the scheduler having to divide processor time among
  294. multiple active threads.</font><br>
  295. <br>
  296. <font color="#000000">The goal of a server is to
  297. incur as few context switches as possible by having
  298. its threads avoid unnecessary blocking, while at
  299. the same time maximizing parallelism by using multiple
  300. threads. The ideal is for there to be a thread actively
  301. servicing a client request on every processor and
  302. for those threads not to block if there are additional
  303. requests waiting when they complete a request. For
  304. this to work correctly however, there must be a
  305. way for the application to activate another thread
  306. when one processing a client request blocks on I/O
  307. (like when it reads from a file as part of the processing).
  308. </font><br>
  309. <br>
  310. <font color="#000000">Windows NT 3.5 introduced
  311. a set of APIs that make this goal relatively easy
  312. to achieve. The APIs are centered on an object called
  313. a <i>completion port</i>. In this article I'm going
  314. to provide an overview of how completion ports are
  315. used and then go inside them to show you how Windows
  316. NT implements them. </font>
  317. </td>
  318. </tr>
  319. <tr>
  320. <td colspan="3" height="40" valign="middle"><span class="sectionheader">Using I/O Completion Ports </span></td>
  321. </tr>
  322. <tr>
  323. <td valign="TOP" colspan="3">Applications use completion
  324. ports as the the focal point for the completion
  325. of I/O associated with multiple file handles. Once
  326. a file is associated with a completion port any
  327. asynchronous I/O operations that complete on the
  328. file result in a completion packet being queued
  329. to the port. A thread can wait for any outstanding
  330. I/Os to complete on multiple files simply by waiting
  331. for a completion packet to be queued on the completion
  332. port. The Win32 API provides similar functionality
  333. with the <b>WaitForMultipleObjects</b> API, but
  334. the advantage that completion ports have is that
  335. concurrency, or the number of threads that an application
  336. has actively servicing client requests, is controlled
  337. with the aid of the system. <br>
  338. <br>
  339. When an application creates a completion port it
  340. specifies a concurrency value. This value indicates
  341. the maximum number of threads associated with the
  342. port that should be running at any given point in
  343. time. As I stated earlier, the ideal is to have
  344. one thread active at any given point in time for
  345. every processor in the system. The concurrency value
  346. associated with a port is used by NT to control
  347. how many threads an application has active - if
  348. the number of active threads associated with a port
  349. equals the concurrency value then a thread that
  350. is waiting on the completion port will not be allowed
  351. to run. Instead, it is expected that one of the
  352. active threads will finish processing its current
  353. request and check to see if there's another packet
  354. waiting at the port - if there is then it simply
  355. grabs it and goes off to process it. When this happens
  356. there is no context switch, and the CPUs are utilized
  357. to near their full capacity. <br>
  358. <br>
  359. Figure 1 below shows a high-level picture of completion
  360. port operation. Incoming client requests cause completion
  361. packets to be queued at the port. A number of threads,
  362. up to the concurrency limit for the port, are allowed
  363. by NT to process client requests. Any additional
  364. threads associated with the port are blocked until
  365. the number of active threads drops, as can happen
  366. when an active thread blocks on file I/O. I'll discuss
  367. this further a little later.<br><br>
  368. <img src="./Inside IO Completion Ports_files/comport1.gif" width="529" height="326"><br>
  369. A completion port is created with a call to the
  370. Win32 API <b>CreateIoCompletionPort</b>: <br>
  371. <p><font color="#000000"><b>HANDLE CreateIoCompletionPort(
  372. </b> <br>
  373. <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE</b>
  374. <i>FileHandle</i>,<b><br>
  375. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE</b>
  376. <i>ExistingCompletionPort</i>, <br>
  377. <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD</b>
  378. <i>CompletionKey ,</i><b><br>
  379. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD</b>
  380. <i>NumberOfConcurrentThreads</i><b><br>
  381. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</b>
  382. </font></p>
  383. <br>
  384. To create the port an application passes in a NULL
  385. for the <i>ExistingCompletionPort</i> parameter
  386. and indicates the concurreny value with the <i>NumberOfConcurrentThreads</i>
  387. parameter. If a <i>FileHandle</i> parameter is specified
  388. then the file handle becomes associated with the
  389. port. When an I/O request that has been issued on
  390. the file handle completes a completion packet is
  391. queued to the completion port. To retrieve a completion
  392. packet and possibly block waiting for one to arrive
  393. a thread calls the <b>GetQueuedCompletionStatus</b>
  394. API: <br>
  395. <p><font color="#000000"><b>BOOL GetQueuedCompletionStatus(</b><br>
  396. <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HANDLE</b>
  397. <i>CompletionPort</i>,<b><br>
  398. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPDWORD</b>
  399. <i>lpNumberOfBytesTransferred</i>, <br>
  400. <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPDWORD</b>
  401. <i>CompletionKey ,</i><b><br>
  402. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;LPOVERLAPPED</b>
  403. <i>*lpOverlapped,</i><b><br>
  404. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DWORD</b>
  405. <i>dwMiillisecondTimeout</i><b><br>
  406. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;);</b>
  407. </font></p>
  408. <br>
  409. Threads that block on a completion port become associated
  410. with the port and are woken in LIFO order so that
  411. the thread that blocked most recently is the one
  412. that is given the next packet. Threads that block
  413. for long periods of time can have their stacks swapped
  414. out to disk, so if there are more threads associated
  415. with a port then there is work to process the in-memory
  416. footprints of threads blocked the longest are minimized.
  417. <br>
  418. <br>
  419. A server application will usually receive client
  420. requests via network endpoints that are represented
  421. as file handles. Examples include Winsock2 sockets
  422. or named pipes. As the server creates its communications
  423. endpoints it associates them with a completion port
  424. and its threads wait for incoming requests by calling
  425. <b>GetQueuedCompletionStatus</b> on the port. When
  426. a thread is given a packet from the completion port
  427. it will go off and start processing the request,
  428. becoming an active thread. Many times a thread will
  429. block during its processing, like when it needs
  430. to read or write data to a file on disk, or when
  431. it synchronizes with other threads. Windows NT is
  432. clever enough to detect this and recognize that
  433. the completion port has one less active thread.
  434. Therefore, when a thread becomes inactive because
  435. it blocks, a thread waiting on the completion port
  436. will be woken if there is packet in the queue. <br>
  437. <br>
  438. Microsoft's guidelines are to set the concurrency
  439. value roughly equal to the number of processors
  440. in a system. Note that it is possible for the number
  441. of active threads for a completion port to exceed
  442. the concurrency limit. Consider a case where the
  443. limit is specified as 1. A client request comes
  444. in and a thread is dispatched to process the request,
  445. becoming active. A second requests comes in but
  446. a second thread waiting on the port is not allowed
  447. to proceed because the concurrency limit has been
  448. reached. Then the first thread blocks waiting for
  449. a file I/O so it becomes inactive. The second thread
  450. is then released and while it is still active the
  451. first thread's file I/O is completes, making it
  452. active again. At that point in time, and until one
  453. of the threads blocks, the concurrency value is
  454. 2, which is higher than the limit of 1. Most of
  455. the time the active count will remain at or just
  456. above the concurrency limit.<br>
  457. <br>
  458. The completion port API also makes it possible for
  459. a server application to queue privately defined
  460. completion packets to a completion port using <b>PostQueuedCompletionStatus</b>.
  461. Servers typically use this function to inform its
  462. threads of external events such as the need to shut
  463. down gracefully.</td>
  464. </tr>
  465. <tr>
  466. <td height="40" colspan="3" valign="middle"><span class="sectionheader">Completion Port Internals</span>
  467. </td>
  468. </tr>
  469. <tr>
  470. <td colspan="3" valign="TOP">
  471. <p><font color="#000000">A call to the Win32 API
  472. <b>CreateIoCompletionPort</b> with a NULL completion
  473. port handle results in the execution of the native
  474. API function <b>NtCreateIoCompletion</b>, which
  475. invokes the corresponding kernel-mode system service
  476. of the same name. Internally, completion ports
  477. are based on an undocumented executive synchronization
  478. object called a <i>Queue</i>. Thus, the system
  479. service creates a completion port object and initializes
  480. a queue object in the port's allocated memory
  481. (a pointer to the port also points to the queue
  482. object since the queue is at the start of the
  483. port memory). A queue object has (coincidentally)
  484. a concurrency value that is specified when a thread
  485. initializes one, and in this case the value that
  486. is used is the one that was passed to <b>CreateIoCompletionPort</b>.
  487. <b>KeInitializeQueue</b> is the function that
  488. <b>NtCreateIoCompletion</b> calls to initialize
  489. a port's queue object.</font> <br>
  490. <br>
  491. <font color="#000000">When an application calls
  492. <b>CreateIoCompletionPort</b> to associate a file
  493. handle with a port the Win32 API invokes the native
  494. function <b>NtSetInformationFile</b> with the
  495. file handle as the primary parameter. The information
  496. class that is set is <b>FileCompletionInformation</b>
  497. and the completion port's handle and the <i>CompletionKey</i>
  498. parameter from <b>CreateIoCompletionPort</b> are
  499. the data values. <b>NtSetInformationFile</b> dereferences
  500. the file handle to obtain the file object and
  501. allocates a completion context data structure,
  502. which is defined in NTDDK.H as: </font><br>
  503. </p>
  504. <p><font color="#000000"><b>typedef struct _IO_COMPLETION_CONTEXT
  505. {</b><br>
  506. <b>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PVOID</b>
  507. <i>Port</i>;<b> <br>
  508. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ULONG</b>
  509. <i>Key</i>; <br>
  510. <b>} IO_COMPLETION_CONTEXT, *PIO_COMPLETION_CONTEXT;</b></font></p>
  511. <br>
  512. <font color="#000000">Finally, <b>NtSetInformationFile</b>
  513. sets the <i>CompletionContext</i> field in the file
  514. object to point at the context structure. When an
  515. I/O operation completes on a file object the internal
  516. I/O manager function <b>IopCompleteRequest</b> executes
  517. and, if the I/O was asynchronous, checks to see
  518. if the <i>CompletionContext</i> field in the file
  519. object is non-NULL. If its non-NULL the I/O Manager
  520. allocates a completion packet and queues it to the
  521. completion port by calling <b>KeInsertQueue</b>
  522. with the port as the queue on which to insert the
  523. packet (remember that the completion port object
  524. and queue object are synonymous).</font><br>
  525. <br>
  526. <font color="#000000">When <b>GetQueuedCompletionStatus</b>
  527. is invoked by a server thread, it calls the native
  528. API function <b>NtRemoveIoCompletion</b>, which
  529. transfers control to the <b>NtRemoveIoCompletion</b>
  530. system service. After validating parameters and
  531. translating the completion port handle to a pointer
  532. to the port, <b>NtRemoveIoCompletion</b> calls <b>KeRemoveQueue</b>.
  533. </font><br>
  534. <br>
  535. <font color="#000000">As you can see, <b>KeRemoveQueue</b>
  536. and <b>KeInsertQueue</b> are the engine behind completion
  537. ports and are the functions that determine whether
  538. a thread waiting for an I/O completion packet should
  539. be activated or not. Internally, a queue object
  540. maintains a count of the current number of active
  541. threads and the maximum active threads. If the current
  542. number equals or exceeds the maximum when a thread
  543. calls <b>KeRemoveQueue</b>, the thread will be put
  544. (in LIFO order) onto a list of threads waiting for
  545. a turn to process a completion packet. The list
  546. of threads hangs off the queue object. A thread's
  547. control block data structure has a pointer in it
  548. that references the queue object of a queue that
  549. it is associated with; if the pointer is NULL then
  550. the thread is not associated with a queue. </font><br>
  551. <br>
  552. <font color="#000000">So how does NT keep track
  553. of threads that become inactive because they block
  554. on something other than the completion port? The
  555. answer lies in the queue pointer in a thread's control
  556. block. The scheduler routines that are executed
  557. in response to a thread blocking (<b>KeWaitForSingleObject</b>,
  558. <b>KeDelayExecutionThread</b>, etc.) check the thread's
  559. queue pointer and if its not NULL they will call
  560. <b>KiActivateWaiterQueue</b>, a queue-related function.
  561. <b>KiActivateWaiterQueue</b> decrements the count
  562. of active threads associated with the queue, and
  563. if the result is less than the maximum and there
  564. is at least one completion packet in the queue then
  565. the thread at the front of the queue's thread list
  566. is woken and given the oldest packet. Conversely,
  567. whenever a thread that is associated with a queue
  568. wakes up after blocking the scheduler executes the
  569. function <b>KiUnwaitThread</b>, which increments
  570. the queue's active count. </font><br>
  571. <br>
  572. Finally, the <b>PostQueuedCompletionStatus</b> Win32
  573. API calls upon the native function <b>NtSetIoCompletion</b>.
  574. As with the other native APIs in the completion
  575. port group, this one invokes a system service bearing
  576. the same name, which simply inserts that packet
  577. onto the completion port's queue using <b>KeInsertQueue</b>.</td>
  578. </tr>
  579. <tr>
  580. <td colspan="3" height="40" valign="middle"><span class="sectionheader">Not
  581. Exported</span></td>
  582. </tr>
  583. <tr>
  584. <td valign="TOP" colspan="3" align="left"> Windows
  585. NT's completion port API provides an easy-to-use
  586. and efficient way to maximize a server's performance
  587. by minimizing context switches while obtaining high-degrees
  588. of parallelism. The API is made possible with support
  589. in the I/O Manager, Kernel, and system services.
  590. While the Queue object is exported for use by device
  591. drivers (it is undocumented but its interfaces are
  592. relatively easy to figure out), the completion port
  593. APIs are not. However, if the queue interfaces are
  594. derived it is possible to mimick the completion
  595. port interfaces by simply using the queue routines
  596. and manually associating file objects with queues
  597. by setting the <i>CompletionContext</i> entry.</td>
  598. </tr>
  599. <tr>
  600. <td colspan="3" height="40" valign="middle" align="center">
  601. <a href="https://web.archive.org/web/20101031075704/http://doc.sch130.nsc.ru/www.sysinternals.com/ntw2k/info/comport.shtml#top"><b>Back to Top</b></a> </td>
  602. </tr>
  603. </tbody></table>
  604. </td>
  605. </tr>
  606. </tbody></table>
  607. </td>
  608. </tr>
  609. </tbody></table>
  610. <!-- #EndEditable --></td>
  611. </tr>
  612. </tbody></table>
  613. </td>
  614. </tr>
  615. </tbody></table>
  616. <!-- #EndTemplate -->
  617. <!--
  618. FILE ARCHIVED ON 7:57:04 Oct 31, 2010 AND RETRIEVED FROM THE
  619. INTERNET ARCHIVE ON 12:01:09 Dec 31, 2014.
  620. JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
  621. ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
  622. SECTION 108(a)(3)).
  623. -->
  624. </body></html>