面试官:谈谈你对IO多路复用的理解?

简介: 面试官:谈谈你对IO多路复用的理解?

“IO 多路复用”是编程中常见的技术词汇,使用这种技术的框架有很多,如,Redis、Kafka、Netty、Nginx 中都用到了此技术。那问题来了,什么是 IO 多路复用?它的具体实现技术有哪些?这些技术之间有什么区别?今天我们就来简单的探讨一下。

1.什么是IO多路复用?

IO 多路复用技术是一种允许单个线程管理多个网络连接的技术,它使得服务器能够高效地处理大量的并发连接而不需要为每个连接创建一个独立的线程或进程。

想象如果客户端有成千上万个的情况下,那么非 IO 多路复用就会有成千上万个线程,那么就会发生 IO 过度争抢和多线程切换的问题,因为 CPU 资源只有几个,而要执行的线程却有成千上万个。

2.IO多路复用技术实现

常用的 IO 多路复用实现技术有:select、poll、epoll 和 kqueue 等,它们的具体介绍如下。

2.1 select

  • 特点:select 是最早出现的一种多路复用 I/O 模型,几乎在所有平台上都有支持。它通过一个调用来监视多个文件描述符,等待其中任何一个变为可读或可写状态。
  • 局限性
    • 文件描述符数量受限:通常限制为 1024 个,可以通过修改系统参数来增加这个限制,但这样做会消耗更多的系统资源。
    • 效率低下:每次调用 select 都需要将文件描述符列表复制到内核,检查完后又需要复制回用户空间,这对于大量文件描述符来说效率很低。
    • 不支持边缘触发模式:只支持水平触发模式。

边缘触发模式 VS 水平触发模式

  1. 边缘触发模式:当一个文件描述符从不可读(或不可写)变为可读(或可写)时,内核仅通知应用程序一次。如果应用程序未能立即处理完所有可用的数据(例如,缓冲区中的数据未完全读取),那么即使文件描述符仍然是可读的,内核也不会再次通知应用程序,直到该文件描述符的状态再次发生变化(例如,从可读变为不可读,再变回可读)。
    1. 优点:减少了系统调用次数,提高了效率,特别适合于大数据量传输的场景。
    2. 缺点:要求应用程序必须在接收到事件后尽可能多地读取或写入数据,否则可能会错过后续的数据。因此,边缘触发模式对编程的要求较高,需要更加小心地处理。
  2. 水平触发模式:在水平触发模式下,只要文件描述符处于可读(或可写)状态,无论之前是否已经通知过,内核都会持续通知应用程序。这意味着,如果应用程序未能一次性处理完所有数据,只要文件描述符仍然处于可读或可写状态,内核就会继续发送通知。
    1. 优点:编程较为简单,因为即使错过了某个事件的通知,只要文件描述符的状态没有改变,应用程序仍然有机会在下一次轮询时接收到同样的事件。
    2. 缺点:可能造成更多的系统调用,因为即使数据已经被部分处理,内核仍然会不断地通知应用程序,这可能导致效率降低。

2.2 poll

  • 特点:poll 在功能上与 select 非常相似,但没有文件描述符数量的限制。poll 使用一个 pollfd 结构体数组来表示要监听的文件描述符集合。
  • 局限性:虽然解决了 select 的文件描述符数量限制问题,但在性能上仍然存在类似 select 的问题,即每次调用都需要复制文件描述符列表到内核,并且返回时也需要复制回用户空间。

2.3 epoll

  • 特点:epoll 是 Linux 特有的高效 IO 多路复用技术,它克服了 select 和 poll 的所有缺点。epoll 使用三个系统调用来管理文件描述符:epoll_create 创建一个 epoll 实例,epoll_ctl 添加/删除需要监听的文件描述符,epoll_wait 等待事件的发生。
  • 优势
    • 无数量限制:没有文件描述符数量限制。
    • 高效:只有活跃的文件描述符才会被传递给用户空间,减少了不必要的复制操作。
    • 功能强大:支持边缘触发和水平触发两种工作模式。

