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

网络编程中的直接内存与零拷贝

本篇文章会介绍 JDK 与 Linux 网络编程中的直接内存与零拷贝的相关知识,最后还会介绍一下 Linux 系统与 JDK 对网络通信的实现。

1、直接内存

所有的网络通信和应用程序中(任何语言),每个 TCP Socket 的内核中都有一个发送缓冲区(SO_SNDBUF)和一个接收缓冲区(SO_RECVBUF):

请添加图片描述

应用程序调用 write() 会使内核复制应用程序缓冲区中所有的数据到 Socket 的发送缓冲区,如果后者放不下并且该 Socket 是阻塞式的,应用程序会被投入睡眠。write() 直到应用程序缓冲区的所有数据都复制到 Socket 的发送缓冲区后才会返回,此时可以继续向应用程序缓冲区写入数据,但不表示对端的 TCP 或应用程序已经接收到数据:

请添加图片描述

Java 也遵从这种规则。只不过因为堆、GC 等特性影响,会有一些特殊操作,即使用直接内存(或称堆外内存),下面来阐述原因:

  • 前面说过,要发送的数据会从应用程序的缓冲区被内核拷贝到 Socket 内核的发送缓冲区中。这中间必定有调用 Native 方法将 Java 对象地址通过 JNI 传递给底层 C 库的过程
  • 如果该 Java 对象存在堆中,受 GC 影响该对象可能会在堆中移动,就有可能出现该对象地址在传递给底层前后不同的情况,原地址失效底层就拿不到原本的对象。因此会要求调用 Native 方法之前一定要将数据存在堆外内存,JDK 对此的解决方案是将堆中的数据拷贝到堆外的 DirectBuffer 中
  • 也可以直接使用 DirectBuffer 而不再通过堆,这样可以省去把数据由堆拷贝到 DirectBuffer 的一次拷贝,使用直接内存当然就会快一点
  • 直接内存不受新生代的 Minor GC 影响,只有执行老年代的 Full GC 时才会顺便回收直接内存,整理内存的压力也比将数据放到堆上小

使用堆外内存的好处是减少了 GC(会暂停其他工作)工作、加快了复制速度(相比于堆少了一次数据拷贝);缺点是如果堆外发生内存泄漏难以排查、不适合存很复杂的对象(适合简单对象或扁平化对象)。

请添加图片描述

2、零拷贝

指计算机执行操作时,CPU不需要先将数据从某处内存复制到另一个特定区域。这种技术通常用于通过网络传输文件时节省CPU周期和内存带宽。

零拷贝并不是说不需要拷贝,只是说减少冗余的、不必要的(尤其是需要 CPU 干预的)拷贝:

  • 零拷贝技术可以减少数据拷贝和共享总线操作的次数,消除传输数据在存储器之间不必要的中间拷贝次数,从而有效地提高数据传输效率
  • 零拷贝技术减少了用户进程地址空间和内核地址空间之间因为上下文切换而带来的开销

2.1 Linux 的 IO 机制与 DMA

早期用户进程需要读取磁盘数据时都需要 CPU 中断并参与,这样 CPU 的效率低,因为每次 IO 请求都要中断 CPU 带来 CPU 的上下文切换,为了解决这个问题出现了 DMA(Direct Memory Access)。

DMA 不需要依赖 CPU 大量的中断负载就可以与不同速度的硬件装置进行沟通。DMA 控制器接管了数据读写请求,减少了 CPU 的负担,使得 CPU 可以高效工作。现代硬盘基本都支持 DMA,实际的 IO 读取涉及两个过程(都是阻塞的):

  1. DMA 等待数据准备好,把磁盘数据读取到操作系统内核缓冲区
  2. 用户进程,将内核缓冲区的数据 copy 到用户空间

