当前位置: 首页 > news >正文

五种 IO 模型

文章目录

      • 操作系统和内存
        • 内核空间和用户空间
        • 应用程序的内核态和用户态
        • 网络 IO 和磁盘 IO
        • 简易的网络通信流程
        • 阻塞和非阻塞
      • 阻塞 IO 模型
      • 非阻塞 IO 模型
      • IO 复用模型
        • Select
        • Poll
        • Epoll
        • 小结
      • 信号驱动 IO 模型
      • 异步 IO 模型
      • 五种 IO 模型的对比
      • IO 模型里的同步和异步

5种 IO 模型分别是: 阻塞 IO 模型非阻塞 IO 模型IO 复用模型信号驱动 IO 模型异步 IO 模型

操作系统和内存

计算机由操作系统和硬件组成。

操作系统主要包含内核(kernel)应用程序

内核提供进程管理、内存管理、网络服务等底层功能,也提供了与硬件交互的接口,通过系统调用提供给上层的应用程序使用。

应用程序(如浏览器、QQ、MySQL 等,下面简称为程序)要操作硬件(如进行磁盘读写),需要先与内核交互再由内核与硬件交互

硬件包括 CPU、内存、硬盘、网卡、声卡、显卡等。

内核空间和用户空间

操作系统都是采用虚拟地址空间,内核是操作系统的核心,独立于普通的应用程序,内核可以访问受保护的内存空间(内核空间),也有访问底层硬件设备的所有权限。

为了保证内核的安全,操作系统将虚拟内存空间划分为内核空间用户空间两个部分。它们是隔离的,即使用户程序崩溃了,内核也不受影响。

  • 内核空间是操作系统的内核代码运行的地址空间,是受保护的内存空间。也称内核内存。
  • 用户空间是普通的用户程序代码运行的内存地址空间。也称用户内存。

应用程序的内核态和用户态

早期的操作系统是不区分内核空间和用户空间的。应用程序能随意访问任意内存空间,导致用户程序经常把系统搞崩溃。

后来,就按照 CPU 指令的重要程度对指令进行了分级。

CPU 指令分为四个级别:Ring0 ~ Ring3,Linux 只使用了 Ring0 和 Ring3 两个运行级别。

程序进程运行 Ring3 级别的指令时运行在用户态,只能访问用户空间。

程序进程运行 Ring0 级别的指令时被称为内核态,可访问任意内存空间。

当程序进程(线程)运行在内核空间时,它就处于内核态;当程序进程(线程)运行在用户空间时,它就处于用户态。

那么,程序什么时候运行在内核空间,什么时候运行在用户空间呢?

当需要进行 IO 操作时,比如读写磁盘文件、读写网卡数据时,程序进程需切换到内核态,否则无法操作。无论是从用户态切换到内核态,还是从内核态切换到用户态,都需要进行一次上下文的切换。一般情况下,程序不能直接操作内核空间的数据,需要把内核内存的数据拷贝到用户空间才能操作。

当程序进程执行系统调用而进入内核代码中执行时,称进程处于内核运行态(内核态)。

除了系统调用可以实现用户态到内核态的切换,软中断和硬中断也会切换用户态和内核态。

  • 在内核态下:程序进程(线程)运行在内核空间中,此时 CPU 可以执行任何指令。运行的代码也不受任何的限制,可以自由地访问任何有效地址,也可以直接进行端口的访问。
  • 在用户态下:程序进程(线程)运行在用户空间中,被执行的代码要受到 CPU 的很多检查,比如:进程只能访问映射其地址空间的页表项中规定的在用户态下可访问的虚拟地址。

网络 IO 和磁盘 IO

IO 是 Input/Output 的缩写,也就是计算机中的输入和输出。

由于应用程序和运行时数据是在内存中驻留的,由 CPU 来执行各种操作,涉及到数据交换的地方(通常是内存、磁盘和网络等)就需要 IO 接口。

通常,程序完成 IO 操作会有 Input 和 Output 两个数据流。比如,从 MySQL 读取数据到内存,就有 Input 操作,再把数据展现出来给我们看,就有 Output 操作。

