理解IO复用的三种模式——select、poll、epoll

news2024/11/25 7:40:14

文章目录

    • 一、Select
      • 1、select简介
      • 2、select实现原理
      • 3、select编程
      • 4、select常见问题
    • 二、poll
      • 1、poll简介
      • 2、poll实现原理
      • 3、poll编程
      • 4、poll常见问题
    • 三、epoll
      • 1、epoll简介
      • 2、epoll实现原理
      • 3、epoll编程
      • 4、epoll常见问题

Linux IO模型是指Linux操作系统中用于实现输入输出的一种机制。
Linux IO模型主要分为五种:阻塞IO、非阻塞IO、IO复用、信号驱动IO和异步IO。

  • 阻塞IO是最常见的IO模型,当用户进程发起一个IO请求后,内核会一直等待,直到IO操作完成并返回结果。在此期间,用户进程会被阻塞,无法进行其他操作。
  • 非阻塞IO是在阻塞IO的基础上进行改进的一种IO模型。当用户进程发起一个IO请求后,内核会立即返回一个错误码,表示IO操作还未完成。用户进程可以继续进行其他操作,随后再通过轮询的方式来查询IO操作是否完成。
  • IO复用是指通过select、poll、epoll等系统调用来监听多个文件描述符的IO事件。当某个文件描述符就绪时,内核会通知用户进程进行IO操作。相比于阻塞IO和非阻塞IO,IO复用可以同时监听多个文件描述符,提高了IO效率。
  • 信号驱动IO是指用户进程通过signal或sigaction系统调用来注册一个信号处理函数,当IO操作完成时,内核会向用户进程发送一个SIGIO信号,用户进程在信号处理函数中进行IO操作。相比于阻塞IO和非阻塞IO,信号驱动IO可以避免用户进程被阻塞,提高了IO效率。
  • 异步IO是指当用户进程发起一个IO请求后,内核会立即返回,表示IO操作已经开始。当IO操作完成后,内核会通知用户进程,用户进程在此时才进行IO操作。相比于其他IO模型,异步IO可以避免用户进程被阻塞,提高了IO效率。

本篇文章要学习的是IO复用的三种模式。

  • select、poll、epoll三种IO复用模式对比
对比项selectpollepoll
事件对象存储方式位图链表+数组红黑树
底层实现轮询:每次调用需要从内存拷贝全部事件到用户空间轮询:每次调用需要从内存拷贝全部事件到用户空间回调通知方式,每次调用只需从内存拷贝就绪事件到用户空间
最大连接数1024理论上无上限(由系统资源池决定)理论上无上限(由系统资源池决定)
是否适用于高并发场景否。随着连接数增加,性能线性下降。否。随着连接数增加,性能线性下降。是。随着连接数增加,性能无明显递减。
编程难度
  • epoll机制效率高,适用于高并发场景,所以epoll机制广泛用于各种开源项目。
  • select机制编程简单,如果对高并发没有需求,那么很多人会选择select机制做多路IO请求处理。
  • poll机制既没有高并发能力,编程也并不简单,所以使用场景比较少。

彻底弄懂IO:https://blog.csdn.net/qq_41822345/article/details/124653958
相关链接1:https://mp.weixin.qq.com/s/ZuqW-SCPZpydjYTl6EvL8g
相关链接2:https://mp.weixin.qq.com/s/BFbnF1YU1jJXHjc7zYT18w
相关链接3:https://mp.weixin.qq.com/s/Tmr49E8vya1cK4un2OXmQQ
相关链接4:https://mp.weixin.qq.com/s/2jlr4BvUlLHBbyDu672PMg

一、Select

1、select简介

  • 概念:select机制是一种I/O多路复用技术,它可以同时监视多个文件描述符,当某个文件描述符就绪(一般是读写就绪)时,就会通知程序进行相应的操作。

  • 优点:select机制的优点是可以同时处理多个连接,避免了大量的线程或进程切换,提高了系统的并发性能。

2、select实现原理

在Linux系统中,select机制可以通过select函数来实现。select函数的参数包括需要监视的文件描述符集合、超时时间等。当select函数返回时,程序可以通过遍历文件描述符集合来确定哪些文件描述符已经就绪,然后进行相应的操作。

  • 下面这张原理图把select主要活动轨迹都进行了描述。