DMA 是物理硬件,也算是一种芯片,磁盘、网卡、键盘等都有自己的 DMA。早期 CPU 会参与 IO 工作,读取磁盘上的数据拷贝到内存当中,由于 IO 读写速度相比于 CPU 的处理速度是很慢的,所以这就相当于浪费了 CPU 的宝贵时间,于是产生了 DMA 设备,在有 IO 需求时,CPU 给 DMA发指令让其读取磁盘数据,DMA 读取后会将数据拷贝到内存中,再通知 CPU 数据拷贝完成,然后 CPU 再用内存中的数据做接下来的操作。这就将 CPU 从低速的 IO 读取工作中解放出来,专心做高速计算。

2.2 传统数据传送机制

以读取文件再用 Socket 发送出去这个过程为例,伪代码如下:

buffer = File.read()
Socket.send(buffer)

这个过程的示意图如下:

请添加图片描述

数据要经过四次拷贝:

  1. 将磁盘中的文件拷贝到操作系统内核缓冲区
  2. 将内核缓冲区数据拷贝到应用程序缓冲区
  3. 将应用程序缓冲区中的数据拷贝到位于操作系统内核缓冲区中的 Socket 网络发送缓冲区
  4. 将 Socket 缓冲区中的数据拷贝到网卡,由网卡进行网络传输

其中 2、3 两次(即图中红线的两次 CPU 拷贝)是“不必要的拷贝”,对于发送网络数据而言属于额外开销,可以优化掉。

此外,read 和 send 都属于系统调用,每次调用都牵涉两次上下文切换,总共就是四次上下文切换:

请添加图片描述

2.3 Linux 常见的零拷贝

零拷贝的目的就是减少不必要的拷贝,需要 OS 支持(需要 kernel 暴露 api)。

mmap 内存映射

将硬盘与应用程序缓冲区进行映射(建立一一对应关系),由于 mmap() 将文件直接映射到用户空间,读取文件时就可以根据该映射关系将文件从硬盘拷贝到用户空间:

请添加图片描述

这样仍有 3 次拷贝,4 次上下文切换。

sendfile

请添加图片描述

sendfile 需要 3 次拷贝,2 次上下文切换:

  • 3 次拷贝如上图所示,当然如果硬件支持的话,红线的 CPU 拷贝是可以省略的。具体做法是文件读取缓冲区将文件的起始位置和长度的描述符传入 Socket 缓冲区,然后 DMA 会根据这个数据从文件读取缓冲区中直接将文件读取到网络设备缓冲区,这样就只需要 2 次拷贝了
  • 用户调用 sendfile 这一个系统调用,仅需两次上下文切换

splice

Linux 在 2.6.17 开始支持的系统调用,使用管道直接将内核缓冲区的数据转换为其他数据 buffer。在 Socket 网络通信的情况下,就是文件读取缓冲区与 SO_SNDBUF 建立 pipe 管道(实际上是管道两侧的缓冲区共用一块物理内存)。这样在无需硬件支持的情况下就省去了 CPU 拷贝:

请添加图片描述

splice 也是需要 2 次拷贝,2 次上下文切换。

总结

零拷贝说法的来源最早出现于 sendfile 系统调用,这是真正操作系统意义上的零拷贝(也称狭义零拷贝)。

但是由于由 OS 内核提供的操作系统意义上的零拷贝发展到现在种类并不是很多,因此随着发展,零拷贝的概念延伸到了,减少不必要的数据拷贝都算作零拷贝的范畴。

3、Linux 和 JDK 对网络通信的实现

3.1 Linux 网络 IO 模型

同步与异步,阻塞与非阻塞

同步与异步关注的是调用方是否主动获取结果:

  • 同步:调用方主动等待结果返回
  • 异步:调用方不用主动等待结果返回,而是通过状态通知、回调函数等手段获取结果

阻塞与非阻塞关注的是调用方在等待结果返回之前的状态:

  • 阻塞:结果返回前,当前线程被挂起不做任何事
  • 非阻塞:结果返回前,线程可以做其他事情,不会被挂起

