** 操作系统将所有的输入输出设备抽象为文件, 在进行I/O操作时实际上要先获取文件描述符, 然后根据文件描述符进行操作。**
** 同步IO 是指:**
** 发起请求--> 获取文件描述符 --> 读取文件 --> 读取文件结束并返回 **
** 异步IO 是指: **
** 发起请求 --> 获取文件描述符 --> 返回 **
**那么, 如何知道文件是否读取完成?这时要使用 轮询, 即重复调用I/O 来确认是否完成 **
轮询
- read, 重复检查I/O的状态
- select, 使用1024 长度的数组来存储状态, 通过判断文件描述符上的事件状态
- poll, 将select 的数组换位链表。
- epoll, Linux 下效率最高的I/O机制,检测不到I/O事件时会进行休眠,直至有事件发生将其唤醒不浪费CPU
- iocp , windows 下的 I/O 机制,也实现了异步。
**Node 的异步IO 实际上是用 主线程 +线程池/IOCP 的方式模拟的异步IO, 而且在主线程上仍然是“同步” **
Event Loop 事件循环如下所示:
- 检查 Event queue 即事件队列中是否还有事件
- 有事件则取出一个交给主线程去处理。
- 主线程将I/O操作交给线程池中的的某个线程处理,然后接着处理下一个事件。
- 调用线程处理事件, 如果处理事件完成,将完成的结果放回到 Event queue 中。
Node为了进行跨平台,提供了抽象封装层 --> libuv 进行平台的判断, 在Node 编译的时候会进行判断,选择性的编译 *nix 或者 Windows 文件。 在 windows 下的异步是调用了 IOCP 来实现, 在*nix 下是使用了 Node 自带的线程池实现。
- V8 引擎负责解析js 代码
- 解析完成的代码调用Node 的API
- libuv 负责处理 事件循环和调用IOCP或者自己的线程池处理I/O 操作, 将结果返回给 V8 引擎
- V8 负责将结果返回给用户。
参考链接:
http://www.ruanyifeng.com/blog/2014/10/event-loop.html
https://vimeo.com/96425312,
朴灵 《深入简出NodeJs》