IO 操作是相对于内存而言的,数据从外部设备进入内存就是 Input;从内存取出数据输出到外部设备就是 Output。

用户进程无法直接操作 IO 设备,必须通过系统调用,请求内核来协助完成。内核会为每一个 IO 设备维护一个缓冲区。

通常,用户进程完成一次完整的 IO 操作,需要两个阶段:用户进程空间与内核空间的交互内核空间与设备空间(硬盘、网卡)的交互

IO 从读取数据的来源分为内存 IO、 网络 IO 和磁盘 IO 三种,通常说的 IO 是指网络 IO 和 磁盘 IO。(因为内存 IO 的读写速度远大于网络 IO 和磁盘 IO)

IO 按照设备来分,可分为网络 IO 和磁盘 IO。网络 IO 就是通过网络进行数据的拉取和输出。
磁盘 IO 就是对磁盘进行的读写操作。

  • 网络 IO:等待网络数据到达网卡,把网卡中的数据读取到内核缓冲区,然后从内核缓冲区拷贝数据到用户进程空间。
  • 磁盘 IO:把数据从磁盘读取到内核缓冲区,然后从内核缓冲区拷贝数据到用户进程空间。

由于 CPU 和内存的运行速度远远高于外部设备(网卡、磁盘等),所以在 IO 编程中,存在速度严重不匹配的问题。

简易的网络通信流程

以两个应用程序的通信为例,程序 A 给程序 B 发送消息,基本流程如下:

  • A 把数据发送到 TCP 发送缓冲区。
  • TCP 发送缓冲区再把数据发送出去,经过网络传递后,数据会发送到 B 所在服务器的 TCP 接收缓冲区。
  • B 再从 TCP 接收缓冲区去读取属于自己的数据。

也就是说,消息发送要经过应用层的程序 A、A 所在服务器的 TCP 发送缓冲区,经过网络传输后消息发送到了另一个应用层的程序 B 所在服务器的 TCP 接收缓冲区,最终 B 读取到消息。

阻塞和非阻塞

由于应用程序之间发送消息是间断性的,那么,当程序 B 所在服务器的 TCP 接收缓冲区,还未接收到消息数据时,此时 B 向 TCP 接收缓冲区发起读取申请,TCP 接收缓冲区是应该马上告诉 B 现在没有你的数据,还是让 B 继续等待,直到有数据再交给 B。

对于应用程序 A 也是一样。A 在向 TCP 发送缓冲区发送数据时,如果 TCP 发送缓冲区已经满了,那么是立即告诉 A 现在没空间了,还是让 A 等着,等 TCP 发送缓冲区有空间了再把 A 的数据拷贝到发送缓冲区。

阻塞:以读取数据为例,当程序 B 发起读取申请时,在内核把数据准备就绪之前,B 一直处于等待状态(其它什么也不做),直到内核把数据准备好交给 B,才结束。

基本流程:

  1. 程序进程(或线程)向内核发起 recfrom 读取数据。
  2. 内核准备数据。
  3. 程序进程将数据从内核空间拷贝到用户空间。
  4. 拷贝完成后,返回成功提示。

非阻塞:以读取数据为例,当程序 B 发起读取申请时,如果内核没有把数据准备好,会立即告诉 B(返回提示或错误),不会让 B 一直等待。

基本流程:

  1. 程序进程(或线程)向内核发起 recfrom 读取数据。
  2. 内核没有把数据好时,立即返回 EWOULDBLOCK 错误码。
  3. 程序进程不断调用 recvfrom,即向内核发起轮询请求。
  4. 当数据准备就绪,就进行下一步;否则还是返回错误码。
  5. 将数据从内核空间拷贝到用户空间。
  6. 拷贝完成后,返回成功提示。

IO 操作分为两个阶段(步骤)

  • 内核进行数据准备的阶段
  • 数据从内核空间拷贝到用户空间的阶段

根据这两个阶段,处理方式的不同,IO 操作可细分为下面五种。

