通常来讲,一个输入操做一般包括两个阶段:
是否同步的判断依据是: 是否 针对的 整个过程,即2个阶段,是否有阻塞
是否阻塞的判断依据是: 按 程序等待消息通知时的状态角度来讲的,,即针对第一阶段来讲
例子很形象:
Linux 认为
一、用系统调用 read 从 socket 里读取 一段数据
二、用系统调用read 从 一个磁盘文件读取一段数据到 内核
分 网路IO 和 磁盘文件 IO。 网络IO 才作 BLOCK。
一个解释是,所谓“Block”是指操做系统能够预见这个Block会发生才会主动Block。
例如当读取TCP链接的数据时,若是发现Socket buffer里没有数据就能够肯定定对方尚未发过来,因而Block;
而对于普通磁盘文件的读写,也许磁盘运做期间会抖动,会短暂暂停,可是操做系统没法预见这种状况,只能视做不会Block,照样执行。
一、Unix 5中 IO模型
- 阻塞式I/O;
- 非阻塞式I/O;
- I/O复用(select,poll,epoll...);
- 信号驱动式I/O(SIGIO);
- 异步I/O(POSIX的aio_系列函数);
一、阻塞式I/O;
同步阻塞IO模型是最经常使用的一个模型。 linux中 默认状况下全部的socket都是 blocing,
在这个模型中,用户空间的应用程序执行一个系统调用 recvform, 这会致使应用程序阻塞,睡没也不干,直到数据准备好,等待 kenel准备好 从 网络上姐都到的 数据包 + 等待收到的报文 被 从 kernel 赋值到bug中,recvform 方法才会返回,最后 进程在处理数据。
2 非阻塞式I/O
非阻塞IO, 对一个非阻塞描述符 循环调用 recvfrom,持续的轮询(polling),以查看某个操做是否就绪。与阻塞IO不同,非阻塞将大的 整片时间的阻塞 分红 N多的小的阻塞, 全部 进程 不断的有机会 被 CPU 光顾。
非阻塞的 recvfrom 系统调用后,进程并无被阻塞,内核立刻返回给进程,若是数据没有准备好,会返回 error。 进程在返回以后,能够干其余事情,而后在发起recvfrom 系统调用。如此循环的仅从 recvfrom 系统调用,检查内核数据,直到数据准备好,在拷贝数据到进程。拷贝数据整个过程,进程仍然是属于 阻塞的状态。
3.I/O复用
IO multiplexing 就是咱们说的 select,poll,epoll。(多路复用,由于它 能够同时监听多个 fd, 减小了为每一个须要监听的fd 开启线程的开销)
select 调用是内核级别的,能够等待多个socket,能实现同时多多个 IO端口进行监听, 当其中任何一个socket 的数据准备好了,就能返回进行 可读(写),而后进程在进行 recvform 系统调用,将数据由 内核 拷贝到用户进程,这个过程是阻塞的。
IO复用模型会用到 select,poll,epoll函数,这几个函数也会使进程阻塞,可是和阻塞IO所不一样的, 这几个函数能够同时阻塞多个 IO操做,多个写操做的 IP函数 进行检测,直到有数据 可读或可写 时(不是等到socket数据所有到达再处理, 而是有了一部分数据就会调用用户进程来处理),才进行真正地调用 IO操做函数。
IO复用有人把其成为同步非阻塞的,也有称为同步阻塞。其实这个是否阻塞还须要看第一个阶段,第一个阶段有的阻塞,有的不阻塞。主要也是阻塞在select阶段,属于用户主动等待阶段,咱们且规范为阻塞状态,因此,把IO多路复用归为同步阻塞模式。
4.信号驱动式I/O
信号驱动式I/O:首先咱们容许Socket进行信号驱动IO,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,能够在信号处理函数中调用I/O操做函数处理数据。
也就是说第一个阶段,彻底是非阻塞的,等数据到达会给一个信号通知,第二个阶段recvfrom仍是阻塞过程,和之上无差别。
5.异步I/O
异步IO不是顺序执行,用户进程进行aio_read系统调用以后,不管内核数据是否准备好,都会直接返回给用户进程,而后用户态进程能够去作别的事情。等到socket数据准备好了,内核直接复制数据给进程,而后从内核向进程发送通知。IO两个阶段,进程都是非阻塞的。
总结
二、JAVA IO
Unix中的五种I/O模型,除信号驱动I/O外,Java对其它四种I/O模型都有所支持。其中Java最先提供的
blocking I/O便是同步阻塞I/O,
而NIO便是同步非阻塞I/O,
同时经过NIO实现的Reactor模式便是I/O复用模型的实现,
经过AIO实现的Proactor模式便是异步I/O模型的实现。