Hardog's blog

trace forever

Group: 572218159
Email: 1273203953@qq.com
Location: hangzhou·zhejiang
GitHub: https://github.com/hardog

提示 本文所讨论的相关知识都是围绕Nodejs(libuv@1.9.2)展开!

uv架构

uv-arch

从上图中可以看到libuv的架构大体分为两层, 上层包含网络IO, 磁盘IO以及一些用户代码. 下层包含uv__io_t这个主要代表针对类*nix系统封装的底层网络IO操作, IOCP代表封装的Windows平台的底层网络IO操作, 而Thread Pool主要是使得操作的磁盘IO可以通过异步的方式进行操作, 即磁盘IO的异步操作主要是通过多线程的方式来实现的.

handle&request

libuv主要提供了两种抽象来处理事件循环过程中的操作, 一种是生命周期比较长的对象即handles, 另一种就是存活时间较短的对象即requests, 当然该抽象也可以针对handles进行操作.

关于uv迭代过程分析

以下分析为浅显理解, 待后续完善(TODO):

loop_iteration.png

首先, 每一个事件队列对应着一个单独的线程, 每一轮事件队列循环执行的是while语句.

关于网络IO

所有的网络IO使用的都是非阻塞的sockets来进行处理, 并且针对不同的平台封装了不同的处理机制, 具体来说就是Linux系统上使用epoll机制, OSX和其他的BSDs系统使用kqueue机制, SunOS系统使用event ports机制, 而Windows平台则采用其独特的IOCP机制. 当前针对异步网络IO处理的机制还包括其他一些, 例如read, select, poll等, 以下为其差别:

其中select, poll, epoll以及kqueue有一个词描述它们:IO复用(IO multiplexing), 简单解释下该词, 复用的意思是指开始一个线程只能处理一个流的操作, 复用之后一个线程可以同时处理多个流, 关于什么是流可以参考这边知乎问答知乎问答, 关于epoll/kqueue.

关于阻塞非阻塞以及同步异步之间的差别如下:

关于磁盘IO

在现有操作系统中还没有很好的方式能够处理异步的磁盘IO的(这里有篇文章讨论为什么采用多线程方式处理磁盘IO以及多线程处理方式与特定于平台的处理方式之间的利弊), 因此在Nodejs中是采用线程池, 开启多个线程的方式来进行异步磁盘IO处理的, 目前在线程池中主要处理三类操作:

参考链接

关于使用多线程实现异步磁盘IO
Unix 网络编程(英文版)
关于异步IO
同步异步/阻塞非阻塞IBM
知乎问答, 关于阻塞非阻塞/同步异步
知乎问答, 关于epoll/kqueue
epoll 维基百科
kqueue 维基百科
kqueue 实现参考
IOCP 维基百科
IOCP IBM