目录

  • IO模型
  • 阻塞与非阻塞
  • 同步与异步
  • 阻塞IO
  • 非阻塞IO
  • 信号驱动IO
  • 多路复用IO
  • 异步IO



IO模型

根据各自的特性不同,IO模型被分为阻塞IO、非阻塞IO、信号驱动IO、异步IO、多路复用IO五类。
最主要的两个区别就是阻塞与非阻塞,同步与异步

阻塞与非阻塞

阻塞与非阻塞最主要的区别就是程序在等待调用结果时的状态。

阻塞:为了完成一个功能发起调用,如果不具备完成功能的条件,则调用会一直等待
非阻塞:为了完成一个功能发起调用,如果不具备完成功能的条件,则立即报错返回

同步与异步

同步与异步最主要的区别就是功能完成的流程是否是顺序化的,且完成的是自身还是系统。

同步:功能完成的流程是顺序化的,并且功能由自身完成。
异步:功能完成的流程是不确定的,并且功能由系统完成。


阻塞IO

发起IO调用,如果不具备IO条件,则一直等待直到条件就绪。


优点流程以及代码实现都非常简单,任务顺序操作

缺点任务处理效率较低,无法充分利用资源


非阻塞IO

发起一个IO调用,如果不具备IO条件,则立即报错返回,继续执行其他命令。通过一个循环来不断发起IO请求,直到条件就绪。


优点:与阻塞IO相比较来说,利用了等待的时间去做了其他的事情,对资源的利用更加充分

缺点:与阻塞IO对比,IO调用需要循环发起,流程更加复杂。并且如果IO条件就绪了,也要等待上一轮循环结束后进入当前循环,才能进行处理,这就导致了IO不够实时

非阻塞IO可以通过fcntl函数设置描述符状态来实现
例如:

void SetNoBlock(int fd) 
{
	int flag = fcntl(fd, F_GETFL, 0);
	
	flag |= O_NONBLOCK;
	fcntl(fd, F_SETFL, flag);
}

信号驱动IO

自定义一个IO就绪的信号,当IO就绪时就发出这个信号。在没有收到信号时,可以继续处理其他事情,一旦收到信号,就会中断当前操作,来优先处理IO事件。

java阻塞io和非阻塞io区别 阻塞io与非阻塞io的区别_java阻塞io和非阻塞io区别


优点:相较于非阻塞IO,因为信号到来后就直接强行中断进行处理,更加实时。并且在没收到信号的时候可以执行其他工作,资源利用更加充分

缺点:因为需要自定义信号,又要有主控流程也要有信号处理流程,并且还需要考虑信号是否可靠导致的事件丢失情况,流程会更加的复杂


多路复用IO

用于对大量的IO事件进行监控,能够让用户只针对就绪了指定事件(可读、可写、异常) 的IO进行IO操作。只针对就绪的描述符进行操作,避免了阻塞,并且提高了效率。

在Linux下,操作系统提供了三种模型:select模型、poll模型、epoll模型。这三种模型的具体使用以及细节会放到下一篇博客中

java阻塞io和非阻塞io区别 阻塞io与非阻塞io的区别_网络编程_02


根据不同的模型具体的优缺点也不一样。


异步IO

IO处理的顺序不确定,整个IO的过程(等待 + 数据拷贝)由操作系统来完成而并非用户。

java阻塞io和非阻塞io区别 阻塞io与非阻塞io的区别_操作系统_03


流程

  1. 自定义一个IO完成信号
  2. 发起异步调用后返回,此时用户可以继续处理其他事情
  3. 系统进行IO事件的等待以及数据拷贝
  4. IO完成后通过信号通知进程IO

优点:对资源的利用最为充分, 以最高的效率进行任务的处理
缺点:资源消耗较高, 流程最为复杂

上面的五种IO模型,从前往后处理的效率逐渐增加,对资源的利用也增加充分,但是流程也越来越复杂。