阻塞 IO 模型

阻塞 IO 模型是指当程序 B 发起 IO 请求时,如果内核没有把数据准备就绪,B 会一直处于等待状态,直到内核把数据准备好了,并交给 B 才结束。

优点:开发相对简单,在阻塞期间,用户线程被挂起,期间不会占用 CPU 资源。

缺点

  • 连接利用率不高,内核如果没有响应数据,则该连接一直处于阻塞状态,占用连接资源。
  • 一个线程维护一个 IO 资源,当有大量并发请求时,需要创建等价的线程来处理请求,不适合高并发场景。

非阻塞 IO 模型

非阻塞 IO 模型是指当程序 B 发起 IO 请求时,如果内核没有把数据准备就绪,会立即告诉 B(返回提示或错误码),这样,B 就不会一直等待,而是每过一段时间发起轮询请求

优点:每次发起 IO 请求时,在内核准备数据的过程中可以立即返回,用户线程不会阻塞,实时性较好。

缺点

  • 当用户线程 B 没有获取到数据时,需不断轮询,占用大量 CPU 时间,效率不高。
  • 和阻塞 IO 一样,一个线程维护一个 IO 资源,当有大量并发请求时,需要创建等价的线程来处理请求,不适合高并发场景。

IO 复用模型

思考一个问题:

高并发的情况下,有很多人向应用程序 B 发送消息,此时程序 B 可能就要创建很多个线程,每个线程都会调用 recvfrom 读取数据。B 是不知道什么时候 TCP 接收缓冲区里会有数据,为了保证能及时读取到消息,每个线程必须不断内核发起 recvfrom 请求。

问题在于,大量线程不断调用 recvfrom,实在太浪费系统资源。

于是,有人便提出了一个解决思路:

在程序 B 中,采用 IO 复用器(select),监控多个网络请求(fd 文件描述符,句柄),这样,只需一个线程就可以完成数据状态的询问操作,当内核空间中有数据准备就绪,再分配其他的线程(或自己)去读取数据。而不用为每一个请求创建一个线程,从而节省出大量的线程资源。这就是 IO 复用模型

Linux 中 IO 复用的实现方式主要有 Select、Poll 和 Epoll。

IO 复用模型的思路是系统提供了一种函数可以同时监控多个 fd,这个函数就是我们常说的 select、poll 或 epoll,程序线程通过调用 select 函数就可以同时监控多个 fd,监控的 fd 集合中只要有任何一个数据状态准备就绪了,select 函数就会返回可读状态,这时再去分配其他线程(或自己),发起 recvfrom 请求读取数据。

Select

水平触发(Level Triggered),它会无差别地遍历(轮询)整个被监听的 fd 文件描述符集合(fd_set) 。如果有哪一个 fd 准备就绪,就返回这个活跃的连接。fd_set 的大小是受限制的(由 Linux 内核的 FD_SETSIZE 定义)。

  • 事件集合:通过3个参数分别可读、可写及异常等事件。内核通过对这些参数的在线修改来反馈其中的就绪事件,使得每次调用 select 函数都要重置这 3 个参数。
  • 工作模式:LT
  • 程序获得就绪 fd 的复杂度:时间复杂度 O(n)
  • 支持最大的 fd 数量:一般为 1024
  • 内核实现和复杂度:轮询方式检测就绪事件,时间复杂度:O(n)

Poll

原理和 select 类似,poll 底层需要分配一个 pollfd 结构数组,维护在内核中,不受 fd_set 大小的限制。

  • 事件集合:统一处理所有事件类型,因此只需要一个事件集参数。用户通过 pollfd.events 传入要监听的事件,内核通过修改 pollfd.revents 反馈其中就绪的事件。
  • 工作模式:LT
  • 程序获得就绪 fd 的复杂度:时间复杂度 O(n)
  • 支持最大的 fd 数量:65535
  • 内核实现和复杂度:轮询方式检测就绪事件,时间复杂度:O(n)

Epoll

