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

Linux内存管理--系列文章肆

一、引子
上篇文章介绍了目标文件,也就是讲到编译过程中的汇编这个阶段。本篇要讲目标文件怎么变成一个可执行文件的,介绍编译过程中的链接
链接主要分为两种,静态链接动态链接。它们本质上的区别,是在程序的编译和运行过程中使用库的方式不同。

特性静态链接动态链接
文件大小较大较小
运行独立性高(无需外部库)低(需要外部库)
启动速度较快稍慢
内存使用不共享库,可能使用更多内存库共享,节省内存
更新和维护更新库需要重新编译和分发整个程序更新库只需替换库文件
兼容性无库版本问题,较高可能存在库版本冲突问题

二、静态链接要做什么

在编译时将所有必要的库和模块直接嵌入到生成的可执行文件中,这是静态链接的定义。这意味着可执行文件包含了所有运行所需的代码,因此无需依赖外部库文件。
下面将用两个Demo来示范,1.c2.c

这是1.c
extern int a;
extern void func1(void);int main()
{int b = 0;func1();return 0;
}
这是2.c
int a = 0;void func1(void)
{int c = 0;c++;
}
 objdump -h 1.o1.o:     文件格式 elf64-x86-64节:
Idx Name          Size      VMA               LMA               File off  Algn0 .text         0000001f  0000000000000000  0000000000000000  00000040  2**0CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE1 .data         00000000  0000000000000000  0000000000000000  0000005f  2**0CONTENTS, ALLOC, LOAD, DATA2 .bss          00000000  0000000000000000  0000000000000000  0000005f  2**0ALLOC3 .comment      0000002c  0000000000000000  0000000000000000  0000005f  2**0CONTENTS, READONLY4 .note.GNU-stack 00000000  0000000000000000  0000000000000000  0000008b  2**0CONTENTS, READONLY5 .note.gnu.property 00000020  0000000000000000  0000000000000000  00000090  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA6 .eh_frame     00000038  0000000000000000  0000000000000000  000000b0  2**3CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATAobjdump -h 2.o2.o:     文件格式 elf64-x86-64节:
Idx Name          Size      VMA               LMA               File off  Algn0 .text         00000016  0000000000000000  0000000000000000  00000040  2**0CONTENTS, ALLOC, LOAD, READONLY, CODE1 .data         00000000  0000000000000000  0000000000000000  00000056  2**0CONTENTS, ALLOC, LOAD, DATA2 .bss          00000004  0000000000000000  0000000000000000  00000058  2**2ALLOC3 .comment      0000002c  0000000000000000  0000000000000000  00000058  2**0CONTENTS, READONLY4 .note.GNU-stack 00000000  0000000000000000  0000000000000000  00000084  2**0CONTENTS, READONLY5 .note.gnu.property 00000020  0000000000000000  0000000000000000  00000088  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA6 .eh_frame     00000038  0000000000000000  0000000000000000  000000a8  2**3CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA

ld 1.o 2.o -e main -o a.out

objdump -h a.out a.out:     文件格式 elf64-x86-64节:
Idx Name          Size      VMA               LMA               File off  Algn0 .note.gnu.property 00000020  00000000004001c8  00000000004001c8  000001c8  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA1 .text         00000035  0000000000401000  0000000000401000  00001000  2**0CONTENTS, ALLOC, LOAD, READONLY, CODE2 .eh_frame     00000058  0000000000402000  0000000000402000  00002000  2**3CONTENTS, ALLOC, LOAD, READONLY, DATA3 .bss          00000008  0000000000404000  0000000000404000  00003000  2**2ALLOC4 .comment      0000002b  0000000000000000  0000000000000000  00002058  2**0CONTENTS, READONLY

2.1 地址和空间的分配

我们将上面两个文件变成目标文件后,每个目标文件都是有自己的代码段,数据段,bss段等。但可执行文件是一个文件,那也就是说链接时要找到各文件中的各符号地址和各段地址,并将它们合并起来,并且分配运行时候的空间。
链接器会为可执行文件或共享库分配内存空间,还会为每个符号分配一个唯一的内存地址。

