Linux下的IO多路复用

文章目录

  • 一. IO的概念和分类
    • 1. IO操作的原理:
    • 二. I/O多路复用使用场景和作用
      • 1. 问题: 一台网络服务器需要接收100台客户端的连接和数据通信,应该如何设计和实现?
      • 2. I/O多路复用机制:
  • 三. Select poll epoll
    • select
    • poll
    • epoll
    • 比较

一. IO的概念和分类

1. IO操作的原理:

以一个进程的输入类型的IO调用为例,它将完成或引起如下工作内容:
1)用户进程向操作系统请求外部数据;
2)操作系统将外部数据加载到内核缓冲区
3)操作系统将数据从内核缓冲区拷贝到进程缓冲区
4)进程读取数据继续后面的工作
在这里插入图片描述

二. I/O多路复用使用场景和作用

1. 问题: 一台网络服务器需要接收100台客户端的连接和数据通信,应该如何设计和实现?

分析:
1).肯定不能一个进程或线程依次进行IO的处理,那么会出现阻塞等待某个IO的过程,此时就可能丢其他IO的数据;
2).可以使用多个线程,每个线程直跟踪处理一个IO通信,只有少量IO通信是可行的,如果有多个IO都是使用线程的话,由于线程的资源开销比较大,线程创建、释放和调度切换等操作都会大大的浪费CPU时间,降低系统资源和效率;
3).解决上面的问题的办法,内核提供了IO多路复用的机制,即下面3种:poll、select、epoll;

2. I/O多路复用机制:

  1. 通过一种事件机制,可以监视多个描述符,一旦某个描述符就绪(一般是可读或可写状态),能够通知应用程序进行相应的读写操作;
  2. 在多路复用IO模型中,会借助于内核的处理。一个内核线程不断地去轮询多个 socket 的状态,只有当真正读写事件发送时,才真正调用实际的IO读写操作。
  3. 在多路复用IO模型中,上层应用只需要使用一个线程就可以管理多个socket,不需要建立新的进程或者线程,也不必维护这些线程和进程,且只有真正有读写事件进行时才会使用IO资源,所以它大大减少来资源占用;
  4. 在多路复用IO模型中,应用层通常使用select/poll/epoll函数向系统内核发起调用,并阻塞在这几个系统函数的调用中,而不是阻塞于实际的IO操作;
  5. 在网络编程的过程中,以下几种情况需要使用I/O复用模型:
  6. 客户端要同时处理多路socket通信;
    客户端程序要同时处理用户交互式输入和网络套接口;
    TCP服务器要同时处理监听socket和连接socket,这种情况是I/O复用使用最多的一种情况。
    服务器要同时处理TCP请求和UDP请求;
    服务器要处理多个服务或多个协议,一般要使用I/O复用。

三. Select poll epoll

select

在这里插入图片描述

1.1 优点 select 其实就是把NIO中用户态要遍历的 fd 数组拷贝到了内核态,让内核态来遍历,因为用户态判断socket是否有数据还是要调用内核态的,所有拷贝到内核态后,这样遍历判断的时候就不用一直用户态和内核态频繁切换了
从代码中可以看出,select系统调用后,就会修改对应数据到达后的标记位,从而判断数据是否到达。之后把内核态的数据再返回到用户态。
1.2 存在的问题 1、bitmap最大1024位,一个进程最多只能处理1024个客户端 2、&rset不可重用,每次socket有数据就相应的位会被置位 3、文件描述符数组拷贝到了内核态,仍然有开销
4、select并没有通知用户态哪一个socket有数据,仍然需要O(n)的遍历

poll

[图片]

优点 1、poll使用pollfd数组来代替select中的bitmap,数组没有1024的限制,可以一次管理更多的client
2、当pollfds数组中有事件发生,相应的revents置位为1,遍历的时候又置位回0,实现了pollfd数组的重用 缺点 poll
解决了select缺点中的前两条,其本质原理还是select的方法,还存在select中原来的问题
1、pollfds数组拷贝到了内核态,仍然有开销 2、poll并没有通知用户态哪一个socket有数据,仍然需要O(n)的遍历

