Node.js中的IOCP
来源:互联网 发布:visio2007 网络拓扑图 编辑:程序博客网 时间:2024/05/21 09:10
想必有些人看过朴灵的《深入浅出Node.js(五):初探Node.js的异步I/O实现》http://www.infoq.com/cn/articles/nodejs-asynchronous-io,此篇写的还是很精彩的,特别是对于原理的分析,说明作者在此浸淫已久,不过个人认为其中对于IOCP的理解不是很精准,或者说会引起读者歧义,且看以下原文中描述:
那么在Windows平台下的状况如何呢?而实际上,Windows有一种独有的内核异步IO方案:IOCP。IOCP的思路是真正的异步I/O方案,调 用异步方法,然后等待I/O完成通知。IOCP内部依旧是通过线程实现,不同在于这些线程由系统内核接手管理。IOCP的异步模型与Node.js的异步 调用模型已经十分近似。
实际上,本篇中的流程介绍和图都是比较精准的,只是对于IOCP的理解上有些偏差,这里确实是用到了IOCP,但是并未体现IOCP的异步功能,下面我着重讲下一下IOCP的异步机制,大家可以对比看看就明白了。
先介绍三个重要的IOCP函数以及他们的底层函数,-》代表调用,Nt*、Io*、Ob*等函数是内核函数
1、CreateIoCompletionPort-》NtCreateIoCompletion-》ObCreateObject
伪代码:
if (IOCP不存在)
{
NtCreateIoCompletion // 创建一个
}
else
{
NtSetInformationFile // 将已经存在的IOCP对象与指定的文件对象绑定
}
这是函数有两个功能,一是创建IOCP对象,二是把IOCP对象跟一个文件对象(理论上只要是文件对象就行,windows上很多东西都是文件对象,socket,串口,磁盘等等,并不一定是狭隘的文件)绑定;一般使用的时候要调用两次分别完成以上两个功能,初学者还是很困惑的。
2、GetQueuedCompletionStatus-》NtRemoveIoCompletion-》KeRemoveQueue
这个看文件名大家都应该能明白意思了,就是从内核中一个队列中取东西。
3、PostQueuedCompletionStatus-》IoSetIoCompletion-》KeInsertQueue
也很简单,向内核中一个队列放东西
看到这里,大家会看到原来IOCP就是一个生产者、消费者模型啊,没错,虽然细节远远比这个复杂,但是大致上可以这么理解。
以上三个函数是IOCP最常用的三个函数,但是第三个并不是必须的,在真正异步IO的时候是不需要第三个函数的,是的,没有这个生产者也可以,请接着看:
在内核中,一个文件对象的操作真正完成后,会调用IoCompleteRequest函数。
IoCompleteRequest-》IofCompleteRequest-》IopfCompleteRequest—发起内核APC—》IopCompleteRequest
发起内核APC是为了使IopCompleteRequest工作在调用者的线程空间中,因为这个里面涉及到一些内核数据到用户态数据的复制,所以必须使用跟调用时候相同的线程环境
重点看IopCompleteRequest,以下是代码节选:
if (port && irp->Overlay.AsynchronousParameters.UserApcContext) // 如果port不为空,则。。。(后面条件先忽略,调用CreateIoCompletionPort跟IOCP对象关联过以后,文件对象中的port就不为空了,好像明白点了吧?)
{
//
// If there is a completion context associated w/this I/O operation,
// send the message to the port. Tag completion packet as an Irp.
//
irp->Tail.CompletionKey = key;
irp->Tail.Overlay.PacketType = IopCompletionPacketIrp;
KeInsertQueue( (PKQUEUE) port, // 原来生产者在这里
&irp->Tail.Overlay.ListEntry );
}
从操作系统层面上看,这才是真正地异步(前摄式)模型!!!
所以,Node.js在windows下对文件的操作虽然使用了IOCP,但也不是真正的操作系统层面上的异步模型,大家可以回顾一下朴灵的原著。
看到这里没晕的,应该明白我想讲什么了吧,简单一句话概括吧 ,凡是用户态自己调用PostQueuedCompletionStatus函数的都不是真正的去使用IOCP内核异步特性的!是另有用途的,只是把IOCP看成一个普通的通知队列而已!
- Node.js中的IOCP
- node.js中的require
- Node.js中的模块
- node.js中的models
- Node.js 中的copy
- node.js中的控制台
- Node.js中的路径
- Node,js 中的Promise
- Node.js 中的模块
- Node.js中的模块
- node.js中的文件系统
- node.js中的exports
- node.js中的Stream
- node.js中的path;
- node.js中的response
- Javascript/Node.js 中的 this
- Node.js 中的加密解密
- Node.js中的网络编程
- gevent 安装
- android ListView详解
- ubuntu 镜像 国内地址
- scanf()如何读取一整行(转)
- 离线配置Android开发环境
- Node.js中的IOCP
- js上下滚动代码
- openstack Logical Architecture
- PHP系列之环境搭建
- 在Ubuntu上安装nasm方法
- 黑马程序员_字符编码解码
- Lesson5: 文本编程
- android中添加native服务的权限问题
- xheditor 无法调用?无法显示编辑栏?看这里!