在这里插入图片描述

  • select核心实现原理是位图,select总共有三种位图,分别为读,写,异常位图,用户程序预先将socket文件描述符注册至读,写,异常位图,然后通过select系统调用轮询位图中的socket的读,写,异常事件。

    • select位图为1024比特位图,通过整型数组模拟而成。
    • select位图数组长度为16,每个数组元素为8字节,一个字节为8比特,位图大小=16 * 8 * 8 = 1024比特。
    • select位图每个比特对应一个文件描述符数值。
  • select底层通过轮询方式获取读,写,异常位图中注册的socket文件事件,如果检测到有socket文件处于就绪状态,则会将socket对应的事件设置到输出位图,等所有位图中的socket都被轮询完,会统一将输出位图通过copy_to_user函数复制到输入位图,并且覆盖掉输入位图注册信息(也就是用户初始化的位图被内核修改)。

  • select轮询完所有位图,如果未检测到任何socket文件处于就绪状态,根据超时时间确定是否返回或者阻塞进程。

  • socket检测到读,写,异常事件后,会通过注册到socket等待队列的回调函数poll_wake将进程唤醒,唤醒的进程将再次轮询所有位图。

  • select返回时会将剩余的超时时间通过copy_to_user覆盖原来的超时时间。

3、select编程

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
## 功能:
select函数是Linux系统中的一种I/O多路复用机制,它可以同时监视多个文件描述符。
## 参数:
nfds:最大文件描述符+1。
readfds:读文件描述符集合,可设置为NULL。
writefds:写文件描述符集合,可设置为NULL。
exceptfds:异常文件描述符集合,可设置为NULL。
timeout:超时时间,设置为NULL为阻塞模式,
## 返回值:
成功:返回检测到的文件描述符数量。
失败:返回-1,设置errno。
超时:返回0
  • select编码流程

在这里插入图片描述

4、select常见问题

问题1:select函数最大文件描述(maxfd)有什么作用?

  • select使用1024比特位图监测最多1024个文件描述符,然而实际的情况很少会到达1024文件描述符上限,使用maxfd可以避免每次都轮询1024个文件描述符,从而提高轮询效率。
  • maxfd通常设置为已打开最大文件描述符+1,目的是为了保证位图中每个文件描述符都被轮询到。

问题2:select优缺点有哪些?

优点:

  • select支持多种文件描述符类型,包括socket、标准输入输出、管道、FIFO等。
  • select是跨平台的,可以在多种操作系统上使用。

缺点:

  • select的效率不高,每次调用select都需要将所有的文件描述符从用户态复制到内核态,这个过程比较耗时。
  • select返回后需要遍历所有的文件描述符,找到就绪的文件描述符,这个过程也比较耗时。
  • select支持的文件描述符数量有限,通常是1024个。

问题3:select为什么会有1024文件描述符限制?

  • 进程默认打开最大文件描述符为1024(次要原因)。
  • select采用轮询的方式获取读,写,异常事件,如果需要轮询的文件描述符比较多的话,select执行效率会非常低(个人观点)。
  • select是通过一个整型数组来模拟位图,整型数组长度和元素大小已经固定,只能模拟出1024比特位图,使用select如果超过1024文件描述符的限制,可能会导致内存越界和其他未知问题(真正原因)。

问题4:select有哪些设计缺陷?

  • select最大文件描述符为1024,所以无法满足高并发应用场景,高并发场景请使用epoll机制。
  • select采用轮询的方式获取读,写,异常事件,轮询的方式效率低,不管文件事件是否就绪,都需要去做检测。
  • select位图设置和获取采用覆盖方式,用户输入的读,写,异常位图会被内核修改,编程非常容易出错,可参考select实现原理图分析,所以每次调用select之前都要重新设置位图。
  • select执行完后会返回剩余超时时间,剩余超时时间会覆盖原来的超时时间,导致超时机制异常。可参考select实现原理图分析,所以每次调用select之前都要重新设置超时时间。

二、poll

epoll机制效率高,适用于高并发场景,所以epoll机制广泛用于各种开源项目。

select机制编程简单,如果对高并发没有需求,那么很多人会选择select机制做多路IO请求处理。