二者有四种组合:

  1. 同步阻塞:编程中最常见的模型,等待结果并且等待期间不做任何事,效率很低
  2. 同步非阻塞:可以抽象为轮询模式,等待结果期间会做其他事情,但是会时不时地询问是否已经返回结果
  3. 异步阻塞:用的很少,有点像在线程池中 submit 后马上 Future.get(),此时线程其实还是挂起的
  4. 异步非阻塞:常用模型是回调函数

Linux 下的五种 IO 模型

五种 IO 模型,前四种是同步的,最后一种是异步的:

  1. 阻塞 IO:调用 IO 函数,会经过系统调用进入内核。应用程序会被阻塞,直到数据被准备好,从内核空间拷贝到用户空间后,IO 函数返回,阻塞才被解除。BIO 中的 bind()、connect()、accept() 都是阻塞方法
    请添加图片描述
  2. 非阻塞 IO:IO 操作无法完成时,不将进程睡眠,而是返回一个错误。这样应用就需要不断测试数据是否已经准备好,如果没有就继续测试直到数据准备好为止。这种不断测试会大量占用 CPU 时间,因此该模型绝对不被推荐
    请添加图片描述
  3. IO 复用(select、poll、epoll):本质上也是阻塞的,只不过将阻塞拆开为 select(或 epoll)和 recvfrom 两个系统调用,前者在有读写事件到来时返回,后者在数据从内核拷贝到用户空间后返回。也就是对一个 IO 端口进行两次系统调用,返回两次结果,这比阻塞 IO 并没有什么优势,甚至相同条件下处理单个连接的效率还要比 BIO 低,但是胜在能同时对多个 IO 端口进行监听
    请添加图片描述
  4. 信号驱动 IO:应用进程向内核注册一个信号处理函数然后继续执行其他内容不会阻塞,当数据到来时,内核发出信号,通过信号处理程序告诉应用进程数据来了,这时应用程序才调用 recvfrom 进入阻塞式获取数据的过程。整个过程有两次调用和两次返回
    请添加图片描述
  5. 异步 IO:当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者的输入输出操作(Linux 下的 AIO 是假的异步,是用 IO 多路复用实现的)
    请添加图片描述

3.2 JDK 对网络通信的实现

JDK 实际上就是对 Linux 的 IO 通信模型进行了一个包装,因此我们先了解 Linux 的通信实现。

Linux 下的阻塞网络编程

Linux 下与 JDK 实现网络通信的一个最大不同是,在服务端,Linux 用的是 socket 而 JDK 用的 ServerSocket,实际上就是 JDK 在 socket 基础上做了一层封装。此外,Linux 下需要通过 listen() 侦听端口,这个大概也被 ServerSocket 封装了。

从 Linux 代码结构看网络通信

分层:应用 API 层、协议层、接口层,应用发送数据是由上至下,接收数据是由下至上,并且接收时还涉及到由网络设备产生的硬中断。

中断、上半部、下半部

内核和设备驱动是通过中断的方式来处理的。所谓中断,可以理解为当设备上有数据到达的时候,会给 CPU 的相关引脚上触发一个电压变化,以通知 CPU 来处理数据。

网卡把数据写入内存后会向 CPU 发出一个中断信号,由操作系统执行网卡中断程序去处理数据。由于网络操作复杂且耗时,如果在中断函数中完成所有处理,会使得中断处理函数(优先级过高)过度占据 CPU,使得 CPU 无法响应其他设备(如鼠标键盘),因此 Linux 将中断处理函数分为上半部和下半部。

上半部只进行最简单的工作,快速处理然后释放 CPU,这样 CPU 就可以让其他中断进来。下半部则慢慢从容的处理绝大部分工作。自 2.4 以后内核采用下半部是软中断,即给内存中的一个变量的二进制赋值以通知中断处理程序;而硬中断则是通过给 CPU 物理引脚施加电压变化。

JDK 的 BIO 实现分析

