【Linux内核系列】:文件ELF格式详解
🔥 本文专栏:Linux
🌸作者主页:努力努力再努力wz
💪 今日博客励志语录:
“人生没有白走的路,你踩过的荆棘、蹚过的泥泞,都会在某一刻,变成你脚下的风。”
★★★ 本文前置知识:
动静态库详解
那么在上一篇文章中,我详解了动静态库是什么以及如何制作我们自己的第三方的动静态库,那么制作完成之后,又用什么样的指令让链接器找到我们自己制作的动静态将其链接,而今天这篇文章的主要内容则是围绕底层,而其中动静态库的链接其中就要涉及到文件的ELF格式,那么文件的ELF格式很多讲Linux操作系统的博主其实很少提及这个东西,但是我认为学习它是很有必要的,了解它的结构不仅能够理解清楚本篇博客所讲的动静态链接是如何做到的,并且理解了ELF格式,我们还能打破语言与系统之间的一层隔阂,那么废话不多说,让我们进入正文的学习
ELF格式是什么
那么很多人或许听说过或者压根就没听说这个专有名词,也就是ELF,那么ELF它究竟是个什么呢?
那么ELF其实没有你想象的那么邪乎或者高大尚,那么首先给它下一个定义,那么ELF就是Linux以及unix下的一个文件的格式
那么什么是所谓的格式呢,那么举一个例子,就好比在大学期间你老师要求你要给他上交一份实验报告,然后你爽快的答应了,接着立马就写完了实验报告然后上交给你的老师,但是不幸的是,你老师只是瞟了一眼你的实验报告,都没有仔细阅读你实验报告的内容,那么就将实验报告给你打回来了,那么你很疑惑的去找你的老师去询问原因,那么你的老师只是轻描淡写的回复一句:“你的实验报告的格式都不对,你的内容没按照我上课要求的结构来写,拿回去重新写。”然后你接着回去问同学才知道,老师要求的一个内容的格式是什么的,也就是第一栏是实验结果,第二栏是实验过程,第三栏是实验心得,那么得按照这个布局写,那么你最终修改你的实验报告之后,上交给老师终于顺利过关
那么刚才就是想通过这个例子告诉读者,那么所谓的ELF其实就是一种规定文件内容的格式或者说布局,就像刚才的例子一样,那么你的实验报告的内容必须按照你老师的要求来划分来布局,同理这里的ELF格式就规定Linux下的文件的内容应该按照怎么样的格式或者结构来布局
现在知道了ELF的概念之后,那么ELF的格式究竟长什么样子呢,那么它规定文件是按照这样的格式来划分或者说布局:
那么它将文件的内容分成了四个部分,那么每一个部分都有各自的作用,那么他们分别是:
elf头
程序头表
段
节头表
那么想必你肯定对它们的作用以及构成感到陌生,那么没有关系,你先记住ELF规定下的文件的构成的这四个部分,而所有的可执行文件就好比学生,那么他可能对自己的实验报告有各种各样的想法与创意,那么无论他有多么的想要在自己的实验报告上施展才华,但是还是不得不遵守老师的要求,必须按照这个格式来写,那么ELF格式就像一个法规一样约束着文件,那么之所以这么规定,那么肯定有它的好处的
而其中应用ELF文件格式的文件类型则是三种,分别是可重定位文件以及可执行文件以及动态库文件,也就意味着只有这三个类型的文件的内容是必须按照ELF格式来组织的
那么我们可以在Linux上输入readelf指令来查看可执行文件的ELF格式
现在我有一个已经编译链接好的test.exe可执行文件:
//查看ELF程序头表
readelf -l test.exe
//查看ELF头
readelf -h test.exe
//查看ELF节头表
readelf -S test.exe
如何形成ELF格式
那么我们知道应用ELF格式的文件类型只有三种,分别是可执行文件以及动态库文件以及可重定位文件,那么可执行文件以及动态库文件我们知道是什么,而对于可重定位文件,我们可能会感到有点陌生,那么可重定位文件究竟是什么?
我们知道要形成可执行文件需要源文件经过编译以及链接这两个过程才能形成最终的可执行文件,那么所谓的可重定位文件其实就是源文件只编译不链接形成的一系列的.o文件,但是至于为什么称呼它为可重定位文件我在下文会解释说明
也就是说应用ELF格式的文件类型分别是目标文件以及可执行文件以及动态库文件,而可执行文件的生成则是需要源文件经过编译以及链接这两个阶段,那么也就意味着ELF格式一定是在编译的某个阶段生成的,那么也就需要在我们再来完善之前对于生成可执行文化的编译以及链接的过程的理解。
结合ELF来重新完善理解编译与链接全过程
那么生成可执行文件首先需要依赖源文件以及保存函数声明的头文件,那么其中会经历编译以及链接这两个阶段,而其中编译又分为预处理以及语法语义分析以及编译和汇编这四个子过程,那么我们结合ELF格式来完善编译与链接的全过程:
那么首先预处理阶段会进行头文件展开的工作,那么此时源文件会将源文件中#include XXX.h语句给替换为引用的头文件中的内容,那么编译器会逐字逐句拷贝头文件的内容将其复制拷贝到引用该头文件的源文件中,此时还会经历宏替换以及注释消去等工作,那么此时经过预处理阶段会生成后缀名为.i的中间临时文件,而此时由于头文件的内容已经全部拷贝复制到源文件中,那么头文件就不在参与后续的流程了,那么此时预处理阶段后的生成的临时文件的内容还是c/c++代码
经过预处理阶段紧接着就是语法以及语义分析了,那么这个过程的核心内容可以简单理解检查代码中是否有语法错误,其中会构建一棵语法树来进行分析,那么在这个阶段还会收集一些符号信息,比如解析全局变量以及局部变量的声明来确定他们在符号表中对应的符号
接着是编译,那么编译阶段会将之前的.i的中间临时文件的代码由汇编器给转换为汇编码
最后则是汇编,那么在这个阶段就会生成ELF格式的雏形,为什么说是雏形呢,是因为ELF格式是要求包含ELF头以及程序头表以及段以及节头表,而这里的目标.o文件则是没有对应的程序头表,而程序头表则是在链接阶段生成,所以说是雏形。
并且此阶段还会生成一个局部的符号表,由于编译器是以一个文件作为独立的编译单元来进行编译的,也就是说编译器只能看到编译的该文件的内容而看不到其他文件的内容,那么如果该文件只有函数的声明而没有函数的定义,那么此时该函数对应的符号表中的条目就会被标记为未定义,那么会在链接阶段进行处理,而如果该文件中有对应函数的定义,那么此时就会在符号表中填入定义对应的一个逻辑地址,由于生成该.o文件将实际的文件内容进行了分类也就是函数的定义部分被划分进了代码段.text,而其中的全局变量被划分进了数据段.data,那么此时符号表中记录的对应的函数的定义的地址是在该文件中在相对于代码段的起始位置的相对偏移量,所以这里是逻辑地址而不是所谓的虚拟地址
,更不是物理地址,因为此时还在链接阶段,都没形成可执行文件,更不存在加载到内存分配物理地址,一定要注意区分
所以上文我们埋了一个伏笔,也就是为什么叫目标文件为可重定位文件,就是因为此时符号表记录的是各个符号是逻辑地址而不是虚拟地址,而之前我们Linux进程部分就提到过,CPU到时候运行的指令,接收到的都是虚拟地址,所以必定要将这其中的符号表中的逻辑地址以及翻译成指令的代码段部分中涉及到的逻辑地址的内容给全部转换为虚拟地址,那么这个工作就叫重定位,其中我们链接器肯定得知道代码的哪些部分使用了逻辑地址,比如调用函数就必然会涉及到逻辑地址,那么此时文件内部就会维护一个可重定位表,那么这个表我们就可以简单理解为帮组链接器寻找到代码中哪些位置使用了逻辑地址从而将其重定位转换为虚拟地址,
那么这就是为什么叫目标文件为重定位文件的原因,但是重定位这个工作不是在编译阶段完成的,而是在链接阶段完成的
那么此时的源文件在编译阶段形成了.o文件,那么此时进入链接阶段,那么链接阶段会获取每一个.o文件的局部符号表然后生成一个全局的符号表,那么其中就会合并每一个局部符号表中相同的符号来作为为全局符号表中的一个条目,然后为其分配一个唯一的逻辑地址,那么有的符号有定义,而有的符号没有定义,那么此时链接器会先去各个.o文件中的局部符号表中查找是否有对应的符号的定义,如果有就填入,而如果发现多个文件的局部符号表都有该函数的定义,那么则会报一个重定义的错误,而如果此时链接器没有在所有的.o文件中找到该函数的定义的话,那么此时链接器如果手上持有静态库文件的话,那么接下来它会去静态库中寻找,而静态库的本质就是一系列.o文件的集合,那么它查询的方式和之前是类似的,也就是去这些.o文件中的局部符号表中寻找,那么一旦找到,那么此时就填入进该符号的地址,并且将其对应的函数的定义给拷贝过来,那么如果说静态库还没有找到,那么此时链接器只能将认为该函数的定义可能在动态库中,但是该链接器无法看到动态库中的函数的定义,而只有在该程序运行时,由动态链接器来完成,那么此时会将该符号标记为动态链接,并将其记录整合进动态符号表中
所以这里链接器填入符号表中的定义的地址优先级是先确定可执行文件依赖的.o文件中是否有定义,那么有则直接将其填入,不需要到静态库以及动态库中寻找,如果没有,那么假设该链接器持有静态库文件的话,那么则会到静态库libxxx.a文件中的一系列.o文件中去搜索是否有对应的定义,并且如果假设该静态库中的不同的.o文件均包含该函数的定义,那么则是按照链接器搜索的顺序来引用其中第一个寻找到的.o文件的定义在将其复制拷贝到可执行文件中,最后如果.o文件以及静态库文件都没有,那么编译器只能将其视为动态库中的函数,将其尝试动态链接
那么此时完善好全局的符号表之后,下一步的工作便是重定位,那么要将逻辑地址转换为虚拟地址,而由于此时链接器将多个.o文件给合成一个可执行文件,其中就包括将各个文件相同的节比如.text以及.data给合并,那么此时就要调整每一个符号的逻辑地址,那么逻辑地址是段内便宜,那么最终重定位调整之后,那么符号定义的地址便是段偏移+段内偏移,那么该结果就是虚拟地址
比如func函数是在其.text段,那么合并所有.o文件的.text段之后,那么此时.text段基地址假设为0x112233
而func在合并段内的偏移量为假设为0x223355,那么重定位后func的逻辑地址便是0x112233+0x223355
那么重定位以及合并相同节之后,那么此时就能够生成程序头表了,那么程序头表是知道操作系统如何在内存中加载段,那么其中程序头表中的每一个条目就包含段的类型以及对应的虚拟地址以及物理地址以及读写权限等等
程序头表的形态
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000040 0x0000000000400040 0x0000000000400040 0x0001c0 0x0001c0 R 0x8
INTERP 0x000200 0x0000000000400200 0x0000000000400200 0x00001c 0x00001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x010000 0x010000 R E 0x200000
LOAD 0x010000 0x0000000000600000 0x0000000000600000 0x002000 0x002000 RW 0x200000
DYNAMIC 0x011000 0x0000000000611000 0x0000000000611000 0x0001d0 0x0001d0 RW 0x8
NOTE 0x00021c 0x000000000040021c 0x000000000040021c 0x000020 0x000020 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x011000 0x0000000000611000 0x0000000000611000 0x0001d0 0x0001d0 R 0x1
那么此时生成的可执行文件就按照标准的ELF格式所构成。
所以现在我们便能理解ELF的形成过程,以及它布局的那四个部分的内容了:
elf头
:记录该文件的配置信息以及整体的结构信息,其中就包括文件类型以及文件的程序头表的地址以及段表的地址以及段表的数量以及每一个条目的大小,还有程序入口点enter point程序头表
:指导操作系统如何加载段到内存,其中包含段的虚拟地址以及物理地址以及权限等段
:存储实际内容,包含合并每一个.o文件的.text段以及.data段节头表
:记录每一个所有的节的类型以及它的逻辑地址,用来调试
结合ELF完善进程的创建
那么由于可执行文件是最初被存放在磁盘中的,那么创建进程,那么首先就要将磁盘中存放的可执行文件给加载到内存中,那么我们知道Linux下可执行文件是按照ELF格式构成的,那么首先操作系统会读取该文件的ELF头,来获取程序的入口,然后存放到CPU的指令寄存器当中,然后接着操作系统会读取程序头表,那么程序头表记录了该程序的段的信息其中就包括虚拟地址
而我们知道操作系统在将可执行文件中的数据加载到内存的同时会在内核中创建给进程对应的task_struct结构体,那么task_struct结构体就是记录了该进程的地址空间以及对应的页表,而页表中记录了各个页为单位的数据的虚拟地址到物理地址的映射,那么操作系统会根据程序头表来完善创建出页表,那么其中页表中的虚拟地址不一定遵循程序头表中的虚拟地址,因为程序头表只是给操作系统加载内存的建议,那么虚拟地址具体怎么分配还是由操作系自己决定,那么创建出页表之后,以后虚拟到物理的转换就交给页表来完成而不需要程序头表了
那么当我们该进程被调度的时候,那么CPU就会从指令寄存器来依次读取指令,那么其中指令分为操作码与操作数,那么其中的操作数可能是一个数据或者是调用函数的地址,比如读取的指令是call 0x112233,那么call后面的操作数就是地址,而CPU此时读取的所有的指令中涉及到的地址都是虚拟地址,那么此时就需要根据页表转换为实际的物理内存地址来获取目标数据
结语
那么这就是本篇文章全部的内容,那么本篇文章也是博主尽可能尽全力的用通俗易懂的语言来讲解ELF格式,那么这篇文章就是我对ELF格式的一个全部理解与思考了,那么我看csdn上讲解ELF格式的博主并不多,并且讲ELF格式的博主中的内容又太过于结论化以及专业化了,上来就给你抛出ELF格式有啥,怎么用就结束了,那么之所以做这期博客的原因,就是觉得学习ELF格式,能加深对CPU的执行程序以及在Linux下你用c或者c++写的源文件最终形成可执行程序的一个形态与过程的理解,那么能够打通语言与系统方向的一些隔阂,这也是我写这篇博客的初衷,当然涉及到ELF格式相关的内容以及细节确实太多了,那么本文确实叙述不完,那么读者可以下去自己查阅了解,那么如果本文有帮组到你的话,那么还请三连加关注哦,你的支持就是我创作的最大动力!
相关文章:
【Linux内核系列】:文件ELF格式详解
🔥 本文专栏:Linux 🌸作者主页:努力努力再努力wz 💪 今日博客励志语录: “人生没有白走的路,你踩过的荆棘、蹚过的泥泞,都会在某一刻,变成你脚下的风。” ★★★ 本文前置…...
CubeMx ——新建工程
新建工程 选择芯片 设置主频 选择调试口 选择晶振口 设置 GPIO 输出 工程设置 LED 闪烁 /* USER CODE BEGIN WHILE */while (1){HAL_GPIO_TogglePin(GPIOH, GPIO_PIN_10);HAL_Delay(1000);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */...
使用postcss-px-to-viewport-8-plugin将页面转响应式
使用postcss-px-to-viewport-8-plugin将页面转响应式 背景 公司最近接了个项目,其中要求部分页面在移动端正常显示,第一方案是使用响应式,但是设计稿最后出的和Web端差别较大同时两端的功能不是完全对齐的,所以决定使用两个模块…...
Java---类与对象
类与对象 前言:一、面向对象二、类的定义1.类的定义格式2.访问修饰限定符 三、类的实例化四、this引用1.this引用2.this引用的原因 五、对象的构造和初始化1.初始化对象2.构造方法(1).构造方法的概念:(2).特性:(3).this调用:3.就地初始化4.默…...
告别桌面杂乱与充电焦虑,移速165W百变桌面充电站首发体验
告别桌面杂乱与充电焦虑,移速165W百变桌面充电站首发体验 哈喽小伙伴们好,我是Stark-C~ 先如今,家里的电子产品越来越多,手机、平板、电脑三件套已经是基础配置,还有相机、Switch、智能手表等,这些产品用…...
基于springboot+vue的农产品电商平台
开发语言:Java框架:springbootJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:…...
dom0运行android_kernel: do_serror of panic----failed to stop secondary CPUs 0
问题描述: 从日志看出,dom0运行android_kernel,刚开始运行就会crash,引发panic 解决及其原因分析: 最终问题得到解决,发现是前期在调试汇编阶段代码时,增加了汇编打印的指令,注释掉这些指令,问题得到解决。…...
MySQL 语句
MySQL 语句教程博客 MySQL 是目前广泛应用的关系型数据库管理系统,本文将详细介绍 MySQL 中常用的 SQL 语句及其应用,内容主要涵盖以下部分: DDL(数据定义语言) DML(数据操作语言) DQL&#…...
MySQL General Log
MySQL General Log MySQL General Log General Log 的开启General Log 的用法log_output 参数 MySQL主从复制:https://blog.csdn.net/a18792721831/article/details/146117935 MySQL Binlog:https://blog.csdn.net/a18792721831/article/details/146606…...
自动关机监控器软件 - 您的电脑节能助手
## 自动关机监控器 - 您的电脑节能助手 自动关机监控器是一款基于Python开发的实用工具,旨在帮助用户节省电力资源并延长电脑使用寿命。该程序通过监控用户的鼠标和键盘活动,在设定的无活动时间后自动关闭计算机,特别适合需要长时间离开电脑但…...
基于改进粒子群算法的多目标分布式电源选址定容规划(附带Matlab代码)
通过分析分布式电源对配电网的影响,以有功功率损耗、电压质量及分布式电源总容量为优化目标,基于模糊理论建立了分布式电源在配电网中选址定容的多目标优化模型,并提出了一种改进粒子群算法进行求解。在算例仿真中,基于IEEE-14标准…...
解锁健康密码:拥抱多元养生新方式
在追求高质量生活的当下,健康养生不再是一句空洞的口号,而是融入到日常生活的方方面面。它不仅关乎我们的身体健康,更与心理状态和生活品质息息相关。下面,就为大家介绍一些实用的养生知识,帮助大家开启健康生活之旅。…...
@Slf4j注解
Slf4j注解是Lombok库提供的一个注解,用于简化日志记录器的创建。使用该注解后,无需手动创建Logger实例,编译器会自动帮你完成这一步。以下是使用Slf4j注解打印日志的步骤和示例: 使用步骤 1. 引入依赖:在项目中引入SL…...
firewall-cmd添加访问规则
若要使用 **firewall-cmd** 允许 192.168.3.0/24 网段访问本地的 8088 端口,你可以按照以下步骤操作。 临时允许访问 如果你仅需临时允许该网段访问 8088 端口,可使用如下命令: firewall-cmd --add-rich-rulerule family"ipv4" …...
【Linux网络与网络编程】02.初识Socket编程
1. 数据传输的目的 前一篇文章中我们讲解了网络传输的流程,那么网络传输的目的是什么呢?难道我们只是将数据从一台主机传输到另一台主机吗? 当然不是的!因为数据是给人用的。比如:聊天是人在聊天,下载是人…...
Python库()
1.概念 Matplotlib 库:是一款用于数据可视化的 Python 软件包,支持跨平台运行,它能够根据 NumPy ndarray 数组来绘制 2D 图像,它使用简单、代码清晰易懂 Matplotlib 图形组成: Figure:指整个图形…...
CVPR-2025 | 南洋理工基于图表示的具身导航统一框架!UniGoal:通用零样本目标导航方法
作者:Hang Yin 1 ^{1} 1, Xiuwei Xu 1 ^{1} 1, Linqing Zhao 1 ^{1} 1, Ziwei Wang 2 ^{2} 2, Jie Zhou 1 ^{1} 1, Jiwen Lu 1 ^{1} 1单位: 1 ^{1} 1南洋理工大学, 2 ^{2} 2清华大学论文标题:UniGoal: Towards Universal Zero-sho…...
Banner区域
div下 justify-content:space-between 左侧测导航left 在这里插入图片描述 在这里插入图片描述...
【C++】C++11介绍列表初始化右值引用和移动语义
个人主页 : zxctscl 如有转载请先通知 文章目录 1. C11简介2. 统一的列表初始化2.1{}初始化2.2 std::initializer_list 3. 声明3.1 auto3.2 decltype3.3 nullptr 4. 范围for循环4.1 范围for的语法4.2 范围for的使用条件 5. STL中一些变化6. 右…...
基于Spring Boot的高校普法系统的设计与实现(LW+源码+讲解)
专注于大学生项目实战开发,讲解,毕业答疑辅导,欢迎高校老师/同行前辈交流合作✌。 技术范围:SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:…...
算法为舟 思想为楫:AI时代,创作何为?
在科技浪潮汹涌澎湃的当下,AI技术以前所未有的态势席卷各个领域,创作领域亦未能幸免。当生成式AI展现出在剧本撰写、诗歌创作、图像设计等方面的惊人能力时,人类创作者仿佛置身于文明演化的十字路口,迷茫与困惑交织,兴奋与担忧并存。在AI时代,创作究竟该何去何从?这不仅…...
GPT-4o 原生图像生成技术解析:从模型架构到吉卜力梦境的实现
最近不少 AI 爱好者、设计师、Vlogger 在社交平台晒出了 GPT-4o 生成的梦幻图像,尤其是吉卜力风格的作品——柔和光影、日系构图、治愈色彩、富有情感的角色表达,一下子击中了无数人的“童年回忆 审美舒适区”。 🎨 下面是一些 GPT-4o 实际生…...
无线通信技术(二):ITU、3GPP及传统波段对无线频谱的划分
本文介绍国际标准组织ITU、3GPP和传统波段对无线频谱的划分 。 一.ITU波段划分 国际电信联盟(ITU)将无线电频谱划分为多个频段,并根据频率范围和业务需求分配用途。 ITU对无线频谱的划分 带号频带名称频率范围波长范围波段名称典型应用…...
[Python学习日记-88] 并发编程之多进程 —— 队列与生产者消费者模型
[Python学习日记-88] 并发编程之多进程 —— 队列与生产者消费者模型 简介 队列 一、队列的介绍 二、队列的使用 生产者消费者模型 一、为什么要使用生产者消费者模型 二、什么是生产者消费者模型 三、生产者消费者模型的优势 四、生产者消费者模型的实现 JoinableQ…...
Vue学习笔记集--computed
computed 在 Vue 3 的 Composition API 中,computed 用于定义响应式计算属性 它的核心特性是自动追踪依赖、缓存计算结果(依赖未变化时不会重新计算) 基本用法 1. 定义只读计算属性 import { ref, computed } from vue;const count ref(…...
python之多线程,多进程理解
目录 一,什么是多线程多进程 1,1 多线程 1.2 多进程 二,多线程 2.1 使用threading模块 三,多进程 3.1 使用multiprocessing模块 3.2 多进程的优势 3.3 进程间的通信 四,如何选择多进程还是多线程 五,异步编程的替代方案(协程) 在开发过程中,提升程序的并…...
3月29日星期六今日早报简报微语报早读
3月29日星期六,农历三月初一,早报#微语早读。 1、全国公立医疗机构自3月31日起全面停止收取门诊预交金; 2、永辉超市“胖东来调改店”已达47家店 一线员工薪酬涨幅50%以上; 3、两孩家庭补10万,三孩家庭补20万&#…...
栈:隐匿于计算机科学长卷的璀璨明珠
目录 🚀前言🌟栈的概念🤔栈的两种实现形式💯数组栈实现💯链表栈实现 ⚙️数组栈与链表栈对比🐧递归与栈💻总结 🚀前言 大家好!我是 EnigmaCoder。 在计算机科学的宏大版图…...
【万字总结】前端全方位性能优化指南(七)——按需加载、虚拟列表、状态管理
现代框架高阶优化——突破复杂场景的性能临界点 当Web应用进入「十万级组件、百万级数据」的复杂场景时,传统优化手段开始触及框架底层瓶颈:Redux的单一Store引发级联渲染风暴、全量加载的首屏资源阻塞关键交互、长列表滚动导致内存飙升直至页面崩溃……这些痛点正在倒逼框架…...
合并石子 | 第十四届蓝桥杯省赛JavaB组
在桌面从左至右横向摆放着 N 堆石子。 每一堆石子都有着相同的颜色,颜色可能是颜色 0,颜色 1 或者颜色 2 中的其中一种。 现在要对石子进行合并,规定每次只能选择位置相邻并且颜色相同的两堆石子进行合并。 合并后新堆的相对位置保持不变&…...
【商城实战(94)】构建高并发的负载均衡与集群架构
【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配…...
鸿蒙开发:了解Canvas绘制
前言 本文基于Api13 系统的组件无法满足我们的需求,这种情况下就不得不自己自定义组件,除了自定义组合组件,拓展组件,还有一种方式,那就是完全的自绘制组件,这种情况,常见的场景有,比…...
Ubuntu和Windows实现文件互传
1.开启Ubuntu下的FTP服务: (1)终端输入: sudo apt-get install vsftpd(2)安装完成后: 终端输入: /etc 是 Linux 系统的全局配置文件目录,存储系统和应用程序的配置信息…...
dav_pg8_vacuum
一、VACUUM基础概念 1.1 VACUUM的作用 在PostgreSQL中,当数据被更新或删除时,系统并不会立即释放物理空间,而是将其标记为 “可重用”。 随着时间推移,表中的死元组(已删除或已被新版本覆盖的数据)会越来越…...
革新汽车安全通信技术,美格智能全系车载通信模组支持NG-eCall
根据QYR(恒州博智)的统计及预测,2024年全球汽车无线紧急呼叫(eCall)设备市场销售额达到了25.17亿美元,预计2031年将达到44.97亿美元,年复合增长率(CAGR 2025-2031)为8.8%…...
Ubuntu桌面环境下网络设置选项缺失问题解决
一、问题现象 在Ubuntu桌面环境中,网络设置界面中仅显示VPN设置,未显示常规网络配置选项,导致无法通过图形界面修改网络配置。但通过命令行工具可正常设置网络。 二、解决方案 (一)检查网络设备状态 nmcli d 发现…...
GitHub绑定本地计算机以及仓库创建跟推送指南
GitHub绑定到本地计算机 要在本地计算机上连接到你的GitHub账户,可以通过以下步骤实现: 1. 检查和安装Git 确保你的计算机上已经安装了Git。如果还没有安装,可以从Git官网下载并安装。 2. 配置Git 打开终端(macOS或Linux&…...
【数据结构】导航
【数据结构】-CSDN博客 【数据结构】next数组、nextval数组-CSDN博客...
Java内存中的Heap(堆)的作用
Java内存中的Heap(堆)的作用 在 Java 的内存模型中,Heap(堆) 是 JVM(Java Virtual Machine)管理的运行时数据区域之一,主要用于存储程序运行过程中动态分配的对象和数据。它是 Java…...
Python控制结构详解
前言 一、控制结构概述 二、顺序结构 三、选择结构(分支结构) 1. 单分支 if 2. 双分支 if-else 3. 多分支 if-elif-else 4.实际应用: 四、循环结构 1. for循环 2. while循环 3. 循环控制语句 五、异常处理(try-except)…...
2023第十四届蓝桥杯大赛软件赛国赛C/C++ 大学 B 组(真题题解)(C++/Java题解)
本来想刷省赛题呢,结果一不小心刷成国赛了 真是个小迷糊〒▽〒 但,又如何( •̀ ω •́ )✧ 记录刷题的过程、感悟、题解。 希望能帮到,那些与我一同前行的,来自远方的朋友😉 大纲: 一、子2023-ÿ…...
JVM介绍
JVM类加载器 栈指令重排序 类的JVM内存分配 堆内存GC模型...
HTML输出流
HTML 输出流 JavaScript 中**「直接写入 HTML 输出流」**的核心是通过 document.write() 方法向浏览器渲染过程中的数据流动态插入内容。以下是详细解释: 一、HTML 输出流的概念 1. 动态渲染过程 HTML 文档的加载是自上而下逐行解析的。当浏览器遇到 <script&…...
Kafka 的高可用性
Kafka 的高可用性主要通过副本机制、ISR(In-Sync Replicas)列表和控制器 Broker 来实现。这些机制共同确保了 Kafka 集群在部分节点故障时仍然可以正常运行,数据不会丢失,并且服务不会中断。 1. 副本机制 Kafka 的副本机制是其高…...
Centos7,tar包方式部署rabbitmq-3.7.6
1. 环境准备 安装编译工具和依赖包 yum -y install make gcc gcc-c glibc-devel m4 perl openssl openssl-devel ncurses-devel ncurses-devel xz xmlto perl 2. Erlang环境搭建 版本对应:https://www.rabbitmq.com/docs/which-erlang 解压到指定目录 tar -xv…...
RISC-V AIA学习3---APLIC 第二部分(APLIC 中断域的内存映射控制区域)
每个中断域都有一个专用的内存映射控制区域,用来处理该中断域的中断。 控制区域的大小是 4KB 的倍数,对齐到 4KB 边界。最小的有效控制区域是 16KB。 1. 控制区域的基本结构:部门文件柜 每个中断域就像公司的一个部门,有自己的 …...
顶刊【遥感目标检测】【TGRS】FFCA-YOLO遥感图像小目标检测
FFCA-YOLO for Small Object Detection in Remote Sensing Images FFCA-YOLO遥感图像小目标检测 0.论文摘要 摘要——特征表征不足、背景干扰等问题使得遥感图像中的小目标检测任务极具挑战性。尤其在算法需部署于星载设备进行实时处理时,需在有限计算资源下对精度…...
【人工智能】从 Llama 到 DeepSeek:开源大模型的演进与技术对比
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着人工智能的迅猛发展,开源大语言模型(LLM)在自然语言处理领域扮演着越来越重要的角色。本文从 Meta 的 Llama 系列开始,追溯开源大模…...
【PCB工艺】时序图(Timing Diagram)
时序图(Timing Diagram)是描述数字电路信号随时间变化的图示,广泛用于分析和设计时序逻辑电路,如锁存器(Latch)、触发器(Flip-Flop)、计数器、状态机等。这篇文章从时序图的原理、构…...
MATLAB 中,并行池(Parallel Pool)自动关闭的情况
在 MATLAB 中,并行池(Parallel Pool)的行为可以通过设置进行控制,但默认情况下,并行池不会自动关闭,除非满足某些条件或显式调用关闭命令。以下是关于并行池自动关闭机制的详细说明: 自动关闭的…...