io多路复用:select、poll和epoll

1、为什么使用多路复用:

     1.1单线程BIO监听socket

        多路复用一般用于网络io当中,提到网络io我们肯定能想到socket。如果我们想要一个线程单纯的用向下文的方式监听很多个socket看他是否有事件发生,那这样是不可行。

但上一个socket1没有可读事件时会阻塞,则此时socket2有可读事件也无法读取到。 

    1.2多线程监听socket

        如果使用多线程监听socket的话,每来一个连接就创建一个新的线程,那这种方法光听着就效率低下,因为线程之间的切换是要消耗资源的。线程过多导致线程切换频繁,效率低。

     1.3多路复用机制的诞生

        多路复用其实就是使用一个线程监听多个socket,那为什么现在不会出现前面讲的那个单线程问题呢,因为现在这个线程只是监听是否有io事件发生,并不真正的进行读取。再Linux系统中每一个socket就是一个文件,每个文件由唯一一个文件描述符表示。当这个多路复用器想要监听放入到一个集合当中,当有事件发生时会将有事件发生的文件描述符特殊标记,表示它有事件发生,然后再将这个io事件分发给真正做事的线程去完成。所以复用是复用再事件的检测方面。让事件检测和事件处理进行解耦。

2、多路复用器的类别及说明

        多路复用器有三中,分别为select、poll和epoll。现在大部分使用的都是epoll。如redis使用的就是epoll。

     2.1 select(假设只检测可读事件):

        select实现多路复用的方式就是想要监听的Socket放入到一个fds(文件描述符集合)当中。它会先把这个集合拷贝到内核空间当中,然后遍历fds看看里面有没有可读事件,如果没有的话会进行阻塞,直至有可读事件发生,当有可读事件发生时(超过超时时间也会停止阻塞),线程会被唤醒并再遍历一遍将可读事件给进行标记。此时将这个集合再次拷贝从内核到用户态。然后用户监听要再次遍历这个集合将其有可读事件的socket找出来然后仍给工作线程进行处理。

        select使用的时固定长度的BitsMap来作为fds。所以说它可监听的socket是有限制的,在Liunx当中默认最多监听1024个socket文件。

从上面的描述当中我们可以看到select有着一些明显的缺点。例如:它使用的是固定长度的BItsMap来作为fds,导致所监听的socket文件数量有限制。还有我们可以看到这个监听的过程中有着两次的fds的拷贝,当次数、数量多起来后这也是性能的一大痛点。还有他对于查询有可读事件的时候要线性遍历fds,返回到用户态时用户还得再次线性遍历一次,查出哪些具有可读状态。

    2.2poll

        poll其实和select没有太大的区别,它两唯一大的区别就是poll改用动态数组来作为fds(文件描述符集合)。这样就解决了select在监听数量上的限制了,但在效率方面并没有改进,还是需要进行拷贝和线性遍历。

    2.3 epoll(相较于前两个效率有了很大的提升)

        这个就是epoll的结构。首先我们需要使用epoll_create方法在内核当中创建epoll对象。再epoll对象中有一个红黑树。这个红黑树的作用就相当于fds(文件描述符集合)。再这颗树上存着要检测的socket文件。再之前的select/poll中是没有再内核中专门创建存放fds的空间的,导致每次调用都要将fds拷贝一遍到内核当中。而此时epoll使用红黑树将fds一直存在内核当中,不再需要每次进行拷贝,当需要增加新的带检测的socket时直接调用epoll_ctl进行添加就行,时间复杂度为(logn)。

        对于事件的检测epoll使用了事件驱动,也就是当某个socket有事件发生时,内核会有回调方法将其加入到就绪队列当中。这个就绪队列就是记录被检测socket中有事件发生的socke。此时我们不需要进行遍历所有socket查询是哪个socket具有事件。

        当我们调用epoll_waitl方法时,它的第二个参数是一个epoll_even结构数组指针,当有就绪链表不为空时,就会将链表链表复制到这个数组当中,返回值为一个数值,表示有多少个事件发生。此时可以通过操作这个数组直接进行数值处理,不用遍历一整个fds。

3、总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/194804.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos7 探测某个tcp端口是否在监听