边缘触发(Edge Triggered),采用事件驱动和回调函数。三大要素:mmap、红黑树、链表。

  • 事件集合:内核通过一个事件表直接管理用户程序监听的所有事件。因此每次调用 epoll_wait 时,无需反复传入事件。epoll_wait 系统调用的参数 events 仅用来反馈就绪的事件。
  • 工作模式:ET
  • 程序获得就绪 fd 的复杂度:时间复杂度 O(1)
  • 支持最大的 fd 数量:65535
  • 内核实现和复杂度:回调方式检测就绪事件,时间复杂度:O(1)

说明:epoll 并不是在所有的场景都比 select 和 poll 高效很多,尤其是当活动连接比较多的时候。epoll 特别适用于连接数量多,但活动连接较少的场景

小结

select、poll、epoll 都是 IO 多路复用的机制。

IO 多路复用就是通过一种机制,监听多个 fd 文件描述符,一旦某个 fd 准备就绪,能够通知程序进行相应的读写操作。

但 select、poll、epoll 本质上都是同步 IO,因为它们都需要在读写事件就绪后自己负责读写(一个个的处理),也就是说这个读写过程是阻塞的。而异步 IO 则无需自己负责读写,异步 IO 的实现会负责把数据从内核空间拷贝到用户空间。

IO 复用的基本思想是通过 select、poll、epoll 来监控多个 fd ,达到不必为每个 fd 创建一个对应的监控线程,从而减少线程资源的创建。

IO 复用的优势并不是对于单个连接处理得多快,而是在于能处理更多的连接。

IO 复用模型的优点:系统不必创建和维护大量的线程,只需要一个或几个线程便可同时处理成千上万个连接,大大减少了系统的开销。

IO 复用模型的缺点:本质上还是同步阻塞模式。

信号驱动 IO 模型

IO 复用模型实现了一个线程可以监控多个 fd,但 select 是采用轮询的方式来监控多个 fd 的,通过不断轮询 fd 的状态来判断是否有数据准备就绪,这种无脑的轮询显得有些暴力,因为大部分情况下的轮询都是无效的。

所以有人就想,能不能不要让我总是去询问你是否有数据准备就绪,能不能我发出请求后等你数据准备好了就通知我。于是,就诞生了信号驱动 IO 模型。

信号驱动 IO 模型是指程序 B 通过系统调用 sigaction,向内核空间注册一个信号处理回调函数,就立即返回(非阻塞);当内核把数据准备就绪时,会发送一个信号(SIGIO)通知 B,B 再向内核调用 recvfrom 读取数据。

信号驱动 IO 模型解决了轮询询问数据状态的问题,线程在发出信号监控后立即返回(非阻塞),因此,一个线程也可以同时监控多个 fd。

信号驱动 IO 也可以看成是一种异步非阻塞 IO。

在内核进行数据准备期间,程序进程(线程)不阻塞。但是,当程序进程(线程)将数据从内核空间拷贝到用户空间期间,是阻塞的。这是它和异步 IO 的本质区别。

异步 IO 模型

可以发现,不管是 IO 复用还是信号驱动 IO,要读取数据需发起两次请求,第一次发起判断数据就绪状态的请求第二次发起 recvfrom 读取数据的请求

为什么我们明明是想读取数据,却非要先发起一个判断数据状态的请求,然后再发起真正的读取请求。有没有一种方法,只需发送一个请求告诉内核我要读取数据,就什么都不管,由内核去帮我完成所有的事情。

于是,异步 IO 模型便诞生了。

异步 IO 模型是指程序 B 向内核发送一个 IO 请求(比如 read),告知内核我要读取数据,便立即返回;内核收到请求后会与之建立一个信号联系,当数据准备就绪,内核会主动把数据从内核空间复制到用户空间。所有操作完成之后,内核会发送一个完成通知告知 B。

异步 IO 模型做到了真正的非阻塞。

异步 IO 模型与信号驱动 IO 模型的主要区别在于,信号驱动 IO 只是让内核通知我们何时可以开始下一个 IO 操作,而异步 IO 模型是让内核通知我们操作什么时候完成。

