网络编程之五种I/O模型

Posted

tags:

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



一.概述:

在网络编程中,阻塞、非阻塞、同步、异步经常被提到,下面我先谈以下我所理解的在I/O中的阻塞、非阻塞、同步、异步。

五种I/O模型分别是阻塞式I/O,非阻塞式I/O,信号驱动,I/O复用(这四种是同步I/O),异步I/O。

我来举一个例子来解释这五种I/O模型:

有A,B,C,D,E五个人在钓鱼:
A用的是最老式的鱼竿,所以呢,得一直守着,等到鱼上钩了再拉杆。(阻塞式I/O)


B呢,它的鱼竿比较新,不怕鱼上钩后把鱼竿拽走,所以他一边看手机,一边时不时看一下鱼竿是否有鱼上钩,有的话就迅速拉鱼竿。(非阻塞式I/O)


C的鱼竿有个功能,能够显示是否有鱼上钩,所以呢,B就和旁边的MM聊天,隔会再看看有没有鱼上钩,有的话就迅速拉杆。(信号驱动)


D用的鱼竿和C差不多,但他想了一个好办法,就是同时放好几根鱼竿,然后守在旁边,一旦有显示说鱼上钩了,它就将对应的鱼竿拉起来;(I/O复用)


E是个有钱人(有钱人了不起啊),干脆雇了一个人帮他钓鱼,一旦那个人把鱼钓上来了,就给E发个短信。(异步I/O)


下面我先谈以下我所理解的在I/O中的阻塞、非阻塞、同步、异步。



二.I/O操作过程:

首先,进行I/O操作涉及到了硬件,所以就会和操作系统打交道。(从网卡这两个读取/发送数据到网络中是操作系统做的)所以,先解释以下我理解的I/O过程(总的来说是   等数据 和  数据搬迁   这两个过程)


首先,通过系统给我们的API函数调用I/O操作(此时在用户态),这个函数先等待I/O缓存中有数据,操作系统会监测I/O缓存(此时在内核态),当I/O缓存中接收到数据时,操作系统先通知这个函数调用(进入用户态),然后这个函数的实现中会调用一些已经包装好的函数,“ 这些 ”函数会把数据从内核中拷贝到用户缓存区(先到内核态,再到用户态),然后这个函数就会返回。

具体如下图:

技术分享



三.I/O操作中的阻塞、非阻塞、同步、异步:

(1).同步:同步就是在一个功能调用时,在这个调用没有得到结果之前,这个调用不会返回。(在I/O操作中,如调用read函数,这个函数会被阻塞在read函数调用处,但内核一直在做与read相关的事情,也就是这个函数是激活的(会占用cpu),只是从表面上看函数还没有返回而已)。


(2).阻塞:阻塞调用就是调用一个函数,这个调用结果没有得到结果之前,执行这个函数的线程会被挂起(这个状态下,cpu不会给该函数分配时间片),直到得到结果后才返回。


(3).非阻塞:是指如果一个函数不能立刻得到结果,这个函数不会阻塞该线程而立即返回。


(4).异步:是指在一个功能调用时,这个调用不会立即得到结果,也不会阻塞该线程,这个调用所在的线程会继续执行其它事情,而这个功能是由其它执行部件来完成,当这个部件执行完该功能时,通过状态,通知来通知调用者,或通过回调函数处理这个调用。


执行部件和调用者可以通过三种途径返回结果:
a.   状态、
b.   通知、
c.   回调函数。

使用哪一种依赖于执行部件的实现,除非执行部件提供多种选择,否则不受调用者控制。

a. 如果执行部件用状态来通知,
    那么调用者就需要每隔一定时间检查一次,效率就很低

b. 如果是使用通知的方式,
    效率则很高,因为执行部件几乎不需要做额外的操作。

c. 至于回调函数,
    和通知没太多区别。




四.五种I/O模型:(理解了上面的知识,下面应该比较容易理解了)

(1).阻塞式I/O:

  应用程序调用一个IO函数,导致应用程序阻塞,等待数据准备好。 如果数据没有准备好,一直等待….数据准备好了,从内核拷贝到用户空间,IO函数返回成功指示。

如下图:

技术分享


(2).非阻塞式I/O:

在非阻塞I/O中,一定要把一个I/O操作函数放在一个死循环中,直到这个I/O函数返回一个正确值时才跳出这个循环。

我们把一个SOCKET接口设置为非阻塞就是告诉内核,当所请求的I/O操作无法完成时,不要将线程睡眠,而是返回一个错误。这样我们的I/O操作函数将不断的测试数据是否已经准备好,如果没有准备好,继续测试,直到数据准备好为止。在这个不断测试的过程中,会大量的占用CPU的时间。

如下图:

技术分享


(3).信号驱动:

 首先要允许接口进行信号驱动I/O,然后安装一个信号处理函数,线程继续运行并不阻塞。当数据准备好时,线程会收到一个SIGIO信号,可以在信号处理函数中调用I/O操作函数处理数据。

如下图:

技术分享


(4).I/O复用:

I/O 复用模型会用到select、poll、epoll函数,这几个函数也会使进程阻塞,但是和阻塞I/O所不同的,这几个函数可以同时阻塞多个I/O操 作。而且可以同时对多个读操作,多个写操作的I/O函数进行检测,直到有数据可读或可写时,才真正调用I/O操作函数。(比阻塞式I/O并没有上面优越性,但它实现了对多个I/O端口的监听)

如下图:

技术分享



(5).异步I/O:

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

如下图:

技术分享




六.五种I/O模型比较:

技术分享





七.总结:

理解五种I/O模型应该先理解I/O操作过程,并理解阻塞,非阻塞,同步,异步的一些知识。

I/O操作要和硬件打交道,所以会I/O操作过程会涉及到操作系统。

处理I/O操作分为两个过程,一是等待数据,二是把数据从内核中搬到用户空间。

这五中I/O模型的不同之处是在等待数据的方式上,在第二个过程中是一样的,都是把数据从内核中搬到用户空间,然后进行相关操作。


本文出自 “水仙花” 博客,请务必保留此出处http://10704527.blog.51cto.com/10694527/1782715

以上是关于网络编程之五种I/O模型的主要内容,如果未能解决你的问题,请参考以下文章

透彻Linux(Unix)五种IO模型

五种 IO 模型

五种I/O模型和Java NIO源码分析

五种I/O模型简述

没搞清楚网络I/O模型?那怎么入门Netty

大白话五种IO模型