网络编程中的I/O模型

Linux的五种IO模型

什么是阻塞和非阻塞

阻塞通常是指调用方在等待数据返回的过程。如果调用方一直在等待,那么就是阻塞的;反之则是非阻塞的;

阻塞会将当前线程挂起,非阻塞则不会。

什么是同步和异步

同步和异步是针对被调用者来说的。同步和异步一般从俩方面来说:

  1. 是指数据处理的过程是由被调用方处理还是交由它方处理(例如内核),由被调用方处理数据那就是同步的,由内核处理数据那就是异步的
  2. 同步过程中,被调用方是不能处理其他数据(行为操作),异步操作则可以,但异步操作获取数据这个过程,需要数据处理结束后才能获取到;(复杂度在这种处理情况中)
钓鱼案例解析IO模型

钓鱼分为等待鱼上钩、鱼上钩、将鱼钓起放入鱼篓、鱼吃勾报警器、多套钓鱼装备、智能钓鱼器自动拉鱼;

调用方:钓鱼人

阻塞和非阻塞区分:

阻塞:

  • 钓鱼人一直等待鱼上勾;
  • 将鱼钓起放入鱼篓

非阻塞:

  • 钓鱼人在玩手机,偶尔看下有没有上钩;
  • 智能钓鱼器自动拉鱼,开始放入鱼篓
  • 鱼上钩,报警器响了;

同步和异步区分:

同步:钓鱼人将鱼钓起放入鱼篓

异步:智能钓鱼器自动拉鱼将鱼放入鱼篓

按照上面的区分,五中IO模型则分别为:

  • 钓鱼人一直等待鱼上钩,上钩后,将鱼钓起放入鱼篓-----阻塞IO------BIO
  • 钓鱼人在玩手机,偶尔看下有没有上钩;上钩后,将鱼钓起放入鱼篓------非阻塞IO--------NIO
  • 钓鱼人在玩手机,鱼上钩,报警器响了;上钩后,将鱼钓起放入鱼篓--------信号驱动模型IO
  • 多套钓鱼装备一起钓鱼,钓鱼人一直等待鱼上钩,上钩后,将鱼钓起放入鱼篓--------IO复用
  • 使用智能钓鱼器钓鱼,鱼上钩后,自动拉鱼,放入鱼篓;通知钓鱼人鱼放进鱼篓了-----异步IO------AIO
烧开水案例解析IO模型

烧开水分为小孩等待水烧开、水开了、开水倒入水杯、水开报警器、多个烧水壶、智能烧水放水烧水壶;

调用方:小孩

阻塞和非阻塞区分:

阻塞:

  • 小孩一直等水烧开
  • 开水倒入水杯

非阻塞:

  • 小孩在看电视,偶尔看下水有没有开
  • 智能烧水壶水烧开,开始倒入水杯;
  • 水烧开了,水开报警器响了

同步和异步区分:

同步:小孩将开水倒入水杯

异步:智能烧水壶将水烧开,倒入水杯

按照上面的区分,五中IO模型则分别为:

  • 小孩一直等水烧开,水开了,将开水倒入水杯------阻塞IO------BIO(阻塞+同步)
  • 小孩在看电视,偶尔看下水有没有开,水开了,将开水倒入水杯-------非阻塞IO--------NIO(非阻塞+同步)
  • 小孩在看电视,水烧开了,水开报警器响了,水开了,将开水倒入水杯-------信号驱动模型IO(非阻塞+同步)
  • 多个烧水壶一起烧水,小孩一直等有没有水烧开,水开了,将开水倒入水杯--------------复用IO(阻塞+同步)
  • 使用智能烧水壶水烧开,水开了,自动倒入水杯;通知小孩水开了-------------异步IO(非阻塞+异步)

1.阻塞IO

应用程序从recvfrom开始到有数据报准备好这段时间是阻塞的。

  1. 应用程序调用recvfrom方法,等待进程中的缓冲区数据
  2. recvfrom系统调用内核
  3. 内核无数据报准备好则进入等待
  4. 内核数据报准备好,复制数据到进程缓冲区
  5. 应用程序开始处理数据报进行返回

2.非阻塞IO

应用程序从recvfrom调用,内核会马上返回结果,数据报有没有准备好,内核不会阻塞等待数据报准备好。

  1. 应用程序反复调用recvfrom方法,检测内核中数据报是否准备好
  2. 当内核数据报准备好后,应用程序再次调用recvfrom
  3. 复制数据到进程缓冲区则会从缓冲区取到数据
  4. 应用程序开始处理数据报进行返回

3.信号驱动模型IO

在信号驱动式 I/O 模型中,应用程序使用套接口进行信号驱动 I/O,并安装一个信号处理函数,进程继续运行并不阻塞。当数据准备好时,进程会收到一个 SIGIO 信号,可以在信号处理函数中调用 I/O 操作函数处理数据。

信号驱动 I/O 尽管对于处理 UDP 套接字来说有用,即这种信号通知意味着到达一个数据报,或者返回一个异步错误。但是,对于 TCP 而言,信号驱动的 I/O 方式近乎无用,因为导致这种通知的条件为数众多,每一个来进行判别会消耗很大资源,与前几种方式相比优势尽失。

  1. 应用程序创建SIGNO锚点,调用sigaction;
  2. 内核开始准备数据,当数据报准备好后,会调用SIGNO锚点
  3. 应用程序接受到通知后,调用recvfrom,将数据复制到对应的进程缓冲区
  4. 应用程序从缓冲区读取数据,开始处理数据报进行返回

4.IO复用

IO复用是调用系统的Select或者Epoll函数,这两个函数可以同时阻塞多个 I/O 操作,而且可以同时对多个读操作,多个写操作的 I/O 函数进行检测,直到有数据可读或可写时,才真正调用 I/O 操作函数。

  1. 应用程序调用select,内核返回selector对应的多个channel中,有没有数据报准备好
  2. 如果没有,则select阻塞,等待有任何一个channel的数据报准备好
  3. 当select返回后,则调用recvfrom,将数据复制到对应的进程缓冲区
  4. 应用程序从缓冲区读取数据,开始处理数据报进行返回

5.异步IO

应用程序告知内核启动某个操作,并让内核在整个操作(包括将数据从内核拷贝到应用程序的缓冲区)完成后通知应用程序。

信号驱动 I/O 是由内核通知应用程序何时启动一个 I/O 操作,而异步 I/O 模型是由内核通知应用程序 I/O 操作何时完成。

  1. 应用程序aio_read,指定通知的信号,调用内核
  2. 内核等待数据报准备好后,将数据复制到应用程序的缓冲区,
  3. 内核调用aio_read的通知锚点
  4. 应用程序处理数据进行返回
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值