2.1.1 各段依次堆叠(Sequential Stacking)

最简单的一个方案,是将输入的目标文件按照次序依次叠加起来,生成输出的可执行文件或共享库。
步骤
扫描目标文件: 链接器首先会扫描所有输入的目标文件,提取每个目标文件的信息,包括代码段、数据段、BSS 段以及符号表等。
地址分配: 链接器会为可执行文件或共享库分配内存空间,并为每个符号分配一个唯一的内存地址。
生成输出文件: 链接器会将所有输入的目标文件的内容依次复制到输出文件中,并根据符号表修正符号地址。
特点
实现简单: 按序叠加的实现代码比较简单,易于理解和开发。
效率低下: 按序叠加会导致输出文件体积较大,并且可能会产生大量的内存碎片,降低程序的运行效率。对于一些硬件来讲,段的装载和空间对齐单位是页,也就是4KB大小。即便只有1B大小也会分配出4KB的内存。
不适用于大型项目: 对于大型项目,按序叠加会导致链接过程非常耗时,并且可能无法有效利用内存空间。

2.1.2 相似段合并(Merge Similar Segments)

各段依次堆叠会产生各种问题。所以在链接目标文件的过程中,可能会执行相似段合并的优化步骤,以减少可执行文件的大小并提高执行效率。相似段合并的步骤通常在优化和合并阶段进行,其主要目标是识别并合并具有相似代码或数据的段,以消除重复并节省空间。
步骤
识别相似段:链接器分析目标文件中的代码段和数据段,寻找具有相似内容的段。相似内容可能是相同的代码片段、常量数据或其他类型的数据。
合并相似段:对于找到的相似段,链接器将其合并成一个单一的段。合并过程可能涉及将重复的代码片段或数据项替换为单个引用,并确保所有引用指向合并后的段。
更新引用
在合并后的段被创建后,链接器需要更新目标文件中的所有引用,以便指向合并后的段。这可能涉及修改目标文件中的地址引用或符号表条目。
删除冗余段:完成相似段的合并后,链接器可能会删除原始目标文件中的冗余段,以释放空间并简化可执行文件的结构。

2.1.3 示例分析

a.out.text段的size就是目标文件的.text段段的size总和。a.out的VMA和LMA是有数值的,但目标文件并没有的。VMA是虚拟地址,是在链接后根据各段的大小被分配的。LMA是加载地址,在确定每个段的大小、对齐要求以及其他系统布局策略并并保证各段在内存中不会相互冲突的情况下,链接器为每个段分配一个加载地址。

有些资料会讲Linux中的.text段默认会分配到0x08048094.data段默认会分配到0x08049108,说是ELF文件默认从该地址分配。但目前新一点版本的静态链接的可执行文件的默认加载地址也不是固定的,它的加载地址同样是由操作系统的动态链接器 ld.so(或者其替代品)在可执行文件被加载时动态确定的。如果强制指定可执行文件的加载地址,可以使用一些链接选项来指定加载地址,例如-Wl,-Ttext-segment=地址 。该技术是地址空间布局随机化(ASLR,Address Space Layout Randomization),主要目的是在每次加载可执行文件时,随机选择加载地址,从而增加攻击者利用程序漏洞的难度。

File off是各个段的起始偏移量。这个偏移量表示了每个段在文件中的位置,即相对于文件的起始位置的偏移量。在链接时,File off的作用主要是用来确定每个段在最终生成的可执行文件中的位置,并且在重定位阶段被使用。在生成最终的可执行文件时,File off 信息通常会被包含在可执行文件的头部或段表中,以便操作系统在加载可执行文件时正确地映射每个段到内存中的位置。

2.2 符号解析和重定位

符号解析和重定位对于程序的正确运行至关重要。如果没有符号解析,程序将无法找到符号定义的变量、函数等对象。如果没有重定位,程序将无法在不同的内存地址上运行。
一般出现在该步骤的错误
符号未定义: 程序中使用了未定义的符号。
符号重复定义: 程序中有多个符号定义使用了相同的名称。
符号地址冲突: 两个或多个符号被分配了相同的地址。

