Unix系统下的5种I/O模型 及其应用场景(BIO NIO AIO)

什么是I/O

  • 这里我们管CPU和内存之间的交互不叫IO哈~
  • 只有本机和外部的交互才叫IO,分为两大类:主机和外设(磁盘也属于外设哈)之间的IO,两台主机之间的网络IO。 
  • 和外部交互这一工作,可以由CPU直接进行,大部分是由内存去和外设交互的(毕竟太慢了拖累CPU效率嘛),不需要纠结到底是CPU还是内存,只需要知道是主机在和外部IO即可!

分清模型和应用产品

学习之前我们要分清什么是模型,什么是实际应用场景。模型就是下面要说的5个,属于理论,实际应用就是在市场中的实现,java BIO、java NIO就是模型的应用,网络I/O中的socket也是应用,还有CPU和外设的终端机制也是应用。对比来理解,关系型数据库理论可以看做模型,MySQL、SQL Server就是这个理论的应用。

前言

  • 因为我们现在讲的是UNIX系统下的IO模型,UNIX是C语言写的,所以下面讲的函数以及代码演示都是C的函数哦。
  • 以网络IO为例,当程序请求获取网络数据的时候,需要经历两次拷贝:

    1. 程序需要等待数据从网卡拷贝到内核空间
    2. 因为用户程序无法访问内核空间,所以内核又得把数据拷贝到用户空间,这样处于用户空间的程序才能访问这个数据。

对应的就是这张图里框出来的两部分:

介绍这么多就是让你理解为什么会有两次拷贝,且系统调用是有开销的,因此最好不要频繁调用。

然后我们今天说的 I/O 模型之间的差距就是这拷贝的实现有所不同!

今天我们就以 read 调用,即读取网络数据为例子来展开 I/O 模型。
 

一、5种I/O模型

UNIX 系统下, IO 模型一共有 5 种: 同步阻塞 I/O同步非阻塞 I/OI/O 多路复用信号驱动 I/O异步 I/O

  • 数据准备阶段和数据拷贝阶段

  • 阻塞和非阻塞:阻塞和非阻塞指的是数据准备阶段进程是否需要阻塞等待。或者这样理解,还记得UDP的receive()方法和TCP的accept()方法吗,什么都没收到也不知道会不会收到的时候也要阻塞等待,这叫阻塞

  • 同步和异步:同步和异步指的是数据拷贝阶段进程是否需要阻塞,阻塞为同步,不阻塞为异步

分为4种同步的,1种异步的。同步和异步很好理解,同步的定义我们在操作系统已经深入理解了:“进程A的执行需要B的结果,所以并发执行的进程需要在某些点上相互等待”,也就是CPU/进程在内核拷贝数据的时候要一直阻塞等待I/O完成,才能继续干自己的事情。异步是指在内核拷贝数据的时候,应用进程也不需要阻塞,从头至尾和I/O是并行的。

1.1 阻塞IO模型

1. 模型介绍

2. 典型应用

阻塞socket、Java BIO

3. 特点

Java BIO

        我们就用TCP socket这个典型BIO去看一下BIO的特点。BIO会给每个accept接收到的客户端连接单独开一个线程去处理(为什么这样做呢?以为如果只有一个线程的话,客户端那边来了一个请求,服务端这边accept接收到了,然后阻塞在read方法等待客户端输入,如果这个客户端迟迟不输入,那么其他陆陆续续来的连接请求都得不到处理,所以BIO给每个请求单独开一个线程,这样就保证新来的请求一直能够被处理,互联网发展初期,网站的用户请求不多时,BIO是能用的,但是当请求量激增的时候呢?来了50万个请求,给开50万个线程吗?服务器崩掉!

1.2非阻塞IO模型

1. 思想:虽然该模型叫非阻塞I/O模型,但是只是下图中等待数据的阶段不用阻塞,接收数据的时候依然要阻塞哦,只有异步I/O在接收数据的时候也不需要阻塞。

2.典型应用CPU的查询方式访问I/O

3. 特点

轮询会消耗大量CPU资源,CPU效率低下,计组时就讲过CPU轮询太浪费资源,一定会被淘汰的,所以非阻塞IO只有在特定场景下才会被用到

CPU和外设只能串行,CPU不能并发和多个线程通信,只能和一个线程通信。

1.3 I/O复用模型

思想:之前都是执行主要任务的线程自己负责和I/O通信,现在额外开辟一个线程,专门负责和I/O通信的,叫做select线程, select会监听所有注册进来的IO,当select线程接收到来自外设的I/O请求后,再交给应用线程进行数据的I/O

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

java NIO

JDK1.4前只能用BIO,当时程序规模不大,互联网在起步阶段并发要求也不高,所以BIO够用,但是逐渐不够用了。从JDK1.4开始,java提供了NIO,NIO比BIO强在哪里?

  1. BIO需要一直阻塞,浪费CPU资源,NIO不需要阻塞

  1. BIO在同一时间只能为一个客户端线程提供服务,NIO可以同时和多个客户端线程通信

选择器(selector):监听

通道(channel)

缓冲区(buffer):外设的数据不是直接给进程,而是先放到缓冲区里,这样就可以实现一个服务器线程和多个客户端线程通信了。

1.4 信号驱动I/O模型

还是同步的,因为数据从内核拷贝到用户空间时,进程是阻塞的。

当进程发起一个IO操作,会向内核注册一个信号处理函数,然后进程返回不阻塞;当内核数据就绪时会发送一个信号给进程,进程便在信号处理函数中调用IO读取数据。

典型应用:中断机制

1.5 异步I/O模型

        消息中间就是异步,客户端和服务器各干各的。

        实现太复杂,太复杂,现在没人用。你想啊,现在的RPC、RMC、中断机制都是主线程阻塞,先去处理子线程,子线程处理完了再返回主线程,都是同步的。

        异步的不是不可以实现,而是实现起来太复杂了。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值