Linux的五种I/O方式

转载自:https://blog.csdn.net/qq_34018840/article/details/106217337

 

一、背景

在搞清楚Linux的五种I/O方式之前,我们首先需要弄清楚的是同步/异步、以及阻塞/非阻塞的概念,先用一个事例做一个简单的介绍。某一天你去银行办理某个业务,而这个时候有很多人在办理业务,因此你需要等待,现在有下面4种情况:

  1. 你自己主动去排队(同步),然后排队过程中你担心会漏掉你,于是不玩手机不干其他事情只是专心的等待队伍前进(阻塞);
  2. 你自己主动去排队(同步),但是在这个过程中你觉得很无聊,于是开始边玩手机边等(非阻塞);
  3. 银行有一个排号机器可以帮你排号并播放到号提醒(异步),于是你拿了一个号,但是你担心叫号的时候你听不见,于是你还是什么都不敢坐在大厅等着(阻塞);
  4. 银行有一个排号机器可以帮你排号并播放到号提醒(异步),于是你拿了一个号,然后你就在旁边玩手机甚至还出去买了瓶水回来喝(非阻塞);

在这个银行排队事务中,你就是一个处理业务的进程、而银行则是中央处理器CPU。

  • 第一种/第二种情况都是你自己在队伍里等待,由你自己主动同步的去查看银行窗口的状态,区别在于中途干不干别的;
  • 第三种/第四种情况则是银行的机器异步的通知你是否可以办理业务,区别同样在于中途干不干别的;

二、同步/异步、阻塞/非阻塞的简单总结

1、同步/异步

关注的是消息通知机制(即是由你自己主动查看消息,还是由其他人通知你消息),根本区别在于同步是主动等待消息通知,而异步是被动接受消息通知,通过回调、通知、状态等方式来被动获取信息;

  • 所谓同步,就是在发出一个*调用*时,在没有得到结果之前,该*调用*就不返回。但是一旦调用返回,就得到返回值了。换言之,由*调用者*主动等待这个*调用*的结果。
  • 异步则相反,*调用*在发出后,这个调用就直接返回了,所以没有返回结果。换言之,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。

2、阻塞/非阻塞

关注的是程序/线程等待消息通知时的状态(即你在能不能在等待的过程中干其他事情);

3、简单总结

同步的情况下,是由处理消息者自己去等待消息是否被触发;而异步的情况下是由触发机制来通知处理消息者,所以在异步机制中,处理消息者和触发机制之间就需要一个连接的桥梁

三、Linux的五种I/O方式

       1、同步阻塞I/O(银行排队,且不能玩手机干其他事)

  • 程序阻塞直到数据准备好,并将数据从内核复制到用户进程。
  • 优点在于能及时返回数据,无延迟。缺点在于等待需要付出性能代价

       2、同步非阻塞I/O(银行排队,但是可以玩手机,但也需要不断观察自己的排队状态,轮询)

  • 每隔一段时间查询一次的主动轮训方式。将大阻塞分割成N多份阻塞,数据准备好时,拷贝过程依旧处于阻塞状态。
  • 优点在于可以利用部分等待时间,缺点在于响应延迟增大,效率低下,需要在不同操作之间切换

       3、I/O多路复用(银行排队,但增加了一个显示屏显式号码,玩会手机或出去喝口水了回来看看屏幕即可select、poll、epoll,从而避免轮询,显示屏的信息交给内核去做)

  • 多路复用的特点是通过一种机制使得一个进程能同时等待多个I/O文件描述符,基本原理就是select,poll,epoll这个function会不断的轮询I_O状态,任何一个I_O可读写便调用用户进程来处理
  • 当用户进程调用了select、poll、epoll,那么整个进程会被block,由kernel“监视”所有相关的socket,当任何一个socket中的数据准备好了,select、poll、epoll就会返回。这个时候用户进程再调用例如read操作,将数据从kernel拷贝到用户进程
  • IO多路复用是阻塞在select、epoll这样的系统调用之上,而没有阻塞在真正的I/O系统调用如recvfrom之上,实际上可以归为同步阻塞模式

       4、信号驱动I/O

  • 建立SIGIO信号处理程序,进程继续运行并不阻塞。当数据准备好时,进程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

       5、异步非阻塞I/O(银行拿号,可以离开银行去干其他的,等通知到号即可,注册一个回调函数)

  • 用户进行aio_read系统调用之后,无论内核数据是否准备好,都会直接返回给用户进程。等待数据准备好,内核直接复制数据给进程,然后从内核向进程发送一个signal或执行一个基于线程的回调函数来完成这次IO处理过程,告诉它read操作完成了。两个阶段都是非阻塞的。
  • 不会被缓存或缓冲

 

posted @ 2020-09-29 10:18  Ethan_x  阅读(486)  评论(0编辑  收藏  举报