IO模型!

IO模型

IO模型须知

什么是IO(input/output)

  • 网络IO
  • 设备IO

IO模型的两个阶段

  1. 第一阶段:等待数据准备,此阶段是不需要占用CPU的,CPU通过调用DMA执行设备操作。可是如果是调用其他进程执行数据准备(例如mysql进程),还是会需要用到CPU,但是已经算是另外一个进程的IO操作了
  2. 第二阶段:数据从内核空间拷贝到用户空间,此阶段需要占用CPU进行拷贝

5种IO模型

  • 阻塞IO
  • 非阻塞IO
  • 多路复用IO
  • 异步IO
  • 信号驱动IO

为何一个监听socket可以accept多次

accept()能够返回一个新的socket。下面是 accept 接口的原型:

int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
输入参数s是从socket()bind()listen()中沿用下来的socket句柄值(int(fd))。执行完bind()listen()后,操作系统已经开始在指定的端口处监听所有的连接请求,如果有请求,则将该连接请求加入请求队列。调用accept()接口正是从 socket s 的请求队列抽取第一个连接信息,创建一个与s同类的新的socket返回句柄。新的socket句柄即是后续read()recv()的输入参数。如果请求队列当前没有请求,则accept() 将进入阻塞状态直到有请求进入队列。

什么是文件描述符fd(File Descriptor),它是计算机科学中的一个术语,形式上是一个非负整数。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符

IO模型解析

阻塞IO (blocking IO)

阻塞只是针对于数据准备阶段(第一阶段)的用户进程(recvfrom),数据从内核拷贝到应用内存时依旧是阻塞态。当kernel没有获取到完整的数据时,用户进程会进入**阻塞态**,所以这CPU使用权被让出,在此期间,线程将无法执行任何运算或响应任何的网络请求。当kernel准备好数据,cpu被调度回来执行数据拷贝。

因为阻塞状态,cpu使用权被让出,如果是多个socket连接,都在同一个进程上,一样没有cpu使用权,所以阻塞IO模型是一对一

blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了。

阻塞态:

当用户进程阻塞后,进程进入等待,所以会让出CPU,CPU去执行其他的进程。

阻塞IO code
一对一阻塞IO

多线程阻塞IO

这虽然已经解决了多监听不阻塞,可是当成千上万个请求洪峰到来时,系统资源就会被占满,所以不是最佳方案

非阻塞IO(non-blocking IO)

非阻塞只是针对于数据准备阶段(第一阶段)的用户进程(recvfrom),数据从内核拷贝到应用内存时依旧是阻塞态。当用户发出read操作时,如果kernal没有准备好数据,recvfrom请求会立即放返回数据,并不会使用户进程blocking。

在非阻塞式IO中,用户进程其实是需要不断的主动询问kernel数据准备好了没有。

非阻塞IO就实现了多个线程阻塞IO,因为不是阻塞态,所以进程还有CPU使用权,那么多客户端连接时,用户进程就会为下一个客户端的socket发送recvfrom请求,同时检测多个连接的数据时候准备就绪。一对多

DMA:操作系统内核 调用 CPU ,然后CPU调用DMA实现硬件IO,这样CPU就可以从操作系统内核切换到其他的应用这样就出现了 5种IO模型 blocking select poll epoll !!!

非阻塞IO code

非阻塞IO就实现了多个线程阻塞IO,因为不是阻塞态,所以进程还有CPU使用权,那么多客户端连接时,用户进程就会为下一个客户端的socket发送recvfrom请求,同时检测多个连接的数据时候准备就绪。

虽然已经不阻塞了,并且可以监听多个客户端连接。但是不推荐使用这种方法,因为需要循环调用recv(),它将大幅度提高CPU的占用率。

多路复用IO (multiplexting IO)

多路复用IO包括了select/poll/epoll。它的好处在于单个进程就可以同时处理多个网络连接的IO。当用户进程调用select,整个进程会被阻塞,但是和阻塞IO不同的是,kernel会监听所有的select负责的socket,当任何一个socket中数据被准备完毕,那么cpu会调度到用户进程中。他的原理就是select/epoll这个function会不断的轮训所有socket。IO复用同非阻塞IO本质一样,不过利用了新的select系统调用,由内核来负责本来是请求进程该做的轮询操作。

在多路复用模型中,对于每一个socket,一般都设置成为non-blocking,但是,如上图所示,整个用户的process其实是一直被block的。
在这里插入图片描述

异步IO(Asynchronous IO)

用户进程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从kernel的角度,当它受到一个asynchronous read之后,首先它会立刻返回,所以不会对用户进程产生任何block。然后,kernel会等待数据准备完成,然后将数据拷贝到用户内存,当这一切都完成之后,kernel会给用户进程发送一个signal,告诉它read操作完成了。

以为不是block状态,所以应用程序是继续执行的,通过回调执行获取数据之后的业务逻辑。可以参照swoole的协程

5种IO的对比

可以看出前4种IO模型在数据从内核态copy到用户态的时候,用户进程是阻塞的,而异步IO全程都是非阻塞的

参考

https://blog.csdn.net/qiu18610714529/article/details/119512760

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值