2.2.1 符号解析(Symbol Resolution)

通过符号解析,链接器能够确保所有的符号引用都能正确指向其在其他目标文件或库中的定义,从而使得最终生成的可执行文件能够正确地执行。

链接器首先解析所有目标文件中的符号(函数和变量)。每个目标文件包含的符号可以分为以下两类
定义的符号:在目标文件中定义的符号(例如函数实现或变量定义)。
引用的符号:目标文件中使用但未定义的符号(例如外部函数或变量)。
链接器需要确保所有引用的符号都能在某个目标文件或库中找到定义。

主要过程
定义和引用:在程序中,符号可以是函数、变量或其他命名实体。在目标文件中,这些符号可以被定义(有实际的实现)或引用(被使用但未定义)。
扫描目标文件:链接器首先会扫描所有的目标文件和库文件,从中提取出所有的符号。这个过程包括解析目标文件的符号表、重定位表等信息。
符号解析:对于每个引用的符号,链接器需要在其他目标文件或库中找到对应的定义。这可能涉及搜索多个目标文件和库文件,直到找到符号的定义。如果找不到符号的定义,链接器将会报错并提示未定义的符号。
符号表管理:链接器维护一个符号表,记录了每个符号的定义和引用情况。对于每个引用的符号,链接器会在符号表中查找其定义,以确定其在可执行文件中的实际位置。
生成符号表:在符号解析过程完成后,链接器会生成一个最终的符号表,其中包含了所有解析后的符号信息。这个符号表将被用于后续的符号重定位等操作。

2.2.2 符号重定位(Symbol Relocation)

目的是将程序中使用的符号引用(例如函数地址、变量地址等)修正为实际的内存地址。符号重定位是确保程序在不同环境下能够正确运行的关键步骤之一。

在目标文件中,符号的地址通常是相对的或未确定的。链接器需要将这些符号地址调整到它们在最终可执行文件中的实际内存地址。这一步包括以下过程
地址计算:在符号解析完成后,链接器需要计算每个符号在最终可执行文件中的内存地址。这个地址通常是相对于程序的起始地址的偏移量。
地址调整:链接器将目标文件中的所有引用符号的地址调整为其在最终可执行文件中的实际内存地址。这包括修改目标文件中的指令、数据、符号表等,以便在程序执行时正确地指向符号的位置。
重定位表:重定位表记录了需要进行重定位的符号及其偏移量。链接器根据重定位表中的信息,将引用的符号地址进行调整,以确保程序能够正确执行。
代码和数据重定位:对于代码段和数据段中的引用符号,链接器会修改指令或数据中的地址,使其指向正确的内存位置。这可能涉及修改指令中的跳转地址、函数调用地址,或者修改数据中的符号地址引用。
符号表更新:在完成符号重定位后,链接器可能会更新符号表中的符号信息,以反映符号在最终可执行文件中的实际位置。

2.2.3 示例分析

objdump -d a.out 
a.out:     文件格式 elf64-x86-64
Disassembly of section .text:
0000000000401000 <main>:401000:	f3 0f 1e fa          	endbr64 401004:	55                   	push   %rbp401005:	48 89 e5             	mov    %rsp,%rbp401008:	48 83 ec 10          	sub    $0x10,%rsp40100c:	c7 45 fc 00 00 00 00 	movl   $0x0,-0x4(%rbp)401013:	e8 07 00 00 00       	callq  40101f <func1>401018:	b8 00 00 00 00       	mov    $0x0,%eax40101d:	c9                   	leaveq 40101e:	c3                   	retq   000000000040101f <func1>:40101f:	f3 0f 1e fa          	endbr64 401023:	55                   	push   %rbp401024:	48 89 e5             	mov    %rsp,%rbp401027:	c7 45 fc 00 00 00 00 	movl   $0x0,-0x4(%rbp)40102e:	83 45 fc 01          	addl   $0x1,-0x4(%rbp)401032:	90                   	nop401033:	5d                   	pop    %rbp401034:	c3                   	retq   

