五种IO模型

阻塞非阻塞+同步异步

只针对网络IO而言

典型的一次IO的两个阶段:

  1. 数据就绪:根据系统IO操作的就绪状态
    • 阻塞
    • 非阻塞
  2. 数据读写:根据应用程序和内核的交互方式
    • 同步
    • 异步
 ssize_t recv(int sockfd, void *buf, size_t len, int flags);
//recv---内存缓冲区地址,将所接收数据存放的数组,长度,标记:一般置0

阻塞:调用IO方法的线程进入阻塞状态,不占用CPU

非阻塞:不会改变线程的状态,通过返回值去判断当前线程状态

对recv()而言:

  • -1是出错了,有些是设置了特殊错误号
  • 0是读到末尾了,对方连接关闭
  • 大于0:读取的数据大小

数据就绪阶段一般发生在操作系统的内存缓冲区;数据读写阶段发生在应用程序

同步:调用网络IO进行数据读写的时候,应用程序主动向os的缓冲区读数据

因为数组是自己定义的,所以是我们自己主动去OS读数据

异步:OS提供api然后由操作系统读数据,是OS把数据存到提供的存放数组地址

效率高,但是编程复杂

API:

重要参数:sockfd,buf(存放数据),通知方式(用信号)

在处理 IO 的时候,阻塞和非阻塞都是同步 IO,只有使用了特殊的 API 才是异步 IO

int aio_read(struct aiocb *aiocbp);
int aio_write(struct aiocb *aiocbp);
//异步IO只和非阻塞连用,因为要保证程序执行其他任务,阻塞状态无意义

阻塞非阻塞和同步异步的总结

一个网络IO接口的调用会有两个阶段:数据就绪和数据读写

  1. 数据就绪分为阻塞和非阻塞:
  • 阻塞就是当前线程挂起,但不影响CPU调度

  • 非阻塞就是直接返回结果,当前进程状态不会改变

  1. 数据读写分为同步和异步
  • 同步就是:应用程序主动从缓冲区读取数据
  • 异步就是:给OS系统一个存取地址和通知方式,数据读写是os自己完成的,os完成后通知线程

IO多路复用:select,poll,epoll都是同步的数据读写方式,除了一些特殊网络接口,不管是阻塞还是非阻塞的数据就绪状态都是同步的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uLJ8OFnV-1680170721794)(/home/guojiawei/.config/Typora/typora-user-images/image-20230330174402909.png)]

Linux五种IO模型

1.阻塞 blocking

​ 调用者调用了某个函数,阻塞地等待函数的返回,这期间什么都不做,只有函数返回后这个线程才能进行下一部动作。

五种IO模型_第1张图片

2.非阻塞 non-blocking NIO

​ 非阻塞IO执行系统调用总是立刻返回,如果没发生就返回-1,设置错误号EAGAIN;发生了就进行操作.

​ 进程需要每隔一段时间就去检测一下IO事件是否就绪

五种IO模型_第2张图片

3.IO复用 IO multiplexing

一次检测多个文件描述符,如果有数据可读可写,系统就直接对这个文件描述符进行操作

​ 不管是阻塞还是非阻塞,系统一次只能进行一次IO操作,Linux通过select,poll,epoll实现IO复用,使得可以同时阻塞多个IO,可以进行多个读写IO函数的检测。

​ 直到数据准备好后,有数据可读可写才真正执行IO操作函数。

五种IO模型_第3张图片

4.信号驱动

安装一个信号处理函数,进程继续运行并不阻塞,当IO事件就绪,进程收到SIGIO 信号,然后处理 IO 事件。

注册一个信号处理函数,IO时间就绪,内核通过发送信号给进程,让进程处理IO读写操作

五种IO模型_第4张图片

5.异步 asynchronous

Linux中,可以调用 aio_read 函数告诉内核描述字缓冲区指针缓冲区的大小文件偏移及通知的方式,然后立即返回,当内核将数据拷贝到缓冲区后,再通知应用程序。

内核完成数据就绪和数据读写过程,最后只要通知进程完成了操作即可。

五种IO模型_第5张图片

你可能感兴趣的:(Linux网络编程,网络,开发语言,linux)