IO

在这里插入图片描述

    IO (Input/Output,输入/输出)即数据的读取(接收)或写入(发送)操作,
    通常用户进程中的一个完整IO分为两阶段:
    用户进程空间<-->内核空间、内核空间<-->设备空间(磁盘、网络等)。
    IO有内存IO、网络IO和磁盘IO三种,通常我们说的IO指的是后两者。

什么是内核态,用户态

在这里插入图片描述

  • 用户态:也称为用户空间,即上层应用程序的活动空间,应用程序的执行必须依赖于内核提供的资源
  • 用户态:也称为用户空间,即上层应用程序的活动空间,应用程序的执行必须依赖于内核提供的资源
  • 注:用户态可以通过系统调用切换到内核态,这是主动进入到内核态。此外在出现异常或者外围设备的中断也会进入到内核态,不过是被动响应的

先说结论:各种IO模型其实是根据它在上述两个阶段的不同表现(用户进程或者线程是否阻塞)来区分的!!!
在第一个阶段用户进程是否阻塞用来区分阻塞/非阻塞,在第二个阶段用户是否阻塞用来区分同步/异步!!!

阻塞IO

在这里插入图片描述
当用户进程发起系统调用recvfrom时,在第一阶段,内核首先会等待****数据准备就绪,这个过程中用户进程是阻塞的;在第二阶段,当数据准备就绪之后,数据会从内核空间拷贝到用户空间(应用程序空间),这个过程中用户进程同样是阻塞的,直到数据拷贝完成才恢复。

所以,阻塞IO在两个阶段都是阻塞的!!

非阻塞IO

在这里插入图片描述
非阻塞IO和阻塞IO相似,区别在于第一阶段,在等待数据准备就绪的过程中,用户进程不会阻塞,而是在数据没有准备就绪的时候得到一个error返回,这是用户进程就知道数据还没有准备好,然后就可以继续发起recvfrom操作直到数据准备就绪

在第二阶段,数据从内核空间向用户空间拷贝时,非阻塞IO用户进程同样是阻塞的。

IO多路复用

在这里插入图片描述

1.多个的进程的IO可以注册到一个复用器(select)上,然后用一个进程调用该select, select会监听所有注册进来的IO;
2. 如果select没有监听的IO在内核缓冲区都没有可读数据,select调用进程会被阻塞;而当任一IO在内核缓冲区中有可数据时,select调用就会返回;
3.而后select调用进程可以自己或通知另外的进程(注册进程)来再次发起读取IO,读取内核中准备好的数据。
4. 可以看到,多个进程注册IO后,只有另一个select调用进程被阻塞。

IO多路复用实际上是通过select/epoll等函数轮询多个socket,当用户进程调用了select函数,整个用户进程就会被阻塞,直到收到数据准备就绪的返回

后续的操作和非阻塞IO是类似的,由于在recvfrom系统调用之前,需要的数据就已经准备就绪了,所以第一个阶段是非阻塞的;第二个阶段同样还是阻塞的

所以IO多路复用整个过程中,用户进程都是阻塞的~
简单理解:就是对于(应用层)来看,进程/线程还是阻塞的。只是对应内核来说阻塞的线程只有复用器 select

1、典型应用:select、poll、epoll三种方案,nginx都可以选择使用这个方案;
2、特点:

  • 专一进程解决多个进程IO的阻塞问题,性能好;Reactor模式;
  • 实现、开发应用难度较大;
  • 适用高并发服务应用开发:一个进程(线程)响应多个请求;

异步IO

异步IO实际上是用户进程发起read操作之后,就会立刻收到一个返回,所以用户进程就可以去完成其他的工作,而不需要阻塞;直到数据准备就绪并且完成了从内核空间向用户空间拷贝的工作,这时用户进程会收到一个通知,告诉他read操作已完成

整个过程中用户进程不会被阻塞

总结

所以实际上阻塞IO和非阻塞IO都是同步IO,用到了特殊的异步函数才是异步IO