epoll

[图片]

一棵记录要监听的FD的红黑树和一个记录就绪FD的链表

1 事件通知机制 1、当有网卡上有数据到达了,首先会放到DMA(内存中的一个buffer,网卡可以直接访问这个数据区域)中
2、网卡向cpu发起中断,让cpu先处理网卡的事
3、中断号在内存中会绑定一个回调,哪个socket中有数据,回调函数就把哪个socket放入就绪链表中

2 详细过程

首先epoll_create创建epoll实例,它会创建所需要的红黑树,以及就绪链表,以及代表epoll实例的文件句柄,其实就是在内核开辟一块内存空间,所有与服务器连接的socket都会放到这块空间中,这些socket以红黑树的形式存在,同时还会有一块空间存放就绪链表;红黑树存储所监控的文件描述符的节点数据,就绪链表存储就绪的文件描述符的节点数据;
epoll_ctl添加新的描述符,首先判断是红黑树上是否有此文件描述符节点,如果有,则立即返回。如果没有,
则在树干上插入新的节点,并且告知内核注册回调函数。当接收到某个文件描述符过来数据时,那么内核将该节点插入到就绪链表里面。
epoll_wait将会接收到消息,并且将数据拷贝到用户空间,清空链表。

3 水平触发和边沿触发

Level_triggered(水平触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据一次性全部读写完(如读写缓冲区太小),那么下次调用
epoll_wait()时,它还会通知你在上没读写完的文件描述符上继续读写,当然如果你一直不去读写,它会一直通知你!!!如果系统中有大量你不需要读写的就绪文件描述符,而它们每次都会返回,这样会大大降低处理程序检索自己关心的就绪文件描述符的效率!!!
Edge_triggered(边缘触发):当被监控的文件描述符上有可读写事件发生时,epoll_wait()会通知处理程序去读写。如果这次没有把数据全部读写完(如读写缓冲区太小),那么下次调用epoll_wait()时,它不会通知你,也就是它只会通知你一次,直到该文件描述符上出现第二次可读写事件才会通知你!!!这种模式比水平触发效率高,系统不会充斥大量你不关心的就绪文件描述符!!!
4 优点 epoll是现在最先进的IO多路复用器,Redis、Nginx,linux中的Java NIO都使用的是epoll
1、一个socket的生命周期中只有一次从用户态拷贝到内核态的过程,开销小
2、使用event事件通知机制,每次socket中有数据会主动通知内核,并加入到就绪链表中,不需要遍历所有的socket

比较

  1. select:
    优点:目前几乎在所有的平台上支持,其具有良好的跨平台支持;
    缺点:
    1)单个进程能够监视的文件描述符的数量存在最大限制,在Linux上一般为1024, 可以通过修改宏定义甚至重新编译内核的方式提升这一限制,但 是这样也会造成效率的降低。
    2) 可读和可写的fdset分开管理和添加,比较麻烦。假设我们有一个文件描述符sockfd,如果我们要监听它的可读和可写,那么这个文件描述符就需要传入到两个fd_set中,再将两个fd_set传入到select中;
    2.poll:
    优点:
    1)poll克服了文件描述符数量的限制,但仍然存在一定的效率问题;
    2)解决了select中的第2个缺点;
    3)select监测的事件只有3种,而poll将监测事件细化了。
    缺点:select和poll采用的都是轮询检测的机制,即每次调用都要重复的将文件描述符传入到内核当中,这一点很大程度上降低了程序的运行效率;
  2. epoll:
    优点:
    1)监视的描述符数量不受限制,它所支持的FD上限是最大可以打开文件的数目;
    2)效率高;尤其适用于高并发场景;不同于select和poll轮询的方式,而是通过每个fd定义的回调函数来实现的;
    3)支持电平触发和边沿触发两种方式,理论上边缘触发的性能要更高一些,但是代码实现相当复杂;
    4)mmap加速内核与用户空间的信息传递。epoll是通过内核于用户空间mmap同一块内存,避免了无畏的内存拷贝。
    缺点:但仅能在Linux平台上可用,跨平台性差;

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

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

