Published on

I/O

Authors
  • avatar
    Name
    noodles
    每个人的花期不同,不必在乎别人比你提前拥有

简介

在看深入浅出node.js这本书的过程中,遇到了几个容易迷糊的概念,例如阻塞I/O、非阻塞I/O、同步、异步。下面主要从I/O模型上对上面的概念进行理解.

基本概念

I/O复用指的是内核具有当进程指定的I/O条件就位的时候通知进程的能力.

I/O模型

  1. 阻塞式I/O 在发生系统调用(I/O)的时候,对应的系统调用直到相应的操作完成或者错误时才返回.(例如在进行网络IO时,需要等待网络数据的就绪完成读取才会完成系统调用的返回)
  2. 非阻塞式I/O 进程可以把一个套接字设置成非阻塞模式.这样当通过该套接字进行相关I/O操作并且需要进程进行等待的时候(例如通过网络读取数据,但是数据并没有就绪的时候), 内核不能将该进程投入睡眠而是返回一个错误标识(轮询)
  3. I/O复用模型 通过select或者poll来对多个相关的描述符进行监听(此时进程阻塞在select和 poll的调用上)),当描述符状态就绪的时候,返回可读条件然后在通过系统调用来完成对应的I/O操作
  4. 信号驱动式I/O模型 通过开启套接字的信号驱动式I/O的功能并且添加相应的信号处理函数,当套接字准备好读取的时候,通过信号通知进程来完成响应的I/O操作.这种模式进程是不被阻塞的
  5. 异步I/O模型 通告系统调用告知内核相应的操作,然后内核在完成相应的操作后会通知进程.这个过程中进程是不被阻塞的.

同步VS异步

同步,异步的概念区分上在于实际上发生系统I/O的时候,是否会阻塞进程.因此上面的前四种模式都是同步I/O,只有最后一种是异步I/O

select

int select(int maxfdpl, fd_set *readset, fd_set *writeset,fd_set *exceptset, const struct timeeval *timeout) 该函数允许进程指示内核等待多个事件中的任何一个发生,在其实一个或者多个事件发生后或者经历了一定时间后唤起进程.该函数的当有描述符就位的时候返回描述符的数目,超时返回0,若出错返回-1,下面对主要的参数进行分析

  • timeout 告知内核等待所指定的描述符中任何一个就绪所花的时间.
    1. 当该timeout结构的代表的值均为0的时候,表示无需等待直接返回
    2. 当设定一定时间的时候,表示当select返回的时候,不能超过该时间
    3. 当设置为空指针的时候,表示select会一直等待直至有响应的描述符就绪
  • readset writeset exceptset 表示让内核检测响应的读,写,异常描述符,当有响应的描述符就位时返回.
  • maxfdpl 指定待测试的描述符的个数

node如何实现高性能的异步I/O

参考自己之前整理的一篇blognode的异步I/O