IO多路复用模型(Select、Poll、Epoll )

2024-05-26 19:32

本文主要是介绍IO多路复用模型(Select、Poll、Epoll ),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们之前采用的多进程方式实现的服务器端,一次创建多个工作子进程来给客户端提供服务。其实这种方式是存在问题的。

可以打个比方:如果我们先前创建的几个进程承载不了目前快速发展的业务的话,是不是还得增加进程数?我们都知道系统创建进程是需要消耗大量资源的,所以这样就会导致系统资源不足的情况。

那么有没有一种方式可以让一个进程同时为多个客户端端提供服务?

接下来要讲的IO复用技术就是对于上述问题的最好解答。

对于IO复用,我们可以通过一个例子来很好的理解它。(例子来自于《TCP/IP网络编程》)

某教室有10名学生和1名老师,这些学生上课会不停的提问,所以一个老师处理不了这么多的问题。那么学校为每个学生都配一名老师,也就是这个教室目前有10名老师。此后,只要有新的转校生,那么就会为这个学生专门分配一个老师,因为转校生也喜欢提问题。如果把以上例子中的学生比作客户端,那么老师就是负责进行数据交换的服务端。则该例子可以比作是多进程的方式。后来有一天,来了一位具有超能力的老师,这位老师回答问题非常迅速,并且可以应对所有的问题。而这位老师采用的方式是学生提问前必须先举手,确认举手学生后在回答问题。则现在的情况就是IO复用。

目前的常用的IO复用模型有三种: select,poll,epoll

 

IO复用

目前的常用的 IO 复用模型有三种:select、poll、epoll。

I/O 多路复用就是通过一种机制,一个进程可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作。但 select、poll、epoll 本质上都是同步 I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步 I/O 则无需自己负责进行读写,异步 I/O 的实现会负责把数据从内核拷贝到用户空间。

jdk1.4 是使用的 select/poll 模型,jdk1.5 以后把 select/poll 改为了 epoll 模型。

 

select模型

说的通俗一点就是各个客户端连接的文件描述符也就是套接字,都被放到了一个集合中,调用select函数之后会一直监视这些文件描述符中有哪些可读,如果有可读的描述符那么我们的工作进程就去读取资源。PHP 中有内置的函数来完成 select 系统调用。

我们在 select 函数中告诉内核需要监听的不同状态的文件描述符以及能接受的超时时间,函数会返回所有状态下就绪的描述符的个数,并且可以通过遍历 fdset,来找到就绪的文件描述符。

存在的问题:

  • 每次调用 select,都需要把待监控的 fd 集合从用户态拷贝到内核态,当 fd 很大时,开销很大。
  • 每次调用 select,都需要轮询一遍所有的 fd,查看就绪状态。这个开销在 fd 很多时也很大。
  • select 支持的最大文件描述符数量有限,默认是 1024。

 

poll模型

poll 和 select 的实现非常类似,本质上的区别就是存放 fd 集合的数据结构不一样。 select 在一个进程内可以维持最多 1024 个连接,poll 在此基础上做了加强,可以维持任意数量的连接。

但 select 和 poll 方式有一个很大的问题就是,我们不难看出来 select 是通过轮训的方式来查找是否可读或者可写,打个比方,如果同时有100万个连接都没有断开,而只有一个客户端发送了数据,所以这里它还是需要循环这么多次,造成资源浪费。

所以后来出现了 epoll 系统调用。

 

epoll模型

epoll 在 Linux2.6 内核正式提出,是基于事件驱动的 I/O 方式。,相对于 select 来说,epoll 没有描述符个数限制,使用一个文件描述符管理多个描述符,将用户关心的文件描述符的事件存放到内核的一个事件表中,这样在用户空间和内核空间的 copy 只需一次(可以理解为一块公共内存,该内存既不属于用户态也不属于内核态)。

epoll 是 select 和 poll 的增强版,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统 CPU 利用率。原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核 IO 事件异步唤醒而加入 Ready 队列的描述符集合就行了。