例子1.o.text段的大小是1F,2.o中的.text段的大小是16。并且我们将程序的入口函数定位了main函数。所以a.out.text段的起始位置也就是main函数的位置。那func1函数的位置就是main + 1F了。查看a.out的汇编代码,发现callq 40101f ,这就是调用了func1函数。这样可执行文件就可以正常运行了。

三、静态链接过程注意点

3.1 强符号和弱符号不一致

在链接器的世界中,符号可以被分为两种类型:强符号(Strong Symbol) 弱符号(Weak Symbol)。这些术语通常用于描述符号的可见性和优先级。
强符号(Strong Symbol):强符号是具有全局可见性和固定地址的符号。当多个目标文件或库文件中存在相同名称的强符号时,链接器会选择其中的一个作为最终的定义。通常情况下,全局变量函数都是强符号。强符号的定义具有最高的优先级,将覆盖所有弱符号和普通符号。
弱符号(Weak Symbol):弱符号是具有全局可见性但没有固定地址的符号。当多个目标文件或库文件中存在相同名称的弱符号时,链接器会选择其中的一个作为最终的定义。弱符号的定义具有较低的优先级,当没有找到强符号时,链接器才会考虑使用弱符号。通常情况下,全局变量的声明函数的声明会被视为弱符号,因为它们没有固定的地址。
在程序中强弱符号定义不一致,主要分三种
两个及以上强符号类型不一致:多个强符号定义,会在链接时报重定义,因为链接器无法判断该符号的类型。
类型不一致的一个强符号和多个弱符号:在程序分配内存时,会按强符号的类型分配内存,同时报告警:size of symbole 符号 change from 。在连接的时候,要是弱符号的类型大于强符号,将报alignment 1 of symbol 符号 in 目标文件 is smaller than 8 in 目标文件
两个及以上弱符号类型不一致:这个时候,编译器不会给出要符号内存,只能到链接过程中看有没有强符号,在分配内存。这种情况下不会报告警和错误,但运行时会有未定义符号或者直接段错误。
综上,我们应该可以清楚了,为什么目标文件的bss段在磁盘中的大小是0。因为编译器无法判断其他编译单元中是否有比本单元该符号所占的内存更大的符号,所以给不出内存空间。

3.2 静态库链接

将静态库(Static Library)嵌入到可执行文件(Executable File)中的过程。静态库是一种预编译的代码库,包含函数、变量和其他代码对象,但并非直接可执行。在静态库链接过程中,链接器会将静态库中的所有代码和数据复制到可执行文件中,使其成为可执行文件的一部分。
优点
可执行文件独立性: 静态链接的可执行文件无需依赖外部库,即使在没有库的情况下也能运行。
提高安全性: 静态链接的可执行文件包含所有代码,因此更不容易受到外部库漏洞的影响。
减小可执行文件大小: 在某些情况下,静态链接可使可执行文件更小,因为无需包含额外的库文件。

缺点:
增加可执行文件大小: 在大多数情况下,静态链接会使可执行文件更大,因为包含了所有静态库代码。
浪费资源: 如果多个可执行文件使用相同的静态库,则每个可执行文件都包含该库的副本,这会导致资源浪费。
更新困难: 当静态库更新时,需要重新编译所有依赖它的可执行文件。

本篇大致讲述了静态链接的情况,下一篇文章将会对动态链接的情况进行阐述。

相关文章:

Linux内存管理--系列文章肆

一、引子 上篇文章介绍了目标文件&#xff0c;也就是讲到编译过程中的汇编这个阶段。本篇要讲目标文件怎么变成一个可执行文件的&#xff0c;介绍编译过程中的链接。 链接主要分为两种&#xff0c;静态链接和动态链接。它们本质上的区别&#xff0c;是在程序的编译和运行过程中…...

kali下载zsteg和stegpy

