1. 概念理解

     在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式:
同步:
      所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。

     例如普通B/S模式(同步):提交请求->等待服务器处理->处理完毕返回 这个期间客户端浏览器不能干任何事

异步:
      异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。

     例如 ajax请求(异步): 请求通过事件触发->服务器处理(这是浏览器仍然可以作其他事情)->处理完毕

阻塞
     阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。

     有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说,很多时候当前线程还是**的,只是从逻辑上当前函数没有返回而已。 例如,我们在socket中调用recv函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。

非阻塞
      非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。
对象的阻塞模式和阻塞函数调用
      对象是否处于阻塞模式和函数是不是阻塞调用有很强的相关性,但是并不是一一对应的。阻塞对象上可以有非阻塞的调用方式,我们可以通过一定的API去轮询状 态,在适当的时候调用阻塞函数,就可以避免阻塞。而对于非阻塞对象,调用特殊的函数也可以进入阻塞调用。

       函数select就是这样的一个例子。

      1. 同步,就是我调用一个功能,该功能没有结束前,我死等结果。
      2. 异步,就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(回调通知)
      3. 阻塞,就是调用我(函数),我(函数)没有接收完数据或者没有得到结果之前,我不会返回。
      4. 非阻塞,就是调用我(函数),我(函数)立即返回,通过select通知调用者

     其中的区别如下:

     同步IO和异步IO的区别就在于:数据拷贝的时候进程是否阻塞!

     阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否立即返回!

2、五种I/O模型

        IO的本质是socket的读取,数据先拷贝到内核的缓冲区中,然后拷贝到应用程序的地址空间(进程)

2.1 同步阻塞 I/O

(1)过程

Linux 五种I/O模型

分析:从上图可以看到在整个过程中,当用户进程进行系统调用时,内核就开始了I/O的第一个阶段,准备数据到缓冲区中,当数据都准备完成后,则将数据从内核缓冲区中拷贝到用户进程的内存中,这时用户进程才解除block的状态重新运行。

(2)实例

  • Blocking I/O是在I/O执行的两个阶段都被block了。

  • 例如:我要去饭堂吃饭,这时饭堂的人很多,我就得排队买饭,排队的时间被浪费了,

(3)特点

  • 能够及时返回数据,无延迟
  • 性能下降

2.2 同步非阻塞 I/O

(1)过程

Linux 五种I/O模型

分析:从上图可以看到在I/O执行的两个阶段中,用户进程只有在第二个阶段被阻塞了,而第一个阶段没有阻塞,但是在第一个阶段中,用户进程需要盲等,不停的去轮询内核,看数据是否准备好了。

(2)实例

  • nonblocking I/O是在I/O执行的第二个阶段(数据复制)被block了,而第一个阶段并未阻塞(数据准备)。
  • 例如:我要去饭堂吃饭,这时饭堂的人很多,一般来说我需要排队买饭,但我们饭堂的管理最近变的比较人性化,你点完饭后,会给你一个号码,但饭堂噪声很大,我不得不频繁的询问我的饭是否做好了,但是我可以利用之前排队的时间去买瓶饮料喝!

(3)特点

  • 拷贝数据的整个过程,进程仍然是阻塞的
  • 需要不断询问数据是否准备好了
  • 能够在等待任务完成的过程中处理其他事件
  • 由于需要轮询,所以延迟会增加

2.3  IO多路复用

(1)过程

Linux 五种I/O模型

分析:从上图可以看到在I/O复用模型中,由于同步非阻塞方式需要不断主动轮询,轮询占据了很大一部分过程,轮询会消耗大量的CPU时间,而 “后台” 可能有多个任务在同时进行,

       如果循环查询多个任务的完成状态,只要有任何一个任务完成,就去处理它。轮询不是进程的用户态。这时 “IO 多路复用”就出现了。即UNIX/Linux 的 select、poll、epoll,

       IO多路复用是阻塞在select,epoll这样的系统调用之上,而没有阻塞在真正的I/O系统调用如recvfrom之上。

从整个IO过程来看,他们都是顺序执行的,因此可以归为同步模型(synchronous)。都是进程主动等待且向内核检查状态

(2)实例

  • 多路复用I/O执行的两个阶段用户进程都是阻塞的,但是两个阶段是独立的。
  • 例如:我要去饭堂吃饭,这时饭堂的人很多,点完饭后,我会拿到一个号码,以前我不得不频繁的询问我的饭做好了没,但是最近饭堂安装了一块电子显示屏,你的饭好了就会在屏上显示出来,这时候我就不用频繁的去问了,直接看电子显示屏就醒了,然后我就可以利用这个时间去超市买个牙膏了。

(3)特点

  • select/poll调用后会阻塞进程,但可以同时阻塞多个IO事件操作(文件描述符),有数据可读或可写(就绪事件),就通知用户进程。
  • select 需要每次注册事件(轮询),而epoll不需要每次注册事件(没有轮询,回调函数)
  • IO多路复用阻塞在select/epoll的系统调用之上的,而真正的IO系统调用如recvfrom是非阻塞的。

(4)适用场景

  • 服务器需要同时处理多个处于监听状态或连接状态的套接字
  • 服务器需要处理多种网络协议的套接字

2.4 信号驱动I/O

(1)过程

Linux 五种I/O模型

分析:从上图可以看出,只有在I/O执行的第二阶段阻塞了用户进程,而在第一阶段是没有阻塞的。该模型在I/O执行的第一阶段,当数据准备完成之后,会主动的通知用户进程数据已经准备完成,即对用户进程做一个回调。该通知分为两种,一为水平触发,即如果用户进程不响应则会一直发送通知,二为边缘触发,即只通知一次。

(2)实例

  • 信号驱动I/O执行的第一阶段不阻塞,而第二阶段是阻塞的。
  • 例如:我要去饭堂吃饭,这时饭堂的人很多,点完饭后,我会拿到一个号码,虽然说饭堂安装了一块电子显示屏,但我在玩手机时还不得不抬头看一下显示屏上有我的号码没,最近饭堂买了一个大喇叭,哪个号码好了,卖饭的阿姨就会用喊,虽说饭堂有点吵,但这个声音还是可以听到的,这样我就可以专心的低头玩手机了。

2.5 异步 I/O

(1)过程

Linux 五种I/O模型

分析:从上图可以看出,在该模型中,当用户进程发起系统调用后,立刻就可以开始去做其它的事情,然后直到I/O执行的两个阶段都完成之后,内核会给用户进程发送通知,告诉用户进程操作已经完成了。

(2)实例

  • 异步 I/O执行的两个阶段都不会阻塞。
  • 例如:我要去饭堂吃饭,估计这会饭堂的人很多,但最近我们饭堂可以叫外卖了,这样就省事多了,我直接打个电话,订份饭送到我们宿舍,而我现在就可以利用原来去饭堂路上和等饭的时间写博客了。

(3)特点

  • 读写操作由内核完成,完成后内核将数据放到指定的缓冲区,通知应用程序来取。
     

3、I/O模型总结

 

Linux 五种I/O模型

 

相关文章:

  • 2021-10-18
  • 2021-10-23
  • 2021-05-26
  • 2021-08-05
  • 2021-09-11
  • 2021-07-01
  • 2021-09-09
  • 2021-10-03
猜你喜欢
  • 2021-12-05
  • 2021-09-28
  • 2021-08-30
  • 2021-08-22
  • 2021-12-19
相关资源
相似解决方案