相关文章

【前端素材】推荐优质后台管理系统Modernize平台模板(附源码)

一、需求分析 后台管理系统是一种用于管理和控制网站、应用程序或系统后台操作的软件工具,通常由授权用户(如管理员、编辑人员等)使用。它提供了一种用户友好的方式来管理网站或应用程序的内容、用户、数据等方面的操作,并且通常…

光学3D表面轮廓仪微纳米三维形貌一键测量

光学3D表面轮廓仪(白光干涉仪)利用白光干涉原理,以0.1nm分辨率精准捕捉物体的表面细节,实现三维显微成像测量,被广泛应用于材料学领域的研究和应用。 了解工作原理与技术 材料学领域中的光学3D表面轮廓仪,也被称为白光干涉仪&am…

Mybatis框架相关问题(面试)

目录 1、什么是Mybatis? 2、Mybatis的优点 3、Mybatis的缺点 4、Mybatis框架的适用场合 5、#{}和${}的区别是什么 {}是预编译处理,${}是字符串替换。 6、实体类中的属性名和表中的字段名不一样,怎么办? 8、编写模糊查询like语句 9、…

【LV14 day9内核模块编译】

模块三要素: 入口函数 出口函数 module_license 一、内核模块基础代码解析 Linux内核的插件机制——内核模块 类似于浏览器、eclipse这些软件的插件开发,Linux提供了一种可以向正在运行的内核中插入新的代码段、在代码段不需要继续运行时也可以从内核…

常用的集合有哪些

常用的三大类集合:Set、List、Map。 1 Set 1) Set 集合属于单列集合,不允许包含重复元素; 2) 判断元素是否重复的标准为对象的 equals 方法,存在时返回 false,不存在返回 true; 3) 元素的排序规则,由相应的实现类决定,分为无序、元素大小排序、写入顺序排序; 4) 初始化…

SpringBoot -【SmartInitializingSingleton】基础使用及应用场景

