网络总结(四大IO模型)

四大IO模型

阻塞和非阻塞的区别:
阻塞与非阻塞都指的是用户空间程序的执行状态。阻塞IO指的是需要内核IO操作彻底完成后,才返回到用户空间执行用户的操作。
阻塞是指用户空间(调用线程)一直在等待,而不能干别的事情;非阻塞是指用户空间(调用线程)拿到内核返回的状态值就返回自己的空间,就可以去完成别的任务。
同步和异步的区别:
 同步IO是一种用户空间与内核空间的IO发起方式。同步IO是指用户空间的线程是主动发起IO请求的一方,内核空间是被动接收方;异步IO是指系统内核是主动发起IO请求的一方,用户空间的线程是被动接受方。

1、同步阻塞IO(Blocking IO)

在Java中,默认创建的socket都是阻塞的。由用户空间向内核空间发起IO请求,等到内核IO操作彻底完成后,才返回到用户空间执行用户操作。
  在阻塞式IO模型中,Java程序从IO系统调用开始,直到系统调用返回,在这段时间内,Java进程是阻塞的。返回成功后,应用进程开始处理用户空间的缓存区数据。

在这里插入图片描述
流程:

  1. 从Java启动IO读的read系统调用开始,用户线程就进入阻塞状态。
  2. 当系统内核收到read系统调用,就开始准备数据。一开始,数据可能还没有到达内核缓冲区(例如还未收到一个完整的socket数据包),这个时候内核就要开始等待。
  3. 内核一直等到完整的数据到达,就会将数据从内核缓冲区复制到用户缓冲区(用户空间的内存),然后内核返回结果(例如返回复制到用户缓冲区中的字节数)。
  4. 直到内核返回后,用户线程才会解除阻塞的状态,重新运行。

优点:

  1. 应用程序开发简单;
  2. 在阻塞等待数据期间,用户线程挂起,基本不会占用CPU资源。

缺点:
3. 当在高并发的应用场景下,需要大量的线程来维护大量的网络连接,内存、线程切换开销巨大。阻塞IO不适合在高并发应用场景下。
4. 一般情况下,会为每个连接配备一个独立的线程,每个线程维护一个连接的IO操作

2、同步非阻塞IO(Non-blocking IO)

同步非阻塞IO简称为NIO模式。由用户空间主动发起IO请求,但是用户空间的程序不需要等待内核IO操作彻底完成,可以立即返回用户空间执行用户的操作,即处于非阻塞状态,与此同时,内核会立即返回给用户一个状态值。

在NIO模型中,应用程序一旦开始IO系统调用,会出现以下两种情况:
  1. 在内核缓冲区中没有数据的情况下,系统调用会立即返回,返回一个调用失败的信息。
  2. 在内核缓冲区中有数据的情况下,是阻塞的,直到数据从内核缓冲复制到用户进程缓冲。复制完成后,系统调用返回成功,应用进程开始处理用户空间的缓存数据。
在这里插入图片描述
流程:

  1. 在内核数据没有准备好的阶段,用户线程发起IO请求时,立即返回。所以为了读取到最终的数据,用户线程需要不断地发起IO系统调用。
  2. 内核数据到达时,用户线程发起系统调用,用户线程阻塞。内核开始复制数据,它会将数据从内核缓冲区复制到用户缓冲区(用户空间的内存),然后内核返回结果(例如返回复制到用户缓冲区中的字节数)。
  3. 用户线程读到数据后,才会解除阻塞状态,重新运行起来。

特点:
应用程序的线程需要不断地进行IO系统调用,轮询数据是否已经准备好。如果没有准备好,就继续轮询,直到完成IO系统调用为止。即一次IO请求可能无法获取数据。

优点:
每次发起的IO系统调用,在内核等待数据过程中可以立即返回。用户线程不会阻塞,实时性较好。
缺点:
不断地轮询内核,会占用大量的CPU时间,效率低下。

3、IO多路复用模型(IO Multiplexing)