Socket 和 ServerSocket 内部的 SocketImpl 才是真正实现网络通信的组件(使用了门面模式),这与 Linux 下 CS 两端都使用 socket 是吻合的。

Linux 下的 IO 复用编程

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

select 提供了一个函数:

// readfds 读事件 fd 集合,writefds 写事件 fd 集合,exceptfds 异常事件 fd 集合
int select (int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

所有的操作系统都支持 select 机制,Linux 下能监控的最大文件描述符数量为 1024,超过该数量性能会急剧下滑。

poll 也提供了一个函数,将 select() 参数中的三个描述符合为一个:

int poll (struct pollfd *fds, unsigned int nfds, int timeout);

fds 也是不能超过 1024 个,否则性能会急剧下降(因为是轮询 Socket 通道获取事件,数量多了自然性能就下降了)。

epoll 有三个函数,也就是三个系统调用:

// 创建 epoll 的文件描述符,类似于 JDK NIO 的 Selector.open()
int epoll_create(int size);
// 注册、增加、删除、修改关注的事件,类似于 JDK NIO 的 ServerChannel.register()
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
// 等待,看是否有事件发生,类似于 JDK NIO 的 Selector.select()
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

实际上 JDK 的 NIO 就是对 Linux epoll 的包装。

相关文章:

网络编程中的直接内存与零拷贝

本篇文章会介绍 JDK 与 Linux 网络编程中的直接内存与零拷贝的相关知识,最后还会介绍一下 Linux 系统与 JDK 对网络通信的实现。 1、直接内存 所有的网络通信和应用程序中(任何语言),每个 TCP Socket 的内核中都有一个发送缓冲区…...

语音转文字

语音转文字工具大全 1. 网易 网易见外(网页) 地址:网易见外 - AI智能语音转写听翻平台 特点:完全免费,支持音频转文字,每日上限2小时 有道云笔记(安卓/iOS) 地址&a…...

软件设计师考试《综合知识》创建型设计模式考点分析

软件设计师考试《综合知识》创建型设计模式考点分析 1. 分值占比与考察趋势(75分制) 模式名称近5年题量分值占比高频考察点最新趋势抽象工厂模式45.33%产品族创建/跨平台应用结合微服务配置考查(2023)工厂方法模式56.67%单一产品扩展/日志系统与IoC容器…...

【八股战神篇】Java集合高频面试题

专栏简介 八股战神篇专栏是基于各平台共上千篇面经,上万道面试题,进行综合排序提炼出排序前百的高频面试题,并对这些高频八股进行关联分析,将每个高频面试题可能进行延伸的题目再次进行排序选出高频延伸八股题。面试官都是以点破…...

STM32F103定时器1每毫秒中断一次

定时器溢出中断,在程序设计中经常用到。在使用TIM1和TIM8溢出中断时,需要注意“TIM_TimeBaseStructure.TIM_RepetitionCounter0;”,它表示溢出一次,并可以设置中断标志位。 TIM1_Interrupt_Initializtion(1000,72); //当arr1…...

BC 范式与 4NF

接下来我们详细解释 BC 范式(Boyce-Codd范式,简称 BCNF),并通过具体例子说明其定义和应用。 一、BC范式的定义 BC范式(Boyce-Codd范式,BCNF)是数据库规范化理论中的一种范式,它比第…...

Data whale LLM universe

使用LLM API开发应用 基本概念 Prompt Prompt 最初指的是自然语言处理研究人员为下游任务设计的一种任务专属的输入模板。 Temperature 使用Temperature参数控制LLM生成结果的随机性和创造性,一般取值设置在0~1之间,当取值接近1的时候预测的随机性较…...

数据结构第七章(四)-B树和B+树

数据结构第七章(四) B树和B树一、B树1.B树2.B树的高度 二、B树的插入删除1.插入2.删除 三、B树1.B树2.B树的查找3.B树和B树的区别 总结 B树和B树 还记得我们的二叉排序树BST吗?比如就是下面这个: 结构体也就关键字和左右指针&…...

如何利用 Python 获取京东商品 SKU 信息接口详细说明

在电商领域,SKU(Stock Keeping Unit,库存进出计量的基本单元)信息是商品管理的核心数据之一。它不仅包含了商品的规格、价格、库存等关键信息,还直接影响到库存管理、价格策略和市场分析等多个方面。京东作为国内知名的…...

【机器学习】第二章模型的评估与选择

A.关键概念 2.1 经验误差和过拟合 经验误差与泛化误差:学习器在训练集上的误差为经验误差,在新样本上的误差为泛化误差 过拟合:学习器训练过度后,把训练样本自身的一些特点当作所有潜在样本具有一般性质,使得泛化性能…...

[PMIC]PMIC重要知识点总结

PMIC重要知识点总结 摘要:PMIC (Power Management Integrated Circuit) 是现代电子设备中至关重要的组件,负责电源管理,包括电压调节、电源转换、电池管理和功耗优化等。PMIC 中的数字部分主要涉及控制逻辑、状态机、寄存器配置、通信接口&am…...

LVGL- Calendar 日历控件

1 日历控件 1.1 日历背景 lv_calendar 是 LVGL(Light and Versatile Graphics Library)提供的标准 GUI 控件之一,用于显示日历视图。它支持用户查看某年某月的完整日历,还可以实现点击日期、标记日期、导航月份等操作。这个控件…...

ubuntu安装google chrome

更新系统 sudo apt update安装依赖 sudo apt install curl software-properties-common apt-transport-https ca-certificates -y导入 GPG key curl -fSsL https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor | sudo tee /usr/share/keyrings/google-chrom…...

如何开发专业小模型

在专业领域场景下,通过针对性优化大模型的词汇表、分词器和模型结构,确实可以实现参数规模的显著缩减而不损失专业能力。这种优化思路与嵌入式设备的字库剪裁有相似性,但需要结合大模型的特性进行系统性设计。以下从技术可行性、实现方法和潜…...

EXO 可以将 Mac M4 和 Mac Air 连接起来,并通过 Ollama 运行 DeepSeek 模型

EXO 可以将 Mac M4 和 Mac Air 连接起来,并通过 Ollama 运行 DeepSeek 模型。以下是具体实现方法: 1. EXO 的分布式计算能力 EXO 是一个支持 分布式 AI 计算 的开源框架,能够将多台 Mac 设备(如 M4 和 Mac Air)组合成…...

Git Worktree 使用

新入职了一家公司,发现不同项目用的使用一个 git 仓库管理。不久之后我看到这篇文章。 Git 的设计部​​分是为了支持实验。一旦你确定你的工作被安全地跟踪,并且存在安全的状态,以便在出现严重错误时可以恢复,你就不会害怕尝试新…...

【Linux网络】内网穿透

内网穿透 基本概念 内网穿透(Port Forwarding/NAT穿透) 是一种网络技术,主要用于解决处于 内网(局域网)中的设备无法直接被公网访问 的问题。 1. 核心原理 内网与公网的隔离:家庭、企业等局域网内的设备…...

反射机制动态解析

代码解释与注释 package com.xie.javase.reflect;import java.lang.reflect.Field; import java.lang.reflect.Modifier;public class ReflectTest01 {public static void main(String[] args) throws ClassNotFoundException {// 1. 获取java.util.HashMap类的Class对象Class…...

10 分钟打造一款超级马里奥小游戏,重拾20 年前的乐趣

我正在参加CodeBuddy「首席试玩官」内容创作大赛,本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 你好,我是悟空。 前言 小时候看到村里的大朋友家里都有一款 FC 游戏机,然后旁边还放…...

鸿蒙ArkUI体验:Hexo博客客户端开发心得

最近部门也在跟进鸿蒙平台的业务开发,自己主要是做 Android 开发,主要使用 Kotlin/Java 语言。,需要对新的开发平台和开发模式进行学习,在业余时间开了个项目练手,做了个基于 Hexo 博客内容开发的App。鸿蒙主要使用Ark…...

人工智能100问☞第25问:什么是循环神经网络(RNN)?

目录 一、通俗解释 二、专业解析 三、权威参考 循环神经网络(RNN)是一种通过“记忆”序列中历史信息来处理时序数据的神经网络,可捕捉前后数据的关联性,擅长处理语言、语音等序列化任务。 一、通俗解释 想象你在和朋友聊天,每说一句话都会根据之前的对话内容调整语气…...

【springcloud学习(dalston.sr1)】Zuul路由访问映射规则配置及使用(含源代码)(十二)

该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍(含源代码)(一) springcloud学习(dalston.sr1)系统文章汇总如下: 【springcloud学习(dalston…...

STM32IIC协议基础及Cube配置

STM32IIC协议基础及Cube配置 一,IC协议简介1,核心特点2,应用场景 二,IC协议基础概念1,总线结构2,主从架构3,设备寻址4,起始和停止条件5,数据传输6,应答机制 三…...

Python异常模块和包

异常 当检测到一个错误时,Python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的“异常”, 也就是我们常说的BUG 例如:以r方式打开一个不存在的文件。 f open(‘python1.txt’,‘r’,encoding‘utf-8’) 当我们…...

每日算法刷题Day9 5.17:leetcode定长滑动窗口3道题,用时1h

9. 1652.拆炸弹(简单&#xff0c;学习) 1652. 拆炸弹 - 力扣&#xff08;LeetCode&#xff09; 思想 为了获得正确的密码&#xff0c;你需要替换掉每一个数字。所有数字会 同时 被替换。 如果 k > 0 &#xff0c;将第 i 个数字用 接下来 k 个数字之和替换。如果 k < 0…...

题单:递归求和

宣布一个重要的事情&#xff0c;我的洛谷有个号叫 题目描述 给一个数组 a:a[0],a[1],...,a[n−1]a:a[0],a[1],...,a[n−1] 请用递归的方式出数组的所有数之和。 提示&#xff1a;递推方程 f(x)f(x−1)a[x]f(x)f(x−1)a[x]; 输入格式 第一行一个正整数 n (n≤100)n (n≤100)…...

手动实现 Transformer 模型

本文使用 Pytorch 库手动实现了传统 Transformer 模型中的多头自注意力机制、残差连接和层归一化、前馈层、编码器、解码器等子模块&#xff0c;进而实现了对 Transformer 模型的构建。 """ Title: 解析 Transformer Time: 2025/5/10 Author: Michael Jie &quo…...

【鸿蒙开发避坑】使用全局状态变量控制动画时,动画异常甚至动画方向与预期相反的原因分析以及解决方案

【鸿蒙开发避坑】使用全局状态变量控制动画&#xff0c;动画异常甚至动画方向相反的原因分析以及解决方案 一、问题复现1、问题描述2、问题示意图 二、原因深度解析1、查看文档2、调试3、原因总结&#xff1a;&#xff08;1&#xff09;第一次进入播放页面功能一切正常的原因&a…...

天拓四方锂电池卷绕机 PLC 物联网解决方案

近年来&#xff0c;锂电制造行业作为新能源领域的核心支柱产业&#xff0c;呈现出迅猛发展的态势&#xff0c;市场需求持续高涨。在此背景下&#xff0c;行业内对产品质量、生产效率以及成本控制等方面提出了更为严苛的要求。锂电制造流程涵盖混料、涂布、辊压、分切、制片、卷…...

RFID系统:技术解析与应用全景

一、技术架构与运行逻辑 RFID&#xff08;Radio Frequency Identification&#xff09;系统通过无线电波实现非接触式数据交互&#xff0c;其核心由三部分组成&#xff1a; 电子标签&#xff08;Tag&#xff09;&#xff1a; 无源标签&#xff1a;依赖读写器电磁场供电&…...

hbuilderX 安装Prettier格式化代码

一、打开插件安装 搜索输入&#xff1a;Prettier 安装后&#xff0c;重启hbuilderX &#xff0c;再按AltShiftF 没安装Prettier格式化&#xff1a; import {saveFlow,getTemplate } from "../../api/flowTemplate.js"; 安装Prettier格式化后&#xff1a; import …...

Python-92:最大乘积区间问题

问题描述 小R手上有一个长度为 n 的数组 (n > 0)&#xff0c;数组中的元素分别来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]。小R想从这个数组中选取一段连续的区间&#xff0c;得到可能的最大乘积。 你需要帮助小R找到最大乘积的区间&#xff0c;并输出这…...

Compose笔记(二十三)--多点触控

这一节主要了解一下Compose中多点触控&#xff0c;在Jetpack Compose 中&#xff0c;多点触控处理需要结合Modifier和手势API来实现&#xff0c;一般通过组合 pointerInput、TransformableState 和 TransformModifier 来创建支持缩放、旋转和平移的组件。 一、 API 1. Pointer…...

2025.05.17淘天机考笔试真题第一题

📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 01. 魔法棋盘构造 问题描述 LYA 正在设计一款魔法棋盘游戏。游戏棋盘由 2 n 2 \times n...

python的漫画网站管理系统

目录 技术栈介绍具体实现截图![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/0ed2084038144499a162b3fb731a5f37.png)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/a76a091066f74a80bf7ac1be489ae8a8.png)系统设计研究方法&#xff1a;设计步骤设计流程核…...

系统架构设计(十):结构化编程

定义 结构化编程是一种遵循清晰逻辑结构、避免使用 goto 的编程方法。它强调使用有限的三种基本控制结构来组织程序&#xff0c;提高程序的可读性、可维护性和可测试性。 它是现代程序设计的基础&#xff0c;被广泛应用于命令式语言&#xff08;如 C、Pascal、Java&#xff0…...

系统架构设计(七):数据流图

定义 数据流图&#xff08;Data Flow Diagram, DFD&#xff09;是一种用于表示信息系统数据流转及处理过程的图形工具。 它反映系统功能及数据之间的关系&#xff0c;是结构化分析与设计的重要工具。 主要符号 符号说明描述举例方框外部实体&#xff08;源或终点&#xff09…...

BrepGen中的几何特征组装与文件保存详解 deepwiki occwl OCC包装库

有这种好东西我怎么不知道 AutodeskAILab/occwl: Lightweight Pythonic wrapper around pythonocc 组装几何特征以创建B-rep模型 保存为STEP和STL文件细说 Fast 快速 Searched across samxuxiang/BrepGen Ill explain how BrepGen assembles geometric features to create B-r…...

QT6 源(105)篇二:阅读与注释 QAction,给出源代码

&#xff08;5&#xff09;本源代码来自于头文件 qaction . h &#xff1a; #ifndef QACTION_H #define QACTION_H#include <QtGui/qtguiglobal.h> #if QT_CONFIG(shortcut) # include <QtGui/qkeysequence.h> #endif #include <QtGui/qicon.h> #include &…...

复旦微FMQL调试笔记:PS网口

引言 FPGA&#xff0c;全程现场可编程门阵列&#xff0c;是指一切通过软件手段更改、配置器件内部连接结构和逻辑单元&#xff0c;完成既定设计功能的数字集成电路。换个简单通俗的介绍方式&#xff0c;就好比一个全能的运动员&#xff0c;FPGA就是这么神奇的可以通过设定而实…...

SpringBoot启动流程深入分析

文章目录 背景启动流程listeners.starting先获取运行监听器获取SpringApplicationRunListener的实例监听器接口从spring.factories中加载数据&#xff0c;这里有本地缓存监听启动发布starting事件 prepareEnvironment准备环境获取或创建环境配置环境 createApplicationContext创…...

Linux - 2.系统命令

1.帮助命令 1.help [root@localhost /]# cp --help1.查看命令的信息和参数2.只能显示shell内部的命令信息3.help命令第一部分是概述,第二部分是参数详解,第三部分是说明和注意 # 使用语法 Usage: cp [OPTION]... [-T] SOURCE DESTor: cp [OPTION]... SOURCE... DIRECTORYor:…...

CSP 2024 提高级第一轮(CSP-S 2024)单选题解析

单选题解析 第 1 题 在 Linux 系统中&#xff0c;如果你想显示当前工作目录的路径&#xff0c;应该使用哪个命令&#xff1f;&#xff08;A&#xff09; A. pwd B. cd C. ls D. echo 解析&#xff1a;Linux 系统中&#xff0c;pwd命令可以显示当前工作目录的路径。pwd&#x…...

JavaScript运算符

在JavaScript开发中&#xff0c;运算符是编程的基础工具。它们用于执行各种操作&#xff0c;从简单的数学计算到复杂的逻辑判断。本文将深入探讨JavaScript中的各种运算符&#xff0c;包括算术运算符、比较运算符、布尔运算符、位运算符以及其他一些特殊运算符。 一、算术运算…...

无线信道的噪声与干扰

目录 1. 无线信道(wireless channel)与电磁波 2.1 电磁波的传输(无线信道传输) 2.2 视线(line of sight)传播与天线高度 2. 信道的数学模型 2.1 调制信道模型 2.1.1 加性噪声/加性干扰 2.1.2 乘性噪声/乘性干扰 2.1.3 随参信道/恒参信道 2.2 编码信道模型 2.3 小结 …...

计算机视觉与深度学习 | Python实现EMD-CNN-LSTM时间序列预测(完整源码、数据、公式)

EMD-CNN-LSTM 1. 环境准备2. 数据生成(示例数据)3. EMD分解4. 数据预处理5. CNN-LSTM模型定义6. 模型训练7. 预测与重构8. 性能评估核心公式说明1. 经验模态分解(EMD)2. CNN-LSTM混合模型参数调优建议扩展方向典型输出示例以下是使用Python实现EMD-CNN-LSTM时间序列预测的完…...

基于Yolov8+PyQT的老人摔倒识别系统源码

概述 随着人工智能技术的普及&#xff0c;计算机视觉在安防领域的应用日益广泛。幽络源本次分享的​​基于Yolov8PyQT的老人摔倒识别系统​​&#xff0c;正是针对独居老人安全监护的实用解决方案。该系统通过深度学习算法实时检测人体姿态&#xff0c;精准识别站立、摔倒中等…...

【网络入侵检测】基于Suricata源码分析运行模式(Runmode)

【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全&#xff0c;欢迎关注与评论。 1. 概要 &#x1f44b; 在 Suricata 中抽象出线程、线程模块和队列三个概念&#xff1a;线程类似进程&#xff0c;可多线程并行执行操作&#xff1b;监听、解码、检…...

深入解析:java.sql.SQLException: No operations allowed after statement closed 报错

在 Java 应用程序开发过程中&#xff0c;尤其是涉及数据库交互时&#xff0c;开发者常常会遇到各种各样的异常。其中&#xff0c;java.sql.SQLException: No operations allowed after statement closed是一个较为常见且容易令人困惑的错误。本文将深入剖析这一报错&#xff0c…...

ARM-Linux 完全入门

1.准备部分 1.1 虚拟机安装 准备VMware软件、ubuntu系统镜像安装过程 VMware安装 破解&#xff08;自己百度破解码&#xff0c;多试几个网址&#xff0c;会有能用的&#xff09;Ubuntu安装 配置联网 桥接 虚拟机Ubuntu系统必须能连接到外网&#xff0c;不然不能更新软件安装…...