美文网首页
unix网络编程的5种I/O模型

unix网络编程的5种I/O模型

作者: 零一间 | 来源:发表于2020-05-27 20:39 被阅读0次

同步/异步、阻塞/非阻塞

同步

发出一个功能调用时,在没有得到结果之前,该调用就不返回,也就是必须一件一件事做,等前一件做完了才能做下一件事。

异步

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

通知调用者的三种方式:

  • 状态——监听被调用者的状态(轮询),调用者需要每隔一定时间检查一次,效率会很低;
  • 通知——当被调用者执行完成后,发出通知告知调用者,无需消耗太多性能
  • 回调——当被调用者执行完成后,会调用调用者提供的回调函数

阻塞

调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,OS不会给线程分配时间片,即线程暂停运行),调用结果返回后线程进入就绪态

非阻塞

调用结果返回之前,该函数不会阻塞当前线程,而会立刻返回

同步和异步的区别

请求发出后,是否需要等待结果,才能继续执行其他操作

在网络IO模型中,数据拷贝时进程阻塞是同步,反之则是是异步

阻塞和同步的区别

同步调用在结果返回之前,线程并没有进入挂起状态,OS还会给它分配占用CPU的时间片;

阻塞调用在结果返回之前,线程处于挂起状态,OS不会再为其分配占用CPU的时间片,直到结果返回后,线程进入就绪状态在可能继续运行

阻塞和非阻塞的区别

在网络IO模型中,应用程序的调用立即返回是非阻塞,反之则是阻塞

同步/异步和阻塞/非阻塞的区别

在网络编程中,阻塞和非阻塞发生在第一阶段(准备数据阶段);同步和异步发生在第二阶段(准备好的数据从内核缓冲区拷贝到用户进程缓冲区阶段)

用户空间和内核空间

在Linux/Unix中,对于一次读取IO的操作,数据并不会直接拷贝到应用程序的缓冲区(用户空间),它首先会被拷贝到操作系统内核的缓冲区(内核空间)中,然后才会从操作系统内核的缓冲区拷贝到应用程序的缓冲区

可以看做是两个过程:

  1. Waiting for the data to be ready(等待数据到达内核缓冲区);
  2. Copying the data from the kernel to the process(从内核缓冲区拷贝数据到应用程序缓冲区)

五种I/O模型

  1. 阻塞I/O

  2. 非阻塞I/O

  3. I/O多路复用

  4. 信号驱动I/O

  5. 异步I/O

其中前四种是同步I/O模型,只有第五种是异步的。

1 阻塞I/O模型

image

当用户进程调用了recvfrom这个系统调用,kernel就开始了IO的第一个阶段:准备数据,对于network IO来说,一般数据在一开始还没有到达,kernel会等待足够的数据到来,而在用户进程这边,整个进程会被阻塞挂起,当kernel等到数据准备好,它就会将数据从内核缓冲区拷贝到用户进程缓冲区,然后kernel返回结果,用户进程才进入就绪状态,重新运行起来。

作为一个网络的服务器,阻塞式的等待会浪费大量的资源和时间,当服务器调用函数sendto给远端的一个客户端发送数据时,这时候不做其他的事情那么往后的动作都堵塞在后面,这样显然是不合适的,解决这种问题的方法往往是创建一个进程或者线程去解决这件事。

阻塞式的I/O的好处就是它非常的稳定,他能保证连接保证接受和发送数据的确定性,这是大多大的互联网公司使用多线程的原因,并且使用线程池也会大大增加线程开启的效率。

2 非阻塞I/O模型

image

当用户进程发出recvfrom操作时,如果kernel中的数据还没有准备好,那么它并不会阻塞用户进程,而是立刻返回,从用户进程角度讲 ,它发起一个recvfrom操作后,并不需要等待,而是马上就得到了一个结果,用户进程通过结果判断数据是否准备好,如果没有准备好过段时间再次发送recvfrom操作,一旦kernel中的数据准备好了,并且又再次收到了用户进程的recvfrom调用操作,马上将数据从内核缓冲区拷贝到了用户进程缓冲区

非阻塞方式下,当前执行流以睡眠的方式来等待请求或者数据的到来,而采用轮询的方式,每隔一个时间段便返回一次,如果有数据到来则返回,如果没有,则返回一个错误码WSAEWOULDBLOCK,需要不断的用循环来等待数据的成功返回,这个过程往往会占用大量的CPU。

非阻塞的缺点,一次只能等待一个事件的到来。

3 阻塞的I/O复用模型(select,poll,epoll...)

image
  • select,poll,epoll就是IO多路复用模型,其特点就在于单个系统调用可以同时处理多个网络连接的IO,它的基本原理就是select/poll/epoll这个function会不断的轮询所负责的所有socket,当某个socket有数据到达了,就通知用户进程
  • 当用户进程调用了select/poll/epoll,整个进程会被阻塞,而同时,kernel会“监视”所有select/poll/epoll负责的socket,当任何一个socket中的数据准备好了,select/poll/epoll就会返回。这个时候用户进程再调用recvfrom操作,将数据从内核缓冲区拷贝到用户进程缓冲区

缺点就是,无论是上面所述的哪种函数,每次发送或者接受一个数据都会进入两次内核与用户的转换。

4 信号驱动的I/O复用模型(SIGIO)

image

用的很少,就不做讲解了。

5 异步I/O模型(POSIX的aio_系列函数)

image

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

6 5种模型的比较

image

参考:
https://blog.51cto.com/wpfbcr/1783543
https://zhuanlan.zhihu.com/p/121826927

相关文章

网友评论

      本文标题:unix网络编程的5种I/O模型

      本文链接:https://www.haomeiwen.com/subject/ynugahtx.html