嵌入式IDE(2):KEIL中SCF分散加载链接文件详解和实例分析
在上一篇文章IAR中ICF链接文件详解和实例分析中,我通过I.MX RT1170的SDK中的内存映射关系,分析了IAR中的ICF链接文件的语法。对于MCU编程所使用的IDE来说,IAR和Keil用得比较多,所以这一篇文章就来分析一下Keil的分散文件.scf
(scatter file
)。
文章目录
- 1 内存映射
- 2 SCF语法分析
- 2.1 工程的SCF文件
- 2.2 define
- 2.3 加载区域和执行区域
1 内存映射
和上一篇文章一样,同样使用I.MX RT1170的SDK中的链接文件进行分析,通过实际的分散文件来学习里面的语法。和上一节也是同一个例程,除了芯片自带的RAM外,还有NOR Flash和SDRAM。首先来看一下整个工程的内存映射表格:
类型 | 名称 | 起始地址 | 大小 |
---|---|---|---|
Flash | NOR Flash | 0x30000000 | 0x1000000 |
RAM | SDRAM | 0x80000000 | 0x3000000 |
RAM | NCACHE_REGION | 0x83000000 | 0x1000000 |
RAM | SRAM_DTC_cm7 | 0x20000000 | 0x40000 |
RAM | SRAM_ITC_cm7 | 0x0 | 0x40000 |
RAM | SRAM_OC1 | 0x20240000 | 0x80000 |
RAM | SRAM_OC2 | 0x202c0000 | 0x80000 |
RAM | SRAM_OC_ECC1 | 0x20340000 | 0x10000 |
RAM | SRAM_OC_ECC2 | 0x20350000 | 0x10000 |
对于我们的工程来说,有以下几个内存:
- 两个256KB的紧耦合内存
DTCM
和ITCM
- 两个带ECC的片内RAM:
OC1
和OC2
。 - 在映射的起始地址为
0x30000000
的FlexSPI1接口上接了一个16MB的NOR Flash - 在映射的起始地址为
0x80000000
的FlexSPI2接口上接了一个64MB的SDRAM。其中,前48MB用于可缓存的区域,后16MB(NCACHE_REGION
)用于不可缓存区域,通常直接与硬件进行交互的buffer需要设置为不可缓存。
2 SCF语法分析
2.1 工程的SCF文件
针对上面的内存映射,官方的SDK中提供的SCF
文件如下:
#if (defined(__ram_vector_table__))#define __ram_vector_table_size__ 0x00000400
#else#define __ram_vector_table_size__ 0x00000000
#endif#define m_flash_config_start 0x30000400
#define m_flash_config_size 0x00000C00#define m_ivt_start 0x30001000
#define m_ivt_size 0x00000020#define m_boot_data_start 0x30001020
#define m_boot_data_size 0x00000010#define m_dcd_data_start 0x30001030
#define m_dcd_data_size 0x000006E8#define m_xmcd_data_start 0x30001040
#define m_xmcd_data_size 0x00000204#define m_interrupts_start 0x30002000
#define m_interrupts_size 0x00000400#define m_text_start 0x30002400
#if (defined(__use_flash64MB__))
#define m_text_size 0x03FFDC00
#else
#define m_text_size 0x00FFDC00
#endif#define m_qacode_start 0x00000000
#define m_qacode_size 0x00040000#define m_interrupts_ram_start 0x80000000
#define m_interrupts_ram_size __ram_vector_table_size__#define m_data_start (m_interrupts_ram_start + m_interrupts_ram_size)
#define m_data_size (0x03000000 - m_interrupts_ram_size)#define m_data2_start 0x20000000
#define m_data2_size 0x00040000#define m_data3_start 0x202C0000
#define m_data3_size 0x00080000#define m_ncache_start 0x83000000
#define m_ncache_size 0x01000000/* Sizes */
#if (defined(__stack_size__))#define Stack_Size __stack_size__
#else#define Stack_Size 0x0400
#endif#if (defined(__heap_size__))#define Heap_Size __heap_size__
#else#define Heap_Size 0x0400
#endif#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)
LR_m_text m_flash_config_start m_text_start+m_text_size-m_flash_config_start { ; load region size_regionRW_m_config_text m_flash_config_start FIXED m_flash_config_size { ; load address = execution address* (.boot_hdr.conf, +FIRST)}RW_m_ivt_text m_ivt_start FIXED m_ivt_size { ; load address = execution address* (.boot_hdr.ivt, +FIRST)}RW_m_boot_data_text m_boot_data_start FIXED m_boot_data_size { ; load address = execution address* (.boot_hdr.boot_data, +FIRST)}#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)RW_m_dcd_data_text m_dcd_data_start FIXED m_dcd_data_size { ; load address = execution address* (.boot_hdr.dcd_data, +FIRST)}
#elif defined(XIP_BOOT_HEADER_XMCD_ENABLE) && (XIP_BOOT_HEADER_XMCD_ENABLE == 1)RW_m_xmcd_data_text m_xmcd_data_start FIXED m_xmcd_data_size { ; load address = execution address* (.boot_hdr.xmcd_data, +FIRST)}
#endif
#else
LR_m_text m_interrupts_start m_text_start+m_text_size-m_interrupts_start { ; load region size_region
#endifVECTOR_ROM m_interrupts_start FIXED m_interrupts_size { ; load address = execution address* (.isr_vector,+FIRST)}ER_m_text m_text_start FIXED m_text_size { ; load address = execution address* (InRoot$$Sections).ANY (+RO)}
#if (defined(__ram_vector_table__))VECTOR_RAM m_interrupts_ram_start EMPTY m_interrupts_ram_size {}
#elseVECTOR_RAM m_interrupts_start EMPTY 0 {}
#endifRW_m_data2 m_data2_start m_data2_size {* (RamFunction)* (DataQuickAccess)}
#if (defined(__heap_noncacheable__))RW_m_data m_data_start m_data_size-Stack_Size { ; RW data
#elseRW_m_data m_data_start m_data_size-Stack_Size-Heap_Size { ; RW data
#endif.ANY (+RW +ZI)*(*m_usb_dma_init_data)*(*m_usb_dma_noninit_data)}
#if (!defined(__heap_noncacheable__))ARM_LIB_HEAP +0 EMPTY Heap_Size { ; Heap region growing up}
#endifARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack region growing down}RW_m_ram_text m_qacode_start m_qacode_size { ;* (CodeQuickAccess)}
#if (defined(__heap_noncacheable__))RW_m_ncache m_ncache_start m_ncache_size - Heap_Size { ; ncache data
#elseRW_m_ncache m_ncache_start m_ncache_size { ; ncache data
#endif* (NonCacheable.init)* (*NonCacheable)}
#if (defined(__heap_noncacheable__))ARM_LIB_HEAP +0 EMPTY Heap_Size { ; Heap region growing up}RW_m_ncache_unused +0 EMPTY m_ncache_size-ImageLength(RW_m_ncache)-Heap_Size { ; Empty region added for MPU configuration
#elseRW_m_ncache_unused +0 EMPTY m_ncache_size-ImageLength(RW_m_ncache) { ; Empty region added for MPU configuration
#endif}
}
2.2 define
先来分析第一段分散文件,KEIL的分散文件的语法define
和#if defined
语句与C语言一致,所以下面这一段还是很好理解的:
#if (defined(__ram_vector_table__))#define __ram_vector_table_size__ 0x00000400
#else#define __ram_vector_table_size__ 0x00000000
#endif#define m_flash_config_start 0x30000400
#define m_flash_config_size 0x00000C00#define m_ivt_start 0x30001000
#define m_ivt_size 0x00000020#define m_boot_data_start 0x30001020
#define m_boot_data_size 0x00000010#define m_dcd_data_start 0x30001030
#define m_dcd_data_size 0x000006E8#define m_xmcd_data_start 0x30001040
#define m_xmcd_data_size 0x00000204#define m_interrupts_start 0x30002000
#define m_interrupts_size 0x00000400#define m_text_start 0x30002400
#if (defined(__use_flash64MB__))
#define m_text_size 0x03FFDC00
#else
#define m_text_size 0x00FFDC00
#endif#define m_qacode_start 0x00000000
#define m_qacode_size 0x00040000#define m_interrupts_ram_start 0x80000000
#define m_interrupts_ram_size __ram_vector_table_size__#define m_data_start (m_interrupts_ram_start + m_interrupts_ram_size)
#define m_data_size (0x03000000 - m_interrupts_ram_size)#define m_data2_start 0x20000000
#define m_data2_size 0x00040000#define m_data3_start 0x202C0000
#define m_data3_size 0x00080000#define m_ncache_start 0x83000000
#define m_ncache_size 0x01000000/* Sizes */
#if (defined(__stack_size__))#define Stack_Size __stack_size__
#else#define Stack_Size 0x0400
#endif#if (defined(__heap_size__))#define Heap_Size __heap_size__
#else#define Heap_Size 0x0400
#endif
先说明一下,I.MX系列单片机上电会进入L1 BootLoader,它用来引导程序如何启动,比如说是否加密、加密密钥、是XIP还是non-XIP(就要拷贝到RAM)、是否要初始化时钟。在NOR Flash启动的情况下,程序镜像的前0x2000字节就是用来给L1 BootLoader提供一些启动信息的,这里不必过分关注这些字段的意义,若想详细理解可以参考我的这篇文章I.MX RT1170启动详解:Boot配置、Bootable image头的组成。
(1)__ram_vector_table__
没有在别的地方定义,所以__ram_vector_table_size__
为0。这也很好理解,因为这里有NOR Flash,向量表就不放到RAM中了,而是放在NOR Flash的最前面。
(2)m_flash_config_start
和m_flash_config_size
:用来给L1 BootLoader提供NOR Flash的配置信息,因为上电后L1 BootLoader用最慢的最保险的配置来初始化NOR Flash,如果用户希望自行配置一些参数,比如时钟变快一些,就可以在这个字段填充配置信息,起始地址为0x30000400
(NOR Flash的基地址为0x30000000
),长度为0xC00
(3)m_ivt_start
和m_ivt_size
:IVT(Image Vector Table
)字段,用来保存程序入口地址等参数
(4)m_boot_data_start
和m_boot_data_size
:用来保存镜像的绝对起始地址和大小
(5)m_dcd_data_start
和m_dcd_data_size
:DCD
字段,一般用来初始化SDRAM,特别是希望程序在SDRAM运行的时候需要配置此字段
(6)m_xmcd_data_start
和m_xmcd_data_size
:可以看到这里的起始地址和大小与上面的DCD
字段重合了,实际上二者的功能类似,只不过DCD
的配置是一个个寄存器配置的指令,比较复杂,而XMCD简化了这些配置操作,这两个字段是二选一的。
(7)m_interrupts_start
和m_interrupts_size
:前面说了,L1 BootLoader的头信息的大小为0x2000
,所以从0x2000
开始就是程序的开始,最前面放置向量表,长度为0x400
。
(8)m_text_start
和m_text_size
:代码段紧接着向量表后面,起始地址为0x30002400
,这里__use_flash64MB__
为假,我们假设用的是16MB(0x1000000
)的NOR Flash,剩下的大小就是0x1000000-0x2400=0x00FFDC00
。
(9)m_qacode_start
和m_qacode_size
:即前面内存映射中芯片内部的SRAM_ITC_cm7
(10)m_interrupts_ram_start
和m_interrupts_ram_size
:如果向量表没有放在NOR Flash,就放在SDRAM的起始,这里由于放在NOR Flash,这两个字段没有用到
(11)m_data_start
和m_data_size
:data数据段,这里将data段放在了SDRAM。这里SDRAM的大小为64M,这个字段占了前48M。
(12)m_data2_start
、m_data2_size
、m_data3_start
和m_data3_size
:同样是data数据段,分别为SRAM_ITC_cm7
和SRAM_OC2
,即片内的RAM都可以作为data段放置变量
SRAM_OC1
没有用到,我们可以自行声明。因为L1 BootLoader运行时用到了这块SRAM,所以使用时需要考虑使用这块SRAM的时间。
(13)m_ncache_start
和m_ncache_size
:即SDRAM最后的16M用来做non-cacheable区域,比如GUI绘制的Buffer、摄像头的Buffer和DMA的数据,这种直接与硬件交互的内存,需要定义在不可缓存的区域。这与MPU配置有关,可以参考我的MPU系列的文章MPU内存保护单元详解及例子和L1 Cache之I-Cache和D-cache详解。
(14)Stack_Size
和Heap_Size
:分别为栈和堆的大小,由于程序中使用了FreeRTOS,所以只要保证这里的栈和堆的大小能够成功初始化FreeRTOS即可,初始化FreeRTOS过程应该没有内存分配,所以Heap Size
可以设置为0。
2.3 加载区域和执行区域
接下来开始涉及到一些分散文件的语法,参考文档:<DUI0377G_02_mdk_armlink_user_guide.pdf>
(可以在KEIL安装目录下找到)。
相比IAR,KEIL的分散文件的语法简单地多,和Linux的ld文件差不多,分散文件就由一个或多个加载区域(Load Region
)构成,如下图所示:
加载区域的语法如下:
load_region_name (base_address | ("+" offset)) [attribute_list] [max_size]
"{"
execution_region_description+
"}"
load_region_name
(名称): 用于由链接器识别不同加载区域的独特标签,每个加载区域必须具有唯一的名称base_address
(基地址):加载区域内的代码和数据在内存中放置的起始内存地址attribute_list
(属性): 定义加载区域的特性和行为,包括只读、读写、仅执行或其他内存保护属性max_size
(最大大小): 可选,用于限制加载区域的大小,防止内存溢出execution_region_description
(执行区域): 加载区域可以包含一个或多个执行区域。执行区域表示连续的代码和数据块,作为一个单独的单元加载到内存中
如果要把所有语法都总结到文章中就太耗时了,所以还是继续分析分散文件,出现了什么语法或关键字,我们再来去找它的意思。由于后面的分散文件中的宏定义太多而影响阅读,这里假设XIP_BOOT_HEADER_ENABLE=1
、XIP_BOOT_HEADER_DCD_ENABLE=1
、XIP_BOOT_HEADER_XMCD_ENABLE=0
和__heap_noncacheable__
(表示将堆放置在non-cacheable区域,保证堆内存不会收到缓存的影响)。
剩下的分散文件实际上就是定义了一个加载区域LR_m_text
,它的起始地址为m_flash_config_start
(0x30000400
),最大的大小为m_text_start+m_text_size-m_flash_config_start
(16M-0x400=0xFFFC00
),即从0x30000400
处开始链接,大小为0xFFFC00
,这个大小仅限制加载区域的大小(下面属性为FIXED
的执行区域)。0~0x400
与NXP RT系列单片机的加密启动有关,这些字段编译器无法进行填充,所以这里就没有考虑。
LR_m_text m_flash_config_start m_text_start+m_text_size-m_flash_config_start { ; load region size_region......
}
- 在分散文件中,
;
后面为注释
在加载区域LR_m_text
下有非常多个执行区域,下面来一个个分析一下:
1、RW_m_config_text
:起始地址0x30000400
,大小0xC00
RW_m_config_text m_flash_config_start FIXED m_flash_config_size { ; load address = execution address* (.boot_hdr.conf, +FIRST)
}
FIXED
:执行区域的属性,表示让执行区域的执行地址与加载地址尽量保持相等。这意味着,分配给这个执行区域的代码和数据在加载到内存时会尽量放置在指定的执行地址上。如果因为内存冲突或空间不足等原因无法满足,则链接器会报错。+FIRST
:表示把该section
放在该执行区域的最开始的地方
所以这里就是从0x30000400开始处开始放置boot_hdr.conf
段,因为放置的位置必须固定才能被L1 BootLoader正确识别,所以执行区域需要用FIXED
属性。
2、RW_m_ivt_text
:起始地址0x30001000
,大小0x00000020
RW_m_ivt_text m_ivt_start FIXED m_ivt_size { ; load address = execution address* (.boot_hdr.ivt, +FIRST)
}
同上,放置L1 BootLoader的引导头。
3、RW_m_boot_data_text
:起始地址0x30001020
,大小0x00000010
RW_m_boot_data_text m_boot_data_start FIXED m_boot_data_size { ; load address = execution address* (.boot_hdr.boot_data, +FIRST)
}
同上,放置L1 BootLoader的引导头。
4、RW_m_dcd_data_text
:起始地址0x30001030
,大小0x000006E8
RW_m_dcd_data_text m_dcd_data_start FIXED m_dcd_data_size { ; load address = execution address* (.boot_hdr.dcd_data, +FIRST)
}
同上,放置L1 BootLoader的引导头。
5、VECTOR_ROM
:起始地址0x30002000
,大小0x00000400
VECTOR_ROM m_interrupts_start FIXED m_interrupts_size { ; load address = execution address* (.isr_vector,+FIRST)
}
放置中断向量表。在启动文件startup_MIMXRT1176_cm7.S
文件中定义了该段:.section .isr_vector, "a"
,这里的a
表示将该段标记为可分配(allocatable
)的,意味着它在链接时可以被分配到内存中的某个位置。
6、ER_m_text
:起始地址0x30002400
,大小0x00FFDC00
ER_m_text m_text_start FIXED m_text_size { ; load address = execution address* (InRoot$$Sections).ANY (+RO)
}
InRoot$$Sections
是在分散文件中使用的特殊标记,用来将压缩数据段放置该执行区域中,以确保这些数据段在运行时能够被自动解压缩并提供给程序使用。该特性是ARM为了减少存储空间占用设计的,上电后ARM库会根据此段来进行解压。- 参考文章:Example of placing code in a root region
.ANY
:可以理解为*
,表示所有段,但.ANY
可以用在多个执行区域中,而*
一般只用在一个执行区域中,所以.ANY
会更灵活一些。具体参考手册7.4章节<Placement of unassigned sections with the .ANY module selector>
(+RO)
:只读数据段
这里表示将所有的只读数据段放置在这个执行区域。
7、VECTOR_RAM
:这里将中断向量表放置在NOR Flash了,这个执行区域没有用到
VECTOR_RAM m_interrupts_start EMPTY 0 {
}
EMPTY
表示保留一个空区域,但这里区域的大小设为0,所以这段执行区域没有任何作用
8、RW_m_data2
:起始地址0x20000000
,大小0x00040000
RW_m_data2 m_data2_start m_data2_size {* (RamFunction)* (DataQuickAccess)
}
这里定义了两个Section:RamFunction
和DataQuickAccess
,在程序中都可以用__attribute__((section("")))
来定义函数或变量到内部的SRAM_DTCM
中,可以加快函数的执行速度和数据的访问速度。
9、RW_m_data
:起始地址0x80000000
,大小0x03000000-0x400
RW_m_data m_data_start m_data_size-Stack_Size { ; RW data.ANY (+RW +ZI)*(*m_usb_dma_init_data)*(*m_usb_dma_noninit_data)
}
这个执行区域就是SDRAM的前48M,将所有的读写数据段和bss段放置在此,同时声明两个usb段,用于SDK中对于USB相关功能的实现。实际上USB段放在non-cacheable
区域肯定是可以运行的,但是同时也意味着没有用到缓存,速度就会降低很多。所以就可以将USB相关变量声明到cacheable
的区域,然后在代码中必要的地方手动缓存更新相关函数,如SCB_CleanInvalidateDCache
和SCB_CleanDCache
。
10、ARM_LIB_STACK
:起始地址0x83000000
,大小0x400
ARM_LIB_STACK m_data_start+m_data_size EMPTY -Stack_Size { ; Stack region growing down
}
ARM_LIB_STACK
:栈的执行区域的固定名称
这里的Stack_Size
的前面有一个-
,表示栈是向下生长的。
11、RW_m_ram_text
:起始地址0x00000000
,大小0x00040000
RW_m_ram_text m_qacode_start m_qacode_size { ;* (CodeQuickAccess)
}
与上面的7类似,声明一个CodeQuickAccess
段,用于将函数链接到内部的SRAM_ITCM
中,因为内部的SRAM的速度比NOR Flash或SDRAM的访问速度都快得多。
12、RW_m_ncache
:起始地址0x83000000
,大小0x01000000-0x400
RW_m_ncache m_ncache_start m_ncache_size - Heap_Size { ; ncache data* (NonCacheable.init)* (*NonCacheable)
}
定义non-cacheable
区域的两个段NonCacheable.init
和NonCacheable
,同时预留堆的空间,因为这里我们假设堆空间也为non-cacheable
。
13、ARM_LIB_HEAP
:大小0x400
ARM_LIB_HEAP +0 EMPTY Heap_Size { ; Heap region growing up
}
+0
:表示为上一个执行区域的结束地址,根据用户放置到RW_m_ncache
执行区域的变量的多少和大小来决定这个地址ARM_LIB_HEAP
:堆的执行区域的固定名称
定义堆空间的内存。
14、RW_m_ncache_unused
RW_m_ncache_unused +0 EMPTY m_ncache_size-ImageLength(RW_m_ncache)-Heap_Size { ; Empty region added for MPU configuration
}
同样放置在上一个执行区域的结束地址处,用来给MPU进行配置,大小m_ncache_size-ImageLength(RW_m_ncache)-Heap_Size
即除去变量和堆外的剩下的non-cacheable
区域。
ImageLength
可以取某个执行区域占的大小
相关文章:
嵌入式IDE(2):KEIL中SCF分散加载链接文件详解和实例分析
在上一篇文章IAR中ICF链接文件详解和实例分析中,我通过I.MX RT1170的SDK中的内存映射关系,分析了IAR中的ICF链接文件的语法。对于MCU编程所使用的IDE来说,IAR和Keil用得比较多,所以这一篇文章就来分析一下Keil的分散文件.scf(scat…...
Linux防火墙常用操作及端口开放
Linux防火墙常用操作及端口开放 1.查看防火墙状态 firewall-cmd --state 2.开启防火墙 systemctl start firewalld.service 3.开启指定端口 firewall-cmd --zonepublic --add-port3306/tcp --permanent firewall-cmd --zonepublic --add-port6379/tcp --permanent 显示success表…...
[JAVAee]Linux上的javax.mail报错
我们把在window写的项目部署到Linux上的Tomcat时,如果发现使用不了了,该如何找到错误呢?找到报错的地方在哪呢? 在Linux环境下来到Tomcat目录下的logs目录,输入: tail -f catalina.out -n 500 tail 就是把文件的末尾几行读取到终端上,并会持续刷新 -f 循环读取 catalina.ou…...
开学季|校园迎新哪家强?VR全景来导航
九月开学迎新季,各大高校的迎新活动开展的如火如荼,随着科技的不断进步,高校为了更好的开展迎新活动,让新生们尽快熟悉新的校园和生活,会利用VR全景技术带领着新生进行校园游览,给予新生们巨大便利的同时&a…...
el-checkbox-group限制勾选数量
<!--* Description: 视频监控 页面* Author: mhf* Date: 2023-08-15 13:26:33 --> <template><div class"videoSurveillance"><el-row :gutter"24"><el-col :span"4"><div class"videoSurveillance-left&…...
【JavaScript】WebAPI入门到实战
文章目录 一、WebAPI背景知识1. 什么是WebAPI?2. 什么是API? 二、DOM基本概念三、获取元素三、事件初识1. 点击事件2. 键盘事件 四、操作元素1. 获取/修改元素内容2. 获取/修改元素属性3. 获取/修改表单元素属性4. 获取/修改样式属性 五、操作节点1. 新增…...
奥康的高尔夫鞋,圈不住投资者的心
文 | 螳螂观察 作者 | 青月 鞋服行业终于熬过了“寒冬”,2023年行业景气度开始逐步回暖。 东方财富Choice数据显示,截至8月17日,已有28家鞋帽服装类上市公司发布了2023年中期业绩预告或快报,其中,9家预增࿰…...
vue2配置环境变量并且nginx运行成功
需求:我在vue项目配置了生产环境和开发环境,之后通过proxy代理的方式把地址转发到真实的服务器地址上用于请求接口,之后把项目打包后上传到nginx上,之后接口报错404,但是本地运行是可以访问的,找了很久终于…...
Java+Swing形成GUI图像界面
一、Swing 简介 Swing 主要用来开发 GUI 程序,GUI(Graphical User Interface)即图形用户界面。Java 中针对 GUI 设计提供了丰富的类库,这些类分别位于 java.awt 和 java.swing 中,简称 AWT 和 Swing ;其中,AWT(Abstract Window Toolkit)是抽象窗口工具包,是 Java 平…...
编辑距离 -- 动规
72. 编辑距离 给出动规的两种常见实现形式:自顶向下、自底向上,前者一般借助递归函数备忘录实现,后者通常基于dp数组实现。 class MinDistance:"""72. 编辑距离https://leetcode.cn/problems/edit-distance/""&quo…...
douyin【商品抢购js脚本】
文章目录 前言订阅须知知识点源码前言 脚本主要用来实现抢购douyin商城、直播间秒杀商品等一系列商品 订阅须知 订阅后,只提供js源代码,不提供教学,请根据源码自行抓包知识点 1、在查询串插入一个固定的键rstr 2、对查询串进行按键排序并取值,对空格和+进行转义为a …...
常见Web安全技术总结!474页Web安全从入门到精通(附PDF)
Web安全范围比较大,知识点比较杂,很多朋友都无从下手,这不可怕,可怕的是乱下手,其实往往基础才是决定你是否能走远的关键。 为了帮助大家入门网安,给大家推荐一份《新手Web安全入门到精通》,共…...
Prometheus 监控指南:如何可靠地记录数字时间序列数据
🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🐅🐾猫头虎建议程序员必备技术栈一览表📖: 🛠️ 全栈技术 Full Stack: 📚…...
rsync远程同步+inotify监控
目录 一、Rsync 简介 1、rsync是什么 2、备份的方式 3、rsync同步方式 4、常用rsync命令 5、配置源的两种表达方法 二、rsync实验 1、本地复制 编辑编辑 2、异地复制 2.1 rsync服务器配置 2.2 rsync客户端配置 2.2.1 普通同步 2.2.2 免密同步 2.2.3 --delet…...
【面试经典150 | 数组】移除元素
文章目录 写在前面Tag题目来源题目解读解题思路方法一:原地操作 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…… 专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等…...
玩转Mysql系列 - 第21篇:什么是索引?
这是Mysql系列第21篇。 本文开始连续3篇详解mysql索引: 第1篇来说说什么是索引? 第2篇详解Mysql中索引的原理 第3篇结合索引详解关键字explain 本文为索引第一篇:我们来了解一下什么是索引? 路人在搞计算机之前,…...
预处理指令
// The include directive instructs the preprocessor to paste the text of the given file into the current file. // 粘贴指定文件的内容 #include // 定义宏PI #define PI 3.1415926 // 取消定义PI #undef PI条件编译(Conditional Compilation) // 检查xxx是否已被定义为…...
强大的JTAG边界扫描(1):基本原理介绍
文章目录 1. 什么是边界扫描?2. JTAG硬件接口3. 边界扫描相关的软硬件4. 学习资料5. 总结 我是怎么了解到边界扫描的呢? 这就要从我淘到一块FPGA板卡的事情说起了。 前段时间我在某二手平台上淘了一块FPGA板子,它长这样: 板子的…...
【C++】源文件.cpp和头文件.h分离编程
优势介绍 将C代码分为头文件(.h)和源文件(.cpp)的做法有以下几个好处: 模块化和代码组织:将函数和类的声明(包括函数原型、类的成员和属性等)放在头文件中,将函数和类的…...
报错ssh: Could not resolve hostname
…按照网上好多教程试了一下: 新建密钥,添加到gitee,重新测试。修改host,加入gitee的ip地址到里面去。修改.gifconfig配置文件,配置成ssh的仓库链接。 这上面的方法都不行,后面发现一篇文章:SS…...
从零开始学网站建设:从需求分析到上线发布
从零开始学网站建设:从需求分析到上线发布 一、需求分析 在进行网站建设之前,首先需要与客户进行沟通,了解客户的需求和要求,并进行深入的分析和研究。根据不同的需求,需要确定网站的类型、功能、布局、风格等方面的…...
软件系统验收测试需要注意的地方
验收测试 一、软件验收测试含义: 软件验收测试是指测试人员检验软件是否符合软件规格说明书和用户需求的测试活动。 验收测试是软件测试的最后一个环节,也是最为关键的一个要素。 它关系到软件开发公司的产品质量,也关系到需求方的产品能…...
解决three.js中加载纹理贴图时,初次渲染不显示的问题
效果: 解决方法:主要是将一些构建网格对象的操作放在了textureLoader.load()方法中,加载图片也用了require init() {// 1, 创建场景对象this.scene new this.$three.Scene();// 2, 创建立方缓冲几何体this.geometry new this.$three.BoxGe…...
Git学习记录
Contest 一、工作区域二、操作命令2.1 创建仓库2.2 查看仓库状态2.3 从工作区向暂存区添加文件2.3.1 只添加一个文件2.3.2 添加全部文件 2.4 从暂存区向仓库区添加文件2.5 查询日志2.5.1 从当前版本开始查询2.5.2 查看所有日志 2.6 回滚2.6.1 从仓库回滚到工作区2.6.2 取消工作…...
建筑模板木模好还是钢模好
在建筑施工中,模板是一项关键的工程,对于建筑结构的质量和施工效率起着重要作用。在选择模板材料时,木模和钢模都是常见的选择。本文将比较木模和钢模的优缺点,以帮助您做出明智的选择。 正文:一、木模:传统…...
写代码中碰到的错误
bind绑定类内成员导致 "no matching function for call to ..." 当bind绑定类内成员时,需要指明绑定的成员所在类的位置。 上面未指明Remove函数在哪个类中从而导致错误。 此外 bind 的函数指针类型是const类型的,都需要添加 const 修饰。 S…...
java文件传输简单方法
java文件传输简单方法 假设现在已经打包了一个文件(1233444333),要将这个文件传输给另一方: import java.io.*; public class F_PasswordUnPassword { public static void main (String[] args)throws Exception { ByteArrayOutp…...
Vue3后台管理系统Element-plus_侧边栏制作_无限递归
在home.view中添加代码 <template><div><div class"common-layout"><el-container><el-header class"common-header flex-float"><div class"flex"><img class"logo" src"../assets/logo…...
PCIe基础概念
《PCI_Exepress体系结构导读》《WDC databook》读书笔记 RCB read completion boundary MPS max payload size MRRS max read request size 4K对齐 Specifies the address page boundary size supported by the AXI bridge. No packet can have an address that crosses…...
GE IS220PVIBH1A 336A4940CSP16 数字输入模块
GE IS220PVIBH1A(336A4940CSP16)是一种数字输入模块,通常用于工业控制和自动化系统中,以将数字信号输入到PLC(可编程逻辑控制器)或其他控制系统中。以下是一些可能的产品特点和功能,但请注意&am…...
wordpress论坛vip破解/广告外链平台
正负样本不均衡是检测任务中常见的问题,在目标检测中,大量样本都是不包含目标的负样本,只有少量是包含目标的正样本,而Focal Loss就是为了解决这个问题而提出的。 Focal Loss的目的 focal loss的主要目的是降低易分类样本的权重…...
有哪些好的建站平台/做了5天游戏推广被抓了
电动机应用广泛,下面为您揭晓目前电动机重要的七大应用领域: 1、电气伺服传动领域 在要求速度控制和位置控制(伺服)的场合,特种电机的应用越来越广泛。开关磁阻电动机、永磁无刷直流电动机、步进电动机、永磁交流伺服电动机、永磁直流电动机…...
南山优化网站建设案例/推广软件排行榜前十名
本地广播和全局广播(按照传播范围) 本地广播(app内部传播)数据,其它app收不到,保证了数据的安全性 全局广播,可以在整个手机所有App之间传播通信,会有安全性问题。普通广播默认就是全局广播。 例如监听开机充电打电话发短信修改时间这些 1.本地广播只能通过动态注册 2.本地广播…...
男给女做性按摩网站/推推蛙品牌策划
今天和大家分享中继器版商品分类卡片的原型模板,该原型模板由中继器制作,使用时只需要填写好中继器表格,即可自动生成交互效果 【原型预览及下载地址】 https://axhub.im/ax9/b8494994420eef04/#g1 【原型效果】 【Axure高保真原型】商品分…...
北京好一点的微网站开发公司/手机上可以创建网站吗
作用:持有对象 由于程序运行时才会根据某些条件去创建对象。数组也可以持有对象,但是由于长度固定受限严重,所以Java提供了一套完整的容器类来解决这个问题。最基本类型List、Set、Map、Queue。简单容器分布图(详见thinking in Ja…...
网络平台贷款逾期不还的后果/优化seo教程
OpenGL实现视频的剪裁、旋转、水印、滤镜?? 将 ffmpeg 库移植到 Android 平台? 在播放网络上的视频流时,Android原生的MediaPlayer支持两种协议,HTTP和RTSP,这两种协议最大的不同是,RTSP协议支…...