poll机制既没有高并发能力,编程也并不简单,所以使用场景比其它两种要少。

1、poll简介

  • 概念:poll是一种I/O多路复用机制,它可以同时监视多个文件描述符,当其中任意一个文件描述符就绪时,就会通知程序进行相应的读写操作。
  • poll机制与select机制类似,但是poll没有最大文件描述符数量的限制,因此在文件描述符数量较大时,poll的效率会更高。

2、poll实现原理

poll机制的使用需要调用系统调用poll()函数,该函数会阻塞进程直到有文件描述符就绪或者超时。
poll()函数的参数是一个pollfd结构体数组,每个结构体中包含了一个文件描述符和该文件描述符所关注的事件类型。

  • 下面这张原理图把poll主要活动轨迹都进行了描述。

在这里插入图片描述

  • 用户将想要监听的socket文件绑定struct pollfd对象,并注册监听事件至struct pollfd对象events成员,监听多个socket文件使用struct pollfd数组。
  • 用户通过struct pollfd数组注册poll事件至poll_list链表,poll_list链表单个元素可以存储固定数量的struct pollfd对象。
  • poll系统调用采用轮询方式获取socket事件信息,一次poll调用需完成整个poll_list链表轮询工作,轮询socket的过程中会创建socket等待队列项,并加入socket等待队列(用于socket唤醒进程)。如果检测到socket处于就绪状态,将socket事件保存在struct pollfd对象的revents成员。
  • poll系统调用完成一次轮询后,如果检测到有socket处于就绪状态,则将poll_list链表所有的struct pollfd通过copy_to_user拷贝至用户struct pollfd数组。如果未检测到有socket处于就绪状态,根据超时时间确定是否返回或者阻塞进程。
  • socket检测到读,写,异常事件后,会通过注册到socket等待队列的回调函数poll_wake将进程唤醒,唤醒的进程将再次轮询poll_list链表。

3、poll编程

int poll(struct pollfd *fds, nfds_t nfds, int timeout);
## 功能:
poll函数是Linux系统中的一种I/O多路复用机制,它可以同时监视多个文件描述符。
## 参数:
fds:监听事件结构体数组。【这个结构体包含三个属性:1、fd: 监听文件描述符。2、events:监听事件集合,用于注册监听事件。3、revents:返回事件集合,用于存储返回事件。】
nfds:监听事件结构体数组长度。
timeout:等于-1:一直阻塞。等于0:立即返回。大于0:等待超时时间,单位毫秒。
## 返回值【与select返回值一致】:
成功:返回检测到的文件描述符数量。
失败:返回-1,设置errno。
超时:返回0
  • poll编码流程

在这里插入图片描述

4、poll常见问题

问题1:poll的优缺点?

优点:

  • poll没有1024最大文件描述符限制。
  • poll监视事件(events)和返回事件(revents)分离,简化编程。

缺点:

  • 采用轮询方式获取就绪文件描述符,效率低,和select一样。
  • 每次调用poll都需要把所有文件描述符从内核空间复制到用户空间。
  • 虽然poll没有1024最大文件描述符限制,但是注册的文件描述符越多,poll效率越低。

问题2:poll和select的区别?

poll和select底层实现非常相似,分析poll和select内核源码会发现二者之间很多地方都复用了相同的代码。

poll可以说是select的加强版,poll优化了select一些设计缺陷:

  • poll不受1024最大文件描述符限制,poll采用poll_list链表方式存储输入和输出事件,理论上可以不受最大文件描述符限制。
  • poll传入的是struct pollfd数组,并指定了数组长度,可以减少无效的轮询,提高轮询效率。
  • poll监视事件(events)和返回事件(revents)分离,每次调用poll不需要重新设置struct pollfd对象。
  • poll返回时不会返回剩余超时时间,用户不需要当心超时出现异常**。**

不过很可惜,即使poll对select做了很多优化,依然没有改变轮询方式,也没有改变selec执行效率低的本质问题。

三、epoll

epoll是Linux内核为处理大批量文件描述符而作了改进的poll,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。

1、epoll简介

  • epoll可以理解为event poll,它是一种事件驱动的I/O模型,可以用来替代传统的select和poll模型。epoll的优势在于它可以同时处理大量的文件描述符,而且不会随着文件描述符数量的增加而降低效率。

  • epoll的接口和工作模式相对于select和poll更加简单易用,因此在高并发场景下被广泛使用。

