回顾IO模型

Posted 了解这个有多难

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了回顾IO模型相关的知识,希望对你有一定的参考价值。

Unix系统哲学中提出了5种IO模型

  1. 阻塞IO

  2. 非阻塞IO

  3. 多路复用IO

  4. 信号驱动IO

  5. 异步IO

1,阻塞IO

这是传统IO模型,即在读写数据过程中会发生成阻塞现象。

典型的阻塞IO模型的例子为:data = socket.read()

如果数据没有就绪,就会一直阻塞在read方法处,线程处于阻状态,此时交出CPU,直到read返回,内核会将数据拷贝到用户线程用户线程才解除block状态


2,非阻塞IO模型

当用户线程发起一个read操作后,并不需要等待,而是马上就得到了一个结果。这个结果可能是err,户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,直到取到数据,可以看出这种效率不是很高。

典型的非阻塞IO模型一般如下:

while(true){
  data = socket.read();
  if(data!= error){
      处理数据
      break;
  }
}


3、多路复用IO模型

     多路复用IO模型是目前使用得比较多的模型。在多路复用IO模型中,只需要一个用户线程就可以管理多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作,所以它大大减少了资源占用。因此,多路复用IO比较适合连接数比较多的情况。注意,这里轮询每个socket状态是内核在进行的而并非像非阻塞IO中那样是通过用户线程不断地询问socket状态

使用多路复用IO的有著名的redis,nginx等。nginx 采用的是多进程(单线程) + io多路复用(epoll)模型 实现高并发


4、信号驱动IO模型

     在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用IO读写操作来进行实际的IO请求操作。


5、异步IO模型

     异步IO模型才是最理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它收到一个asynchronous read之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要知道实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。

  也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用IO函数进行具体的读写。这点是和信号驱动模型有所不同的,在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用iO函数进行实际的读写操作。

注意:异步IO是需要操作系统的底层支持


前面四种IO模型实际上都属于同步IO,只有最后一种是真正的异步IO,因为无论是多路复用IO还是信号驱动模型,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。


⬇︎⬇︎⬇︎后续更新,长按关注⬇︎⬇︎⬇︎










以上是关于回顾IO模型的主要内容,如果未能解决你的问题,请参考以下文章

Linux的I/O模式事件驱动编程模型

IO模型

IO模型

IO模型

IO模型

IO模型