epoll是基于内核的反射机制,在有活跃的 socket 时,系统会调用我们提前设置的回调函数。而 poll 和 select 都是遍历。

epoll 的好处:

  • 避免内存级拷贝;
  • 事件驱动(不是轮询);

但是也并不是所有情况下 epoll 都比 select/poll 好,比如在如下场景:

在大多数客户端都很活跃的情况下,系统会把所有的回调函数都唤醒,所以会导致负载较高。既然要处理这么多的连接,那倒不如 select 遍历简单有效。

 

select,poll,epoll的区别

selectpollepoll(基于事件驱动)
操作方式遍历遍历回调
底层实现数组链表红黑树
IO效率每次调用都进行线性遍历,时间复杂度为O(n)每次调用都进行线性遍历,时间复杂度为O(n)事件通知方式,每当fd就绪,系统注册的回调函数就会被调用,将就绪fd放到readyList里面,时间复杂度O(1)
最大连接数1024(x86)或2048(x64)无上限无上限
fd拷贝每次调用select,都需要把fd集合从用户态拷贝到内核态每次调用poll,都需要把fd集合从用户态拷贝到内核态调用epoll_ctl时拷贝进内核并保存,之后每次epoll_wait不拷贝

epoll是Linux目前大规模网络并发程序开发的首选模型。在绝大多数情况下性能远超select和poll。目前流行的高性能web服务器Nginx正式依赖于epoll提供的高效网络套接字轮询服务。但是,在并发连接不高的情况下,多线程+阻塞I/O方式可能性能更好。

表面上看epoll的性能最好,但是在连接数少并且连接都十分活跃的情况下,select和poll的性能可能比epoll好,毕竟epoll的通知机制需要很多函数回调。

 

select机制的问题

  • 每次调用select,都需要把fd_set集合从用户态拷贝到内核态,如果fd_set集合很大时,那这个开销也很大
  • 同时每次调用select都需要在内核遍历传递进来的所有fd_set,如果fd_set集合很大时,那这个开销也很大
  • 为了减少数据拷贝带来的性能损坏,内核对被监控的fd_set集合大小做了限制,并且这个是通过宏控制的,大小不可改变(限制为1024)

 

References

  • 一次读懂 Select、Poll、Epoll IO复用技术
  • IO 多路复用是什么意思?
  • IO多路复用模型(select ,poll,epoll)
  • IO多路复用的三种机制Select,Poll,Epoll
  • 五种网络IO模型和select/epoll对比

这篇关于IO多路复用模型(Select、Poll、Epoll )的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1005381

相关文章

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

本地私有化部署DeepSeek模型的详细教程

《本地私有化部署DeepSeek模型的详细教程》DeepSeek模型是一种强大的语言模型,本地私有化部署可以让用户在自己的环境中安全、高效地使用该模型,避免数据传输到外部带来的安全风险,同时也能根据自... 目录一、引言二、环境准备(一)硬件要求(二)软件要求(三)创建虚拟环境三、安装依赖库四、获取 Dee

DeepSeek模型本地部署的详细教程

《DeepSeek模型本地部署的详细教程》DeepSeek作为一款开源且性能强大的大语言模型,提供了灵活的本地部署方案,让用户能够在本地环境中高效运行模型,同时保护数据隐私,在本地成功部署DeepSe... 目录一、环境准备(一)硬件需求(二)软件依赖二、安装Ollama三、下载并部署DeepSeek模型选

SQL Server使用SELECT INTO实现表备份的代码示例

《SQLServer使用SELECTINTO实现表备份的代码示例》在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误,在SQLServer中,可以使用SELECTINT... 在数据库管理过程中,有时我们需要对表进行备份,以防数据丢失或修改错误。在 SQL Server 中,可以使用 SE

Golang的CSP模型简介(最新推荐)

《Golang的CSP模型简介(最新推荐)》Golang采用了CSP(CommunicatingSequentialProcesses,通信顺序进程)并发模型,通过goroutine和channe... 目录前言一、介绍1. 什么是 CSP 模型2. Goroutine3. Channel4. Channe

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt