多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
组装好请求对象、送入I/O线程池等待执行,实际上完成了异步I/O的第一部分,回调通知是第二部分。 线程池中的I/O操作调用完毕之后,会将获取的结果储存在req->result属性上,然后调用PostQueuedCompletionStatus()通知IOCP,告知当前对象操作已经完成: ~~~ PostQueuedCompletionStatus((loop)->iocp, 0, 0, &((req)->overlapped)) ~~~ PostQueuedCompletionStatus()方法的作用是向IOCP提交执行状态,并将线程归还线程池。通过PostQueuedCompletionStatus()方法提交的状态,可以通过GetQueuedCompletionStatus()提取。 在这个过程中,我们其实还动用了事件循环的I/O观察者。在每次Tick的执行中,它会调用IOCP相关的GetQueuedCompletionStatus()方法检查线程池中是否有执行完的请求,如果存在,会将请求对象加入到I/O观察者的队列中,然后将其当作事件处理。 I/O观察者回调函数的行为就是取出请求对象的result属性作为参数,取出oncomplete_sym属性作为方法,然后调用执行,以此达到调用JavaScript中传入的回调函数的目的。 至此,整个异步I/O的流程完全结束,如图: ![](https://box.kancloud.cn/2016-08-28_57c1cec2c7471.png) 事件循环、观察者、请求对象、I/O线程池这4者共同构成了Node异步I/O模型的基本要素。 Windows下主要通过IOCP来向系统内核发送I/O调用和从内核获取已完成的I/O操作,配以事件循环,以此完成异步I/O的过程。在Linux下通过epoll实现了这个过程,FreeBSD下通过kqueue实现,Solaris下通过Event ports实现。不同的是线程池在Windows下由内核(IOCP)直接提供,`*nix`系列下由libuv自行实现。