2.4 kqueue

  • 特点:kqueue 是 FreeBSD 操作系统引入的一种 IO 多路复用技术,后来也被 Mac OS X 和其他基于 BSD 的操作系统采用。kqueue 可以同时处理多种类型的事件,包括但不限于文件描述符事件、信号事件等。
  • 优势
    • 功能更强大:不仅支持文件描述符的事件通知,还能处理其他类型的事件。
    • 性能优秀:与 epoll 类似,只有活跃的文件描述符才会被处理,从而提高了效率。

3.区别对比

select、poll、epoll 和 kqueue 之间的区别如下:

技术名称 支持平台 连接数限制 IO效率 数据拷贝方式
select 跨平台 默认1024 O(N) 每次调用都拷贝
poll 跨平台 O(N) 每次调用都拷贝
epoll Linux 特有 O(1) 仅在 epoll_ctl 时拷贝
kqueue MacOS、FreeBSD 等 O(1) 具体实现方式可能因系统而异,但通常也是高效的。

课后思考

什么叫做“文件描述符”?IO 多路复用为什么要进行“数据拷贝”?

本文已收录到我的面试小站 www.javacn.site,其中包含的内容有:Redis、JVM、并发、并发、MySQL、Spring、Spring MVC、Spring Boot、Spring Cloud、MyBatis、设计模式、消息队列等模块。

相关文章
|
22天前
|
网络协议 安全 Linux
Linux C/C++之IO多路复用(select)
这篇文章主要介绍了TCP的三次握手和四次挥手过程,TCP与UDP的区别,以及如何使用select函数实现IO多路复用,包括服务器监听多个客户端连接和简单聊天室场景的应用示例。
75 0
|
22天前
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
59 1
Linux C/C++之IO多路复用(aio)
|
4月前
|
存储 缓存 NoSQL
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
redis分布式锁、redisson、可重入、主从一致性、WatchDog、Redlock红锁、zookeeper;Redis集群、主从复制,全量同步、增量同步;哨兵,分片集群,Redis为什么这么快,I/O多路复用模型——用户空间和内核空间、阻塞IO、非阻塞IO、IO多路复用,Redis网络模型
Redis常见面试题(二):redis分布式锁、redisson、主从一致性、Redlock红锁;Redis集群、主从复制,哨兵模式,分片集群;Redis为什么这么快,I/O多路复用模型
|
3月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
22天前
|
Linux C++
Linux C/C++之IO多路复用(poll,epoll)
这篇文章详细介绍了Linux下C/C++编程中IO多路复用的两种机制:poll和epoll,包括它们的比较、编程模型、函数原型以及如何使用这些机制实现服务器端和客户端之间的多个连接。
19 0
Linux C/C++之IO多路复用(poll,epoll)
|
25天前
|
Java Linux
【网络】高并发场景处理:线程池和IO多路复用
【网络】高并发场景处理:线程池和IO多路复用
36 2
|
27天前
|
监控 网络协议 Java
IO 多路复用? 什么是 IO 多路复用? 简单示例(日常生活)来解释 IO 多路复用 一看就懂! 大白话,可爱式(傻瓜式)教学! 保你懂!
本文通过日常生活中的简单示例解释了IO多路复用的概念,即一个线程通过监控多个socket来处理多个客户端请求,提高了效率,同时介绍了Linux系统中的select、poll和epoll三种IO多路复用的API。
58 2
|
2月前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
2月前
|
网络协议 Java Linux
高并发编程必备知识IO多路复用技术select,poll讲解
高并发编程必备知识IO多路复用技术select,poll讲解
|
4月前
|
存储 Java Unix
(八)Java网络编程之IO模型篇-内核Select、Poll、Epoll多路复用函数源码深度历险!
select/poll、epoll这些词汇相信诸位都不陌生,因为在Redis/Nginx/Netty等一些高性能技术栈的底层原理中,大家应该都见过它们的身影,接下来重点讲解这块内容。