脚本 nc -vz 192.168.3.128 60001 if [ $? -eq 0 ]; thenecho "tcp succeed" elseecho "tcp failed" fi nc -vz 192.168.3.128 60001 探测192.168.3.128服务器上60001 tcp端口, -vz说明是探测TCP的 端口开启的情况 执行脚本 端口禁用情况 执行脚本

Jmeter——循环控制器中实现Counter计数器的次数重置

近期在使用Jmeter编写个辅助测试的脚本,用到了多个Loop Controller和Counter。 当时想的思路就是三个可变的数量值,使用循环实现;但第三个可变值的数量次数,是基于第二次循环中得到的结果才能确认最终次数,每次的结果…

java拼图游戏(待优化)

启动类 package com.yx.ui;public class App { //启动入口public static void main(String[] args) {//如果想要开启一个界面,就创建谁的对象 // new DengJFrame(); // new ZCJFrame();new GameJFrame();}}游戏类 package com.yx.ui;import java.awt.event.KeyEv…

Azure Machine Learning - Azure AI 搜索中的集成数据分块和嵌入

在基于索引器的索引编制中,Azure AI _集成矢量化_将数据分块和文本到矢量嵌入添加到技能中,它还为查询添加文本到矢量的转换。 关注TechLead,分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验,同济本…

系列十二、强引用、软引用、弱引用、虚引用分别是什么?

一、整体架构 二、强引用(默认支持模式) 2.1、概述 当内存不足时,JVM开始垃圾回收,对于强引用的对象,就算是出现了OOM也不会对该对象进行回收,死都不收。 强引用是我们最常见的普通对象引用,只…

LeetCode【36】有效的数独

题目: 思路: https://blog.51cto.com/u_15072778/3788083 代码: public boolean isValidSudoku(char[][] board) {// 二维数组第一个标识 0-9行,第二个表示 0-9数字,存的内容boolean 表示第0-9行,0-9这些…

【React】React 基础

1. 搭建环境 npx create-react-app react-basic-demo2. 基本使用 JSX 中使用 {} 识别 JavaScript 中的表达式,比如变量、函数调用、方法调用等。 if、switch、变量声明等属于语句,不是表达式。 列表渲染使用 map 。 事件绑定用;on 事件名称…

三栏布局,中间自适应

方法一&#xff1a;两边使用float 中间使用margin 方法二&#xff1a;两边使用absolute 中间使用margin 方法三&#xff1a;flex 布局 方法四&#xff1a;grid 布局 方法一&#xff1a;相关HTML代码【两边使用float 中间使用margin】 <div class"container"…

中间件安全: Apache 远程代码执行 (CVE-2021-42013)

中间件安全&#xff1a; Apache 远程代码执行 &#xff08;CVE-2021-42013&#xff09; Apache HTTP Server是美国阿帕奇&#xff08;Apache&#xff09;基金会的一款开源网页服务器。该服务器具有快速、可靠且可通过简单的API进行扩充的特点&#xff0c;发现 Apache HTTP Ser…

[原创]解决老款AMD CPU在Win10/Win11无故重启的问题.

[简介] 常用网名: 猪头三 出生日期: 1981.XX.XXQQ: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共22年] 职业生涯: 20年 开发语言: C/C、80x86ASM、PHP、Perl、Objective-C、Object Pascal、C#、Python 开发工具: Visual Studio、Delphi、XCode、Eclipse、C Bui…

kaggle新赛:SenNet 3D肾脏分割大赛(3D语义分割)

赛题名称&#xff1a;SenNet HOA - Hacking the Human Vasculature in 3D 赛题链接&#xff1a;https://www.kaggle.com/competitions/blood-vessel-segmentation 赛题背景 目前&#xff0c;人类专家标注员需要手动追踪血管结构&#xff0c;这是一个缓慢的过程。即使有专家…

分组交换技术

目录 一、新型计算机网络的基本特点 二、电路交换 1、回顾电路交换的原理 2、使用交换机连接许多部电话 3、电路交换举例 4、电路交换的三个阶段 5、电路交换的特点 三、分组交换 1、因特网有边缘部分与核心部分组成 2、分组交换的原理 3、分组交换的优点 4、存储转…