1.kali下载zsteg 从 GitHub 上克隆zsteg到kali git clone https://github.com/zed-0xff/zsteg 切换目录 cd zsteg 用于安装名为 zsteg 的 Ruby Gem 包 gem install zsteg 2.kali下载stegpy 下载网站内的stegpy-master压缩包GitCode - 开发者的代码家园 并拉到kali中 切换到s…...

前端面试题日常练-day34 【面试题】

题目 希望这些选择题能够帮助您进行前端面试的准备&#xff0c;答案在文末。 1. jQuery中&#xff0c;以下哪个选项用于筛选出第一个匹配的元素&#xff1f; a) first() b) get(0) c) eq(0) d) find(":first") 2. 在jQuery中&#xff0c;以下哪个选项用于在元素上…...

网站笔记:huggingface model memory calculator

Model Memory Utility - a Hugging Face Space by hf-accelerate 这个工具可以计算在 Hugging Face Hub上托管的大型模型训练和执行推理时所需的vRAM内存量。模型所需的最低推荐vRAM内存量表示为“最大层”的大小&#xff0c;模型的训练大约是其大小的4倍&#xff08;针对Adam…...

SpringBoot2.0.x旧版集成Swagger UI报错Unable to infer base url...解决办法

一、问题描述 1.1项目背景 SpringBoot2.0.9的旧版项目维护开发&#xff0c;集成Swagger-ui2.9.2无法访问的问题。不用想啊&#xff0c;这种老项目是各种过滤器拦截器的配置&#xff0c;访问不到&#xff0c;肯定是它们在作妖。懂得都懂啊&#xff0c;这里交给大家一个排错的办…...

软件项目详细设计说明书实际项目参考(word原件下载及全套软件资料包)

系统详细设计说明书案例&#xff08;直接套用&#xff09; 1.系统总体设计 2.性能设计 3.系统功能模块详细设计 4.数据库设计 5.接口设计 6.系统出错处理设计 7.系统处理规定 软件开发全文档下载&#xff08;下面链接或者本文末个人名片直接获取)&#xff1a;软件开发全套资料-…...

电脑文件qt5core.dll如何修复?如何快速的解决qt5core.dll丢失问题

软件应用程序依赖于各种复杂的文件系统以保证其顺畅运行。这些文件中&#xff0c;动态链接库&#xff08;Dynamic Link Library&#xff0c;简称DLL&#xff09;是Windows操作系统中实现多种功能的关键组件之一。然而&#xff0c;DLL文件出现问题是Windows用户可能面临的常见挑…...

USART串口通信(stm32)

一、串口通信 通信的目的&#xff1a;将一个设备的数据传送到另一个设备&#xff0c;扩展硬件系统 通信协议&#xff1a;制定通信的规则&#xff0c;通信双方按照协议规则进行数据收发 STM32F103C8T6 USART资源&#xff1a; USART1、 USART2、 USART3 自带波特率发生器&…...

快速分析变量间关系(Boruta+SHAP+RCS)的 APP(streamlit)

快速分析变量间关系&#xff08;BorutaSHAPRCS&#xff09;的 APP&#xff08;streamlit&#xff09; 以下情况下&#xff0c;你需要这个快速分析的APP: 正式分析之前的预分析&#xff0c;有助于确定分析的方向和重点变量&#xff1b;收集变量过程中&#xff0c;监测收集的变量…...

解决docker中container运行闪退终止的问题

在运行bindmount-test时&#xff0c;点击完运行按钮后闪退结束运行。 第一步查看log日志&#xff1a; 2024-05-18 23:46:18 Error: Cannot find module /app/nodemon 2024-05-18 23:46:18 at Function.Module._resolveFilename (internal/modules/cjs/loader.js:668:15) …...

Redis 性能管理

一、Redis 性能管理 #查看Redis内存使用 172.168.1.11:6379> info memory 1. 内存碎片率 操作系统分配的内存值 used_memory_rss 除以 Redis 使用的内存总量值 used_memory 计算得出。内存值 used_memory_rss 表示该进程所占物理内存的大小&#xff0c;即为操作系统分配给…...

节水“云”科普丨北京昌平VR节水云展馆精彩上线