为了避免同步非阻塞IO模型中轮询等待的问题,有了IO多路复用模型。 在IO多路复用模型中,用到了一种新的系统调用,用于查询IO的就绪状态。在Linux系统中,对应的系统调用为select/poll、epoll系统调用。通过该系统调用,一个进程可以监视多个文件描述符,一旦某个描述符就绪(内核缓冲区可读/可写),内核能够将就绪的状态返回给应用程序。随后,应用程序根据就绪的状态,进行相应的IO系统调用(读写过程为阻塞状态)
在这里插入图片描述

几种系统调用的区别
1.select

时间复杂度为O(n)。select 的核心功能是调用tcp文件系统的poll函数,不停的查询,若是没有想要的数据,主动执行一次调度(防止一直占用cpu),直到有一个链接有想要的消息为止。select的执行方式基本就是不停的调用poll,直到有需要的消息为止。

优点
①. select的可移植性更好,在某些Unix系统上不支持poll()。
②. select对于超时值提供了更好的精度:微秒,而poll是毫秒。

缺点
①. 每次调用select,都须要把fd(文件描述符)集合从用户态拷贝到内核态,这个开销在fd不少时会很大;
②. 同时每次调用select都须要在内核遍历传递进来的全部fd,这个开销在fd不少时也很大;
③. select支持的文件描述符数量过小了,默认是1024。

2.poll

poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,而后查询每一个fd对应的设备状态,若是设备就绪则在设备等待队列中加入一项并继续遍历,若是遍历完全部fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个过程经历了屡次无谓的遍历。poll还有一个特色是“水平触发”,若是报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

优点
①. poll() 不要求开发者计算最大文件描述符加一的大小。

②. poll() 在应付大数目的文件描述符的时候速度更快,相比于select。

③. 它没有最大链接数的限制,缘由是它是基于链表来存储的。

缺点
①. 大量的fd的数组被总体复制于用户态和内核地址空间之间,而无论这样的复制是否是有意义;
②. 与select同样,poll返回后,须要轮询pollfd来获取就绪的描述符。

3.epoll

epoll是在Linux2.6内核中提出的,是之前的select和poll的增强版本。相对于select和poll来说,epoll更加灵活,没有描述符限制。epoll使用一个文件描述符管理多个描述符,将用户关系的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的copy只需一次。

三者区别

select,poll实现须要本身不断轮询全部fd集合,直到设备就绪,期间可能要睡眠和唤醒屡次交替。而epoll其实也须要调用epoll_wait不断轮询就绪链表,期间也可能屡次睡眠和唤醒交替,可是它是设备就绪时,调用回调函数,把就绪fd放入就绪链表中,并唤醒在epoll_wait中进入睡眠的进程。虽然都要睡眠和交替,可是select和poll在“醒着”的时候要遍历整个fd集合,而epoll在“醒着”的时候只要判断一下就绪链表是否为空即可,这节省了大量的CPU时间。这就是回调机制带来的性能提高。

4、异步IO模型(Asynchronous IO)

异步IO模型(Asynchronous IO,简称为AIO)。AIO的基本流程是:用户线程通过系统调用,向内核注册某个IO操作。内核在整个IO操作(包括数据准备、数据复制)完成后,通知用户程序,用户执行后序的业务操作。在异步IO模型中,用户程序都不会发生阻塞

流程:

  1. 当用户线程发起了read系统调用,立即就可以去做其他的事,用户线程不阻塞。
  2. 内核开始IO的第一个阶段:准备数据。等到数据准备好,内核就会将数据从内核缓冲区复制到用户缓冲区(用户空间的内存)。
  3. 内核会给用户线程发送一个信号(Singal),或者回调用户线程注册的回调接口,告诉用户线程read操作完成。
  4. 用户线程读取用户缓冲区的数据,完成后续的业务操作。

特点:
在内核等待数据和复制数据的两个阶段,用户线程都不是阻塞的。用户线程需要接受内核的IO操作完成的事件,或者用户线程需要注册一个IO操作完成的回调函数。异步IO也被称为信号驱动IO。

优点:
异步IO是真正的异步输入输出,它的吞吐量高于IO多路复用

缺点:
应用程序仅需要进行事件的注册和接收,其余的工作都留给了操作系统,需要底层内核的支持。

原文链接:
https://blog.csdn.net/qq_41051923/article/details/110082229

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值