2、epoll实现原理

epoll的实现机制是通过内核与用户空间共享一个事件表,这个事件表中存放着所有需要监控的文件描述符以及它们的状态,当文件描述符的状态发生变化时,内核会将这个事件通知给用户空间,用户空间再根据事件类型进行相应的处理。

  • 下面这张原理图把epoll主要活动轨迹都进行了描述。

在这里插入图片描述

  • socket等待队列

socket等待队列用于在socket接收到数据后添加就绪epoll事件节点和唤醒eventpoll等待队列项。

socket收到数据后,唤醒socket等待队列项,并执行等待队列项注册的回调函数ep_poll_callback,ep_poll_callback函数将就绪epoll事件节点添加至就绪队列,并唤醒eventpoll等待队列项。

  • eventpoll等待队列

eventpoll等待队列用于阻塞当前进程,用于epoll_wait未检测到就绪epoll事件节点的情况。

epoll_wait检测就绪队列是否有epoll事件节点,没有epoll事件节点,则使用等待队列将当前进程挂起,后续ep_poll_callback函数会唤醒当前进程。

  • 就绪队列

就绪队列用于存储就绪epoll事件节点,用户通过epoll_wait函数获取就绪epoll事件节点。

  • 红黑树

红黑树用于存储通过epoll_ctl函数注册的epoll事件节点。

3、epoll编程

  • ①、创建epoll文件
int epoll_create(int size);
## 功能:
epoll_create函数用于创建epoll文件。
## 参数:
size:目前内核还没有实际使用,只要大于0就行。
## 返回值:
成功:返回epoll文件描述符。
失败:返回-1,并设置errno。

在这里插入图片描述

  • ②、增加,删除,修改epoll事件
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
## 功能:
epoll_ctl函数用于增加,删除,修改epoll事件,epoll事件会存储于内核epoll结构体红黑树中。
## 参数:
epfd:epoll文件描述符。
op:操作码【EPOLL_CTL_ADD:插入事件、EPOLL_CTL_DEL:删除事件、EPOLL_CTL_MOD:修改事件】
fd:epoll事件绑定的套接字文件描述符。
events:epoll事件结构体。
## 返回值:
成功:返回0。
失败:返回-1,并设置errno。

在这里插入图片描述

  • epoll事件处理原则:epoll_wait获取epoll事件 = 注册epoll事件 & 就绪epoll事件
  • ③、 epoll事件就绪
int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);
## 功能:
epoll_wait用于监听epoll事件。
## 参数:
epfd:epoll文件描述符。
events:epoll事件数组。
maxevents:epoll事件数组长度。
timeout:超时时间,【小于0:一直等待;等于0:立即返回;大于0:等待超时时间返回,单位毫秒。
## 返回值:
小于0:出错。
等于0:超时。
大于0:返回就绪事件个数。

在这里插入图片描述

  • epoll编码流程

在这里插入图片描述

4、epoll常见问题

问题1:LT模式和ET模式区别?

  • LT模式又称水平触发,ET模式又称边缘触发。

  • LT模式只不过比ET模式多执行了一个步骤,就是当epoll_wait获取完就绪队列epoll事件后,LT模式会再次将epoll事件添加到就绪队列。

  • LT模式多了这样一个步骤会让LT模式调用epoll_wait时会一直检测到epoll事件,直到socket缓冲区数据清空为止。

  • ET模式则只会在缓冲区满足特定情况下才会触发epoll_wait获取epoll事件。

模式EPOLLINEPOLLOUT
LT模式首次触发,socket接收缓冲区检测到数据。一直触发,直到socketi接收缓存为空。首次触发,socket发送缓冲区有空间可发送数据。一直触发,直到socket发送缓冲区无空间发送数据。
ET模式首次触发,socket接收缓冲区检测到数据。首次触发,socket发送缓冲区有空间发送数据。
  • LT模式和ET模式优缺点。
模式优点缺点
LT模式通过频繁触发保证数据完整性。频繁的用户态和内核态切换消耗大量系统资源。
ET模式只触发一次,减少用户态和内核态切换,减少了资源消耗。一次触发无法保证读取到完整数据。

