IO高并发模型

一、IO概念

  IO (Input/Output,输入/输出)即数据的读取(接收)或写入(发送)操作。

  通常用户进程中的一个完整IO分为两阶段:
(1)设备空间(磁盘、网络等)  到   内核空间;
(2)内核空间   到   用户进程空间。

  IO有内存IO、网络IO和磁盘IO三种,通常我们说的IO指的是后两者。

  Linux中进程无法直接操作I/O设备,其必须通过系统调用来协助完成I/O动作;内核会为每个I/O设备维护一个缓冲区。

  对于一个输入操作来说,进程IO系统调用后,内核会先看缓冲区中有没有相应的缓存数据,没有的话再到设备中读取,因为设备IO一般速度较慢,需要等待;内核缓冲区有数据则直接复制到进程空间。所以,对于一个网络输入操作通常包括两个不同阶段:
(1) 等待网络数据到达网卡→读取到内核缓冲区,数据准备好;
(2) 从内核缓冲区复制数据到进程空间。

二、五种IO模型

  阻塞IO模型、非阻塞IO模型、IO复用模型、信号驱动的IO模型、异步IO模型。
  前4种为同步IO操作,只有异步IO模型是异步IO操作。

阻塞IO模型:
  进程发起IO系统调用后,进程被阻塞,转到内核空间处理,整个IO处理完毕后返回进程。操作成功则进程获取到数据。
  典型应用:阻塞socket。
  特点:进程阻塞挂起不消耗CPU资源,及时响应每个操作;实现难度低、开发应用较容易;适用并发量小的网络应用开发。不适用并发量大的应用:因为一个请求IO会阻塞进程,所以,得为每请求分配一个处理进程(线程)以及时响应,系统开销大。

非阻塞IO模型:
  进程发起IO系统调用后,如果内核缓冲区没有数据,需要到IO设备中读取,进程返回一个错误而不会被阻塞;进程发起IO系统调用后,如果内核缓冲区有数据,内核就会把数据返回进程。对于上面的阻塞IO模型来说,内核数据没准备好需要进程阻塞的时候,就返回一个错误,以使得进程不被阻塞。
  典型应用:socket是非阻塞的方式(设置为NONBLOCK)。
  特点:进程轮询(重复)调用,消耗CPU的资源;适用并发量较小、且不需要及时响应的网络应用开发。

IO复用模型:
  多个的进程的IO可以注册到一个复用器(select)上,然后用一个进程调用该select, select会监听所有注册进来的IO;如果select没有监听的IO在内核缓冲区都没有可读数据,select调用进程会被阻塞;而当任一IO在内核缓冲区中有可读数据时,select调用就会返回;而后select调用进程可以自己或通知另外的进程(注册进程)来再次发起读取IO,读取内核中准备好的数据。多个进程注册IO后,只有另一个select调用进程被阻塞。
  典型应用:select、poll、epoll三种方案。
  特点:专一进程解决多个进程IO的阻塞问题,性能好;Reactor模式; 实现、开发应用难度较大;适用高并发服务应用开发:一个进程(线程)响应多个请求;
Linux中IO复用的实现方式主要有select、poll和epoll:
  Select:注册IO、阻塞扫描,监听的IO最大连接数不能多于FD_SIZE;
  Poll:原理和Select相似,没有数量限制,但IO数量大扫描线性性能下降;
  Epoll :事件驱动不阻塞,mmap实现内核与用户空间的消息传递,数量很大。

信号驱动IO模型:
  当进程发起一个IO操作,会向内核注册一个信号处理函数,然后进程返回不阻塞;当内核数据就绪时会发送一个信号给进程,进程便在信号处理函数中调用IO读取数据。
  特点:回调机制,实现、开发应用难度大。

异步IO模型:
  当进程发起一个IO操作,进程返回(不阻塞),但也不能返回结果;内核把整个IO处理完后,会通知进程结果。如果IO操作成功则进程直接获取到数据。
  特点:不阻塞,数据一步到位。适合高性能高并发应用。

三、五种IO模型的通俗说法(便于理解)

IO模型通俗例子系统层面
阻塞IOA拿着一支鱼竿在河边钓鱼,并且一直在鱼竿前等,在等的时候不做其他的事情,十分专心。只有鱼上钩的时,才结束掉等的动作,把鱼钓上来。在内核将数据准备好之前,系统调用会一直等待所有的套接字,默认的是阻塞方式。我们例子中所说的鱼竿就是这一个文件描述符。这个模型是我们最常见的,程序调用和我们编写的基本程序是一致的。
非阻塞IOB也在河边钓鱼,但是B不想将自己的所有时间都花费在钓鱼上,在等鱼上钩这个时间段中,B也在做其他的事情(一会看看书,一会读读报纸,一会又去看其他人的钓鱼等),但B在做这些事情的时候,每隔一个固定的时间检查鱼是否上钩。一旦检查到有鱼上钩,就停下手中的事情,把鱼钓上来。B在检查鱼竿是否有鱼,是一个轮询的过程每次客户询问内核是否有数据准备好,即文件描述符缓冲区是否就绪。当有数据报准备好时,就进行拷贝数据报的操作。当没有数据报准备好时,也不阻塞程序,内核直接返回未准备就绪的信号,等待用户程序的下一个轮寻。轮寻对于CPU来说是较大的浪费。
信号驱动IOC也在河边钓鱼,但与A、B不同的是,C比较聪明,他给鱼竿上挂一个铃铛,当有鱼上钩的时候,这个铃铛就会被碰响,C就会将鱼钓上来。信号驱动IO模型,应用进程告诉内核:当数据报准备好的时候,给我发送一个信号,对SIGIO信号进行捕捉,并且调用我的信号处理函数来获取数据报。
IO多路复用D同样也在河边钓鱼,但是D生活水平比较好,D拿了很多的鱼竿,一次性有很多鱼竿在等,D不断的查看每个鱼竿是否有鱼上钩。增加了效率,减少了等待的时间。IO多路转接是多了一个select函数,select函数有一个参数是文件描述符集合,对这些文件描述符进行循环监听,当某个文件描述符就绪时,就对这个文件描述符进行处理。IO多路转接是属于阻塞IO,但可以对多个文件描述符进行阻塞监听,所以效率较阻塞IO的高。
异步IOE也想钓鱼,但E有事情,于是他雇来了F,让F帮他等待鱼上钩,一旦有鱼上钩,F就打电话给E,E就会将鱼钓上去。当应用程序调用aio_read时,内核一方面去取数据报内容返回,另一方面将程序控制权还给应用进程,应用进程继续处理其他事情,是一种非阻塞的状态。当内核中有数据报就绪时,由内核将数据报拷贝到应用程序中。

四、同步IO与异步IO

同步和异步关注的是双方的消息通信机制(双方是指,用户进程和IO设备。):
  同步:双方的动作是经过双方协调的,步调一致的。
  异步:双方并不需要协调,都可以随意进行各自的操作。

同步IO:用户进程发出IO调用,去获取IO设备数据,双方的数据要经过内核缓冲区同步,完全准备好后,再复制返回到用户进程。而复制返回到用户进程会导致请求进程阻塞,直到I/O操作完成。
异步IO:用户进程发出IO调用,去获取IO设备数据,并不需要同步,内核直接复制到进程,整个过程不导致请求进程阻塞。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值