此模型和前 4 个模型最大的区别是:前 4 个模型从内核空间拷贝数据到用户空间这一过程,必须由程序自身来进行,必然是阻塞的。
而异步 IO 模型在内核准备数据数据从内核空间拷贝到用户空间这两个过程都不用等待,完全非阻塞。

用户进程(线程)完全不需要关心实际的整个 IO 操作是如何进行的,只需先发起一个请求,当收到内核返回的成功信号时,所有的 IO 操作都已完成。它是最理想的模型。

五种 IO 模型的对比

  • 阻塞 IO:在数据准备阶段和数据拷贝阶段,都会阻塞。
  • 非阻塞 IO:在数据准备阶段,非阻塞;但在数据拷贝阶段阻塞。
  • IO 复用:在数据准备阶段,采用复用器轮询遍历多个 fd,会阻塞;在数据拷贝阶段阻塞。但是,它用单一线程监听了多个连接,减少了线程资源的创建。
  • 信号驱动 IO:在数据准备阶段,注册一个信号处理函数,来接收内核准备数据的结果信号,实现非阻塞;在数据拷贝阶段阻塞。
  • 异步 IO:在数据准备阶段和数据拷贝阶段,都非阻塞。

IO 模型里的同步和异步

我们常常可以听到同步阻塞 IO、同步非阻塞 IO、异步 IO。

应用程序发起读取数据请求,若数据还没准备就绪,需要等待就是阻塞;反之,若立即返回就是非阻塞。

那么,这里的同步和异步怎么理解呢?

同步:是指应用程序发起 IO 请求,从发起请求到请求最终完成,整个过程都需要参与其中(与内核进行交互)。

异步:是指应用程序发起 IO 请求之后,就不再参与后续的具体过程,接收最终完成结果的通知由回调实现。

为什么只有异步非阻塞而没有异步阻塞?因为异步 IO 模型下,程序发送完请求指令后就立即返回了,没有任何后续流程。因此,它注定不会阻塞,也就只会有异步非阻塞。

阻塞必然同步,同步不一定阻塞。

相关文章:

五种 IO 模型

文章目录操作系统和内存内核空间和用户空间应用程序的内核态和用户态网络 IO 和磁盘 IO简易的网络通信流程阻塞和非阻塞阻塞 IO 模型非阻塞 IO 模型IO 复用模型SelectPollEpoll小结信号驱动 IO 模型异步 IO 模型五种 IO 模型的对比IO 模型里的同步和异步5种 IO 模型分别是&…...

34-Golang中的结构体!!!

Golang中的结构体结构体和结构体变量(实例)的区别和联系结构体变量(实例)在内存中的布局如何声明结构体字段/属性注意事项和细节说明创建结构体实例的四种方式结构体使用细节结构体和结构体变量(实例)的区别和联系 1.结构体是自定义的数据类型,代表一类事物2.结构体…...

这6个视频剪辑素材库,你一定要知道~

推荐5个免费商用视频素材网站,建议收藏哦! 1、菜鸟图库 视频素材下载_mp4视频大全 - 菜鸟图库 网站素材量很大,有设计、图片、音频、视频等超多素材,大部分都能免费下载。视频素材都很高清,有自然、人物、科技、农业…...

RocketMQ WIN11 搭建

去官方下载 https://rocketmq.apache.org/zh/download/ 下载,博主下载的是 4.6.0 的版本,选择Binary版本 拓展 Source 下载:需要编译 Binary 下载:不需要编译 解压缩,运行 先解压缩环境变量中添加rocketMQ文件夹路…...

iPhone更换电池和屏幕后提醒非原厂配件的操作办法

---开局一张图,内容全靠编系列! 【图】 自从在iPhone系统iOS13开始支持原厂配件检测后,可以说苹果也动起了维修站商家利益的这块蛋糕。道理自然简单,卷嘛!全球汽车行业也不是靠卖新车才赚钱的,各种交通事故…...

chatGPT发布记录