SmartInitializingSingleton 在继续深入探讨 SmartInitializingSingleton接口之前,让我们先了解一下 Spring Framework 的基本概念和背景。Spring Framework 是一个开源的 JavaEE(Java Enterprise Edition)全栈(full-stack&#x…

力扣 724. 寻找数组的中心下标

思路: 创建两个变量sum和sum1,sum代表左边元素的和,sum1代表右边元素的和 然后假设从数组下标0开始,一直到最后一个作为中心下标 如果sumsum1,返回此时的中心下标 如果所有下标循环完了,发现没有return…

Apipost 数据模型功能API数据重复利用起来

在Apipost数据模型中用户可以预先创建多个数据模型,并在API设计过程中重复利用这些模型来构建API 创建数据模型 在左侧导航点击「数据模型」-「新建数据模型」在右侧工作台配置数据模型参数 引入数据模型 在API设计预定义响应期望下点击引用数据模型,…

Docker安装与基础知识

目录 -----------------Docker 概述--------------------------- 容器化越来越受欢迎,因为容器是: Docker与虚拟机的区别: Docker核心概念: ●镜像 ●容器 ●仓库 -----------------安装 Docker--------------------------…

操作系统——处理机调度

文章目录 进程调度0.概念1.调度分类高级调度低级调度中级调度七状态模型调度对比 2.进程调度进程调度的时机进程调度的方式进程的切换方式调度器/调度程序闲逛进程 3. 调度算法的评价指标CPU利用率系统吞吐量周转时间等待时间响应时间 4. 调度算法先来先服务(FCFS)短作业优先(S…

django rest framework 学习笔记-实战商城3

01用户模块模型定义_哔哩哔哩_bilibili 本博客借鉴至大佬的视频学习笔记 用户模块及商品数据表结构设计 from ckeditor.fields import RichTextField # pip install django-ckeditor from django.db import models# Create your models here. # from wx.richtext import Ri…

MATLAB环境下基于PSO-DBN-ELM方法的图像分类

在纯数据驱动的图像识别方法中,深度信念网络DBN识别模型具备较好的识别性能。对于DBN模型而言,可利用的数据越多,挖掘的信息也越多,建立的模型就越准确。然而DBN本身仍存在一定的不足之处,一方面由于DBN内部包含多层限…

servlet---->request.getHeader(“X-Requested-With“);有什么作用?

X-Requested-With 是一个自定义的HTTP请求头,主要用于在服务器端识别请求是由Ajax技术发起的还是由其他技术发起的。这个请求头是由浏览器或客户端应用程序添加的,因此其值可能取决于发送请求的客户端或者开发者的选择。 如果请求不是通过JavaScript的 …

微信小程序支付(前后端都包含)

Java中换取微信支付唯一订单号(用于换取支付窗口) /*** 微信小程序支付*/PostMapping(value "/xcxPay")ResponseBodypublic Map<String,Object> miniAppPay(RequestBody byte[] req) {HashMap<String, Object> objectObjectMap new HashMap<>();…

【软件测试】--功能测试1

一、测试介绍 什么是软件&#xff1f; 控制计算机硬件工作的工具。 什么是软件测试&#xff1f; 使用技术手段验证软件是否满足需求 软件测试的目的&#xff1f; 减少软件缺陷&#xff0c;保证软件质量。 测试主流技能 1、功能测试 2、自动化测试 3、接口测试 4、性能测试 ​…

MySQL-事务,properties文件解析,连接池

1.事务机制管理 1.1 Transaction事务机制管理 默认情况下是执行一条sql语句就保存一次&#xff0c;那么比如我们需要三条数据同时成功或同时失败就需要开启事务机制了。开启事务机制后执行过程中发生问题就会回滚到操作之前&#xff0c;相当于没有执行操作。 1.2 事务的特征 事…

【初始RabbitMQ】延迟队列的实现

延迟队列概念 延迟队列中的元素是希望在指定时间到了之后或之前取出和处理消息&#xff0c;并且队列内部是有序的。简单来说&#xff0c;延时队列就是用来存放需要在指定时间被处理的元素的队列 延迟队列使用场景 延迟队列经常使用的场景有以下几点&#xff1a; 订单在十分…

Anaconda下安装torch-geometric

主要流程参考&#xff1a;https://blog.csdn.net/weixin_45671036/article/details/130617637 https://blog.csdn.net/weixin_43756314/article/details/130225038?ops_request_misc&request_id&biz_id102&utm_term%E5%80%9F%E5%8A%A9anaconda%20%E5%AE%89%E8%A3%…

配置vscode,使其可以运行C++11特性的代码(如vector)

配置vscode&#xff0c;使其可以运行C11特性的代码 封面引用自配置教程的B站视频&#xff0c;非常详细的视频&#xff0c;感谢视频作者的贡献。 文章目录 配置vscode&#xff0c;使其可以运行C11特性的代码Step 1: 基础配置Step 2: 调整Code Runner的配置Step 3: 更改tasks.jso…

【Spring连载】使用Spring Data的Repositories----定义Repository接口

【Spring连载】使用Spring Data的Repositories----定义Repository接口 一、微调Repository定义二、使用多个Spring Data模块的Repositories 要定义repository接口&#xff0c;首先需要定义特定于域&#xff08;domain&#xff09;类的repository接口。接口必须继承Repository&a…