2024年5月15日上午&#xff0c;由北京昌平区水务局主办的“推进城市节水&#xff0c;建设美丽昌平——2024年全国城市节约用水宣传周暨‘坚持节水优先 树立节水标杆’昌平节水在行动主题实践活动”隆重举办&#xff0c;活动期间&#xff0c;昌平区水务局应用VR虚拟现实技术创新…...

linux的系统调用open, read函数(文件编程)使用demo

1.引言 为了学习linux系统下的app开发&#xff0c;记载了学习文件编程的笔记 2.open函数 功能 打开一个文件 头文件 #include<sys/stat.h> #include<fcntl.h> 函数形式 int open(const char* pathname, int flags, mode_t mode); 返回值 如果调用成功&#xff0c…...

C语言基础——循环(2)+关机程序

欢迎点赞支持 个人主页&#xff1a;励志不掉头发的内向程序员&#xff1b; 专栏主页&#xff1a;C语言基础&#xff1b; 文章目录 目录 前言 一、for循环的补充 二、循环的嵌套 1、嵌套的介绍 1.1 练习&#xff1a; 题目解析&#xff1a; 优化&#xff1a; 三、goto语句 1、go…...

cnVcXsrv 21.1.13.1—VcXsrv 21.1.13中文版本简单说明~~

对于VcXsrv的使用目的和用途相信大家都很了解。前不久VcXsrv做了更新&#xff0c;并且将项目托管到github上了。链接如下&#xff1a; VcXsrv: Windows X-server based on the xorg git sourceshttps://github.com/marchaesen/vcxsrv也可以简单查看如下链接&#xff1a; VcXs…...

心链2---前端开发(整合路由,搜索页面,用户信息页开发)

心链——伙伴匹配系统 接口调试 说书人&#x1f4d6;&#xff1a;上回书说到用了两种方法查询标签1.SQL查询&#xff0c;2.内存查询&#xff1b;两种查询效率是部分上下&#xff0c;打的是难解难分&#xff0c;是时大地皴裂&#xff0c;天色聚变&#xff0c;老祖斟酌再三最后决…...

wordpress主题模板兔Modown 9.1开心版附送erphpdown v17.1插件

Modown 9.1开心版是一款模板兔开发的wordpress主题可&#xff0c;持续更新多年&#xff0c;优秀的资源下载类主题该模板基于Erphpdown&#xff0c;可以销售软件、视频教程、文章等等&#xff0c;通过主题和插件结合可以实现付费下载、付费阅读等功能&#xff0c;配合模板兔的一…...

openai api的初次尝试

不懂已经不去百度了&#xff0c;现在直接问chatgpt就解决绝大多数问题了。 OpenAI API目前还没有官方支持的npm库&#xff0c;但是您可以使用现有的第三方npm库进行OpenAI API的访问和使用。这里提供一个npm库 openai-node 的安装和使用方法&#xff1a; 在命令行或终端中使用…...

Distributed Transactions Mit 6.824

Topic1&#xff1a;distributed transactions concurrency control atomic commit 传统计划&#xff1a;事务 程序员标记代码序列的开始/结束作为事务。 事务示例 x 和 y 是银行余额——数据库表中的记录。x 和 y 位于不同的服务器上&#xff08;可能在不同的银行&#x…...

Redis可视化工具:Another Redis Desktop Manager下载安装使用

1.Github下载 github下载地址&#xff1a; Releases qishibo/AnotherRedisDesktopManager GitHub 2. 安装 直接双击exe文件进行安装 3. 连接Redis服务 先启动Redis服务&#xff0c;具体启动过程可参考&#xff1a; Windows安装并启动Redis服务端&#xff08;zip包&#xff09…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理

引言 Bitmap&#xff08;位图&#xff09;是Android应用内存占用的“头号杀手”。一张1080P&#xff08;1920x1080&#xff09;的图片以ARGB_8888格式加载时&#xff0c;内存占用高达8MB&#xff08;192010804字节&#xff09;。据统计&#xff0c;超过60%的应用OOM崩溃与Bitm…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...