发行说明(2 月 13 日)我们对 ChatGPT 进行了多项更新!这是新功能:我们更新了免费计划中 ChatGPT 模型的性能,以便为更多用户提供服务。根据用户反馈,我们现在默认让 Plus 用户使用更快的 ChatGPT 版本&…...

DataX及DataX-Web

大数据Hadoop之——数据同步工具DataX数据采集工具-DataX datax详细介绍及使用 一、概述 DataX 是阿里云DataWorks数据集成的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、…...

数据结构与算法系列之kmp算法

什么是kmp算法 1.kmp算法是一种改进的字符串算法,其核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数已达到快速匹配的目的。 它主要实现作用的是 在 (主串)中找到 (匹配)字符串。 例 BF算法与k…...

算法分析详解

自古老的公元前1世纪开始,《周髀算经》就作为中国最古老的天文学和数学著作。 《周髀算经》采用最简便可行的方法确定天文历法,揭示日月星辰的运行规律,包括四季更替,气候变化,南北有极,昼夜相推的道理。为…...

东南大学自然辩证法概论期末总结

写在前面 作者:夏日 博客地址:https://blog.csdn.net/zss192 本文为2022年东南大学自然辩证法概论期末总结,内容为根据老师所发题纲综合多个资料总结得来 考试形式:从老师所发题纲,10个题目中选出4个,题…...

《爆肝整理》保姆级系列教程python接口自动化(二十)--token登录(详解)

简介 为了验证用户登录情况以及减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。有些登录不是用 cookie 来验证的,是用 token 参数来判断是否登录。token 传参有两种一种是放在请求头里,本质上是跟 cookie 是一样的&…...

k8s种的kubectl命令

一.kubectl基本命令1.1 称述式资源管理的方法kubernetes集群管理集群资源的唯一入口是通过相应的方法调用apiserver的接口kubectl是官方的CLI命令行工具,用于与apiserver进行通信,将用户在命令行输入的命令,组织并转化为apiserver能识别的信息…...

数组(一)-- LeetCode[26][80] 删除有序数组中的重复元素

1 删除有序数组中的重复项 1.1 题目描述 给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。 由于在某些语言中不能改变数组的长度&#xff0c…...

GEE学习笔记 六十三:新的地图图层ui.Map.CloudStorageLayer

在GEE中导出数据有一种方式是直接导出地图到Google Cloud Storage中,也就是Export.map.toCloudStorage(xxx),这种方式是将我们计算生成影像导出成为静态瓦片的格式存放在Google Cloud Storage中。我们可以在其他的前端程序比如OpenLayer、Mapbox GL JS等…...

ClickHouse 语法详解

ClickHouse有2类解析器:完整SQL解析器(递归式解析器),以及数据格式解析器(快速流式解析器) 除了 INSERT 查询,其它情况下仅使用完整SQL解析器。 INSERT查询会同时使用2种解析器:INSE…...

手把手教你将微信小程序放到git上