问题2:epoll为什么高效?

  • eventpoll等待队列机制,当就绪队列没有epoll事件时主动让出CPU,阻塞进程,提高CPU利用率。
  • socket等待队列机制,只有接收到数据时才会将epoll事件插入就绪队列,唤醒进程获取epoll事件。
  • 红黑树提高epoll事件增加,删除,修改效率。
  • 任务越多,进程出让CPU概率越小,进程工作效率越高,所以epoll非常适合高并发场景。

问题3:epoll采用阻塞方式是否影响性能?

epoll机制本身也是阻塞的,当epoll_wait未检测到epoll事件时,会出让CPU,阻塞进程,这种阻塞是非常有必要的,如果不及时出让CPU会浪费CPU资源,导致其他任务无法抢占CPU,只要epoll机制能够在检测到epoll事件后,及时唤醒进程处理,并不会影响epoll性能。

问题4:socket采用阻塞还是非阻塞?

socket采用非阻塞方式

epoll机制属于IO多路复用机制,这种机制的特点是一个进程处理多路IO请求,如果socket设置成阻塞模式会存在以下几个问题:

  • 一个进程同一时间只能处理一个socket数据,如果socket被阻塞,那么该进程无法处理其他的socket数据,严重影响了性能。
  • 阻塞的本质是进程状态和上下文的切换,频繁的阻塞会把让CPU一直处于上下文切换的状态,导致CPU瞎忙。

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

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

相关文章

MySQL 包含查询特殊符号数据

当你模糊查询包含特殊符号的数据时,如果不加上特殊处理,查询结果是错误的。 如果你查的数据包含如上字符或者其他特殊字符,需要加上\转义字符。 如下示例: SELECT * FROM t_bc_user t where t.name LIKE %\_%

四、分代垃圾回收机制及垃圾回收算法

学习垃圾回收的意义 Java 与 C等语言最大的技术区别:自动化的垃圾回收机制(GC) 为什么要了解 GC 和内存分配策略 1、面试需要 2、GC 对应用的性能是有影响的; 3、写代码有好处 栈:栈中的生命周期是跟随线程&…

ncnn模型部署——使用VS2019把项目打包成DLL文件

一、项目打包成DLL文件 1.创建动态链接库DLL项目 创建完成,项目中包含源文件dllmain.cpp, pch.cpp,头文件framework.h, pch.h 2.编写和配置DLL项目 (1)配置pch.h文件,在头文件pch.h中定义宏,宏的作用的是…

VUE3给table的head添加popover筛选、时间去除时分秒、字符串替换某字符

1. VUE3给table的head添加popover筛选 <el-tableref"processTableRef"class"process-table"row-key"secuId":data"pagingData"style"width: 100%"highlight-current-row:height"stockListHeight":default-exp…

晶圆测试工艺介绍

第一章、晶圆测试简介 晶圆测试的方式&#xff0c;主要是通过测试机&#xff08;事先编好程序&#xff09;和探针台的联动&#xff0c;依靠探针卡的接触衔接&#xff0c;进行晶圆级的芯片测试。 当探针卡Probecard 的探针正确接触晶圆wafer 内一颗 芯片die的每个接触点bondpads…

毕设:《基于hive的音乐数据分析系统的设计与实现》

文章目录 环境启动一、爬取数据1.1、歌单信息1.2、每首歌前20条评论1.3、排行榜 二、搭建环境1.1、搭建JAVA1.2、配置hadoop1.3、配置Hadoop环境&#xff1a;YARN1.4、MYSQL1.5、HIVE(数据仓库)1.6、Sqoop&#xff08;关系数据库数据迁移&#xff09; 三、hadoop配置内存四、导…

网络层(1)——概述

一、概述 网络层毫无疑问是最复杂的一层&#xff0c;涉及到大量的协议与结构的内容。在如今主流的设计中&#xff0c;大家都会把网络层分成两个部分&#xff1a;数据平面、控制平面。其中数据平面指的是网络层中每台路由器的功能&#xff0c;它决定了到达路由器端口输入链路之一…

软考2018下午第六题改编逻辑(状态模式)