背景 首先,要创建一个自己的git仓库,这里默认大家都能够自己创建了git仓库了。如果不会创建仓库的话,百度一下,很容易就能够创建了!(后续,如有不知道在哪里,怎么创建仓库的话&#…...

功能测试3年,回顾一路走来的艰辛

不论你是什么时候开始接触测试这个行业的,你首先听说的应该是功能测试。通过一些测试手段来验证开发做出的代码是否符合产品的需求?当然你也有自己对功能测试的理解,但是最近两年感觉功能测试好像不太受欢迎,同时不少同学真的是功…...

作为Linux C/C++程序员必备的工具

Linux系统 可以选择centOS或者ubautu server(不建议选择桌面版本的)。不建议裸机安装,玩坏了就特别麻烦。不建议使用有桌面版本的ubautu,在一定程度有桌面的版本的会消耗性能。 如果经济实力允许,可以购买云服务器。 参考文章: Ubuntu server…...

docker Alpine一个只有5M小而美的Docker镜像

docker Alpine一个只有5M小而美的Docker镜像 参考链接: Alpine 一个只有5M的Docker镜像 http://www.infoq.com/cn/news/2016/01/Alpine-Linux-5M-Docker?utm_sourcetuicool&utm_mediumreferral 使用alpinelinux 构建 golang http 启动了才15mb http://blog.csdn.net/fre…...

Springboot扩展点之InstantiationAwareBeanPostProcessor

Springboot扩展点系列实现方式、工作原理集合:Springboot扩展点之ApplicationContextInitializerSpringboot扩展点之BeanFactoryPostProcessorSpringboot扩展点之BeanDefinitionRegistryPostProcessorSpringboot扩展点之BeanPostProcessorSpringboot扩展点之Instant…...

基于 U-Net 网络的遥感图像语义分割 完整代码+论文

一、研究目的U-Net 是一种由全卷积神经网络启发的对称结构网络,在医疗影像分割领域取得了很好的效果。 此次研究尝试使用 U-Net 网络在对多光谱遥感影像数据集上进行训练,尝试使用卷积神经网络自动分割出建筑,希望能够得到一种自动分割遥感影…...

Codeql 编译Shiro1.2.4爬坑

0x00 前言 这个Codeql一定要编译才能生成Database,是真的比较恼火,很多项目都不一定可以生成,环境就是一个非常大的坑,为了防止以后,所以将shiro1.2.4编译过程进行记录。 0x01 正文 首先是需要下载到shiro1.2.4的源…...

新C++(9):谈谈,翻转那些事儿

"相信羁绊,相信微光,相信一切无常。"一、AVL树翻转那些事儿(1)什么是AVL树?在计算机科学中,AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为1,所以它也被称为高度平衡树。…...

Java深克隆的几种方式

目录 1、通过继承Cloneable接口,重写clone方法实现深克隆 2、通过序列化与反序列化的方式实现深克隆 3、第三方工具类实现深克隆,克隆对象需继承Serializable接口 3.1、Apache Commons Lang的SerializationUtils.clone方法 3.2、Gson工具类 3.3、F…...

PointNet++的源码运行

首先,从github上下载源码https://github.com/yanx27/Pointnet_Pointnet2_pytorch也可以从百度网盘下载链接:https://pan.baidu.com/s/1sgTYuqnBVC9p3bib450SOQ 提取码:gujd再下载对应的测试数据分类数据modelnet40_normal_resampled下载&…...

npm 上传自己的包

mkdir demo 创建一个新的文件夹 npm init 初始化项目 生成一个package.json文件 name version description等等touch index.js 创建一个node 可执行脚本新的js 文件 #!/usr/bin/env node // 必须在文件头加如上内容指定运行环境为node console.log(hello cli)在package.json 中…...

【Linux】常用命令大全(二)

目录 4. Linux常用命令 4.1 Linux命令初体验 4.2 文件目录操作命令 4.3 拷贝移动命令 4.4 打包压缩命令 4.5 文本编辑命令 4.6 查找命令 4. Linux常用命令 4.1 Linux命令初体验 4.1.1 常用命令演示 在这一部分中,我们主要介绍几个常用的命令&#xff0c…...

第一章 操作系统概述

目录一、什么是操作系统?1、操作系统的概念2、计算系统的构成3、主要作用二、操作系统有哪些功能?1、操作系统的目标2、操作系统的功能三、操作系统有哪些特征?1、并发性2、共享性3、虚拟性4、异步性四、操作系统的运行机制是怎样的&#xff…...

ChatGPT为什么不受开发者喜欢?

记得 ChatGPT 最开始上线不久的时候,看到的大部分尝鲜和测试结果都是开发者在做进行敲代码测试,可以说职业危机感非常强的一群人了。 再者,加上 ChatGPT 要使用起来其实是有一些技术门槛的,愿意折腾的人也多是程序员,…...

Lua table

Table(表) table 是 lua 中唯一的数据结构,可以用于表示 数组,字典与结构体。它非常强大,可以储存任何数据类型。 table 的数据单元为一对键值。 table 是不固定大小的,你可以根据自己需要进行扩容。 构…...