在状态模式中&#xff0c;我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象 package org.example.状态模式.软考航空;/*** author lst* date 2023年12月07日 15:37*/ class FrequentFlyer {CState state;double flyMiles;public FrequentFlyer() {…

为什么 AWS 数据库不讲 HTAP

在 AWS re:Invent 2023 掌门人 Adam Selipsky 的 Keynote 上&#xff0c;数据库方面最重磅的主题是 Zero-ETL&#xff0c;从 TP 数据库 (RDS, Aurora, DynamoDB) 同步数据到 AP 数据库 (Redshift)。 Zero-ETL 是 AWS 在去年 re:invent 2022 上推出的概念&#xff0c;今年则继…

Peter算法小课堂—贪心算法

课前思考&#xff1a;贪心是什么&#xff1f;贪心如何“贪”&#xff1f; 课前小视频&#xff1a;什么是贪心算法 - 知乎 (zhihu.com) 贪心 贪心是一种寻找最优解问题的常用方法。 贪心一般将求解过程分拆成若干个步骤&#xff0c;自顶向下&#xff0c;解决问题 太戈编程第…

simulink enable模块——使能子系统案例仿真分析

1.案例分析 仍以一个简单的乘法增益案例分析 分析&#xff1a;可以看到&#xff0c;在满足条件性才条用使能子系统&#xff0c;在t1s和3s时刻&#xff0c;进行增益操作&#xff0c;这和上篇博客中的触发trigger子系统相同的作用。 simulink trigger模块使用——多种调用案例分…

膜结构建筑:未来体育可持续发展的绿色引擎

随着城市化的飞速发展&#xff0c;现代建筑迫切需要创新性的解决方案&#xff0c;而膜结构建筑以其独特的设计理念和可持续性特点&#xff0c;正在成为未来城市发展的重要引擎。本文将深入探讨膜结构建筑在可持续城市发展中的关键作用&#xff0c;包括其在节能减排、资源有效利…

【Qt开发流程】之元对象系统

描述 Qt的元对象系统&#xff08;Meta-Object System&#xff09;是Qt框架的核心机制之一&#xff0c;它提供了运行时类型信息&#xff08;RTTI&#xff09;和信号与槽&#xff08;Signals and Slots&#xff09;机制的支持。元对象系统在Qt中扮演了很重要的角色&#xff0c;它…

C++STL的string类(一)

文章目录 前言C语言的字符串 stringstring类的常用接口string类的常见构造string (const string& str);string (const string& str, size_t pos, size_t len npos); capacitysize和lengthreserveresizeresize可以删除数据 modify尾插插入字符插入字符串 inserterasere…

解决WPS拖动整行的操作

如上图&#xff0c;想要把第4行的整行内容&#xff0c;平移到第1行。 1.选中第4行的整行 2.鼠标出现如图的样子时&#xff0c;按住鼠标左键&#xff0c;上移到第1行位置后&#xff0c;放开左键即可。

PPT设置章节

0 Preface/Foreward 1 添加章节方法 选择 > 开始 > 节 可以进行&#xff1a; 新增节重命名节删除所有节 相关节的内容如下&#xff1a;

vivado时序方法检查5

TIMING-14 &#xff1a; 时钟树上的 LUT 在时钟树上发现 LUT <cell_name> 。不建议在时钟路径上包含 LUT 单元。 描述 时钟路径上的 LUT 可能导致偏差过大 &#xff0c; 因为时钟必须在穿过互连结构的常规布线资源上进行布线。除偏差过大外 &#xff0c; 这些路径更…

【Java系列】函数式接口编程

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【算法每日一练]-结构优化(保姆级教程 篇4 树状数组,线段树,分块模板篇)

除了基础的前缀和&#xff0c;后面还有树状数组&#xff0c;线段树&#xff0c;分块的结构优化。 目录 分块 分块算法步骤&#xff1a; 树状数组 树状数组步骤&#xff1a; 线段树点更新 点更新步骤&#xff1a; 线段树区间更新 区间更新步骤&#xff1a; 分块 分块算…

Linux CentOS本地部署SQL Server数据库结合cpolar内网穿透实现公网访问

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、Cpolar杂谈 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 安装sql server二. 局域网测试连接三. 安装cpolar内网穿透四. 将sqlserver映射…