【单片机开发】MCU三种启动方式(Boot选择)[主Flash/系统存储器(BootLoader)/嵌入式SRAM]
目录
参考资料:
利用 Boot 选择不同的启动方式:
单片机的存储结构(主 FLASH/系统存储器/嵌入式 SRAM):
1. Cortex-M 内核芯片——启动原理:
1.1. 启动流程:
1.2. 根据单片机的存储器映射和架构图:启动空间必须在代码区域(0x0000 0000 ~ 0x1FFF FFFF)
1.3. 地址映射原理: 存储器别名(memory alias)“技术
1.3.1. 举例
1.3.2. 引出一个问题:为什么可以从其他地址读 0x0000 0000 的中断向量表
1.3.3. 那么新的问题来:(怎么规定/配置内存重映射)
1.3.4. 问题:既然设置到0x0800 0000这么麻烦,为什么不直接使用0x0000 0000?
2. 根据不同的启动方式:会将配置的启动地址(主 FLASH/系统存储器/嵌入式 SRAM)映射到 0x0000 0000(系统中断向量表) 上
2.1. 从系统存储器(System Memory)启动:
2.2. 从主 Flash(Main Flash Memory)启动:这个是平时使用最多的方式,将程序下载到STM32内部Flash,然后从Flash启动。
【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
2.3. 从嵌入式 SRAM 启动(内部 SRAM):【比较好奇】
2.3.1. 为什么可以从 SRAM 启动:
至于为什么STM32还能从SRAM启动,ST官方资料https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf中的3.4节 给出的说明是:
请注意:从SRAM启动与在SRAM中运行代码是两个不同的概念。
2.3.2. 为什么需要从SRAM启动【应用】
2.3.3. 从 SRAM 启动:
实现原理:
实现步骤:MCU的三种启动方式 - EdgeAI Lab
2.3.4. 【补充】在 SRAM 中运行代码:
实现步骤:在SRAM中运行代码 - EdgeAI Lab
参考资料:
MCU的三种启动方式 - EdgeAI Lab
立芯嵌入式的视频
在SRAM中运行代码 - EdgeAI Lab
【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
还有一些在标题附近
利用 Boot 选择不同的启动方式:


单片机的存储结构(主 FLASH/系统存储器/嵌入式 SRAM):

如上图所示,STM32内部:
- 一共有两块物理存储设备
-
- 内部 Flash
- 内部 SRAM
- 三块存储区域
-
- Main Flash Memory ——正常单片机启动方式(0x0800 0000~0x0807 FFFF)
- System Memory ——一般存有 BootLoader 程序(0x1FFF 0000~0x1FFF 7A0F)
一般系统存储器又叫 BootROM
-
- SRAM ——比较特殊,在不想影响 FLASH 程序下调试可用(0x2000 0000)
一般调试用,因为断电后数据会消失
-
- 这三块存储区域也就是STM32的三个启动空间。
1. Cortex-M 内核芯片——启动原理:
1.1. 启动流程:
【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
- M3,M4内核芯片上电复位后,要固定从0x0000 0000地址读取中断向量表
- 获取复位中断服务程序的入口地址后,进入复位中断服务程序
- 其中0x0000 0000是栈顶地址,0x0000 0004存的是复位中断服务程序地址


1.2. 根据单片机的存储器映射和架构图:启动空间必须在代码区域(0x0000 0000 ~ 0x1FFF FFFF)
存储器指可以存储数据的设备(FLASH/SRAM/ROM),本身没有地址信息,对存储器分配地址的过程称为存储器映射

- 单片机默认启动方式:
-
- Cortex®-M3 CPU上电后(开始找中断向量表)
-
-
- 默认从0x0000 0000地址处取得栈顶地址(MSP)
- 通过ICode bus从0x0000 0004地址处取得PC的值(复位向量)
- 然后开始执行代码(进入复位中断服务程序)
-
- 因为ICode bus只能访问代码区域(0x0000 0000 ~ 0x1FFF FFFF),所以启动空间必须在代码区域
【ICode 总线】
1.3. 地址映射原理: 存储器别名(memory alias)“技术
1.3.1. 举例
- STM32内部Flash就位于代码区域(采用从主 FLASH 启动方式),并且通过“ 存储器别名(memory alias)“技术
代码区域——(0x0000 0000 ~ 0x1FFF FFFF)
主 FLASH——(0x0800 0000~0x0807 FFFF)
-
- 可以将STM32的Main Flash Memory的地址空间0x0800 0000 ~ 0x0801 FFFF映射到0x0000 0000 ~ 0x0001 FFFF,对于System memory也是同样的道理。所以STM32可以从Main Flash Memory和System memory启动。
1.3.2. 引出一个问题:为什么可以从其他地址读 0x0000 0000 的中断向量表
- 既然ARM规定了M3,M4内核要从地址0x0000 0000读取中断向量表,而STM32设置Flash地址到0x0800 0000怎么办?

- 解决方法:
-
- STM32支持了个内存重映射功能,将地址0x0800 0000开始的内容重映射到首地址0x0000 0000中,这样就解决了从0x0000 0000读取中断向量表的问题。
1.3.3. 那么新的问题来:(怎么规定/配置内存重映射)
- 你怎么保证0x08000 0000首地址存的就是中断向量表,我们不可以随意设置吗?
- 解决方法:
-
- 保证中断向量表存到0x0800 0000,这个涉及到分散加载的一个小知识
- 以MDK为例:
-
-
- 如果大家看xxx.S启动文件,里面通过AREA定义了一个名叫RESET的段,这段存的就是中断向量表。
-
; Vector Table Mapped to Address 0 at ResetAREA RESET, DATA, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size
-
-
- 这个名字很重要,MDK对应的xxx.sct分散加载里面通过下面这句将这个RESET段放在了0x0800 0000优先存储。
-
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08000000 0x00200000 { ; load region size_regionER_IROM1 0x08000000 0x00200000 { ; load address = execution address*.o (RESET, +First)*(InRoot$Sections).ANY (+RO).ANY (+XO)}RW_IRAM2 0x24000000 0x00080000 { ; RW data.ANY (+RW +ZI)}
}
-
-
- 这样我们就解决了0x0800 0000首地址存储中断向量表,一旦程序开始运行后,我们就可以随意设置中断向量表的位置了。
- 比如想将中断向量表存到内部SRAM,我们就可以操作寄存器SCB->VTOR 重新安排,然后将0x0800 0000的内容复制到设置的地址内即可。【上电启动后,改为从内部 SRAM 启动】
-
1.3.4. 问题:既然设置到0x0800 0000这么麻烦,为什么不直接使用0x0000 0000?
- 因为我们需要从不同的地址启动,以达到不同的启动程序(BootLoader 程序/正常 APP 应用程序)
- M3、M4 内核:

- M7 内核

2. 根据不同的启动方式:会将配置的启动地址(主 FLASH/系统存储器/嵌入式 SRAM)映射到 0x0000 0000(系统中断向量表) 上
2.1. 从系统存储器(System Memory)启动:

System Memory中是ST预置的bootloader程序,用于通过串口下载用户程序到Flash。
一般系统存储器启动的话会存放 BootLoader 程序
程序下载完毕后,重新将启动模式设置为 “从Flash启动” ,然后开机运行用户程序。
【BootLoader】当选择系统存储器启动,从 0x0000 0000 跳转至对应地址启动(映射),

我们可以提前在系统存储器写入 BootLoader 程序(各种通信接口)的,然后以该方式启动
此时用 IAP 下载工具烧录程序,单片机执行 BootLoader 程序,会以对应的通信接口返回指定数据,符合通信要求后(收发特定数据)。
IAP 下载工具开始发送烧录程序(hex 文件),由单片机的 BootLoader 程序(利用对应通信接口)一一接收,然后逐个刷新到 Flash 上(Flash memory-主 Flash[0x0800 0000 - 0x0807 FFFF = 512KB 标定大小 ]),
一般出厂会自带 Boot 程序,一般系统存储器又叫 BootROM
2.2. 从主 Flash(Main Flash Memory)启动:这个是平时使用最多的方式,将程序下载到STM32内部Flash,然后从Flash启动。
【不是问题的问题】为什么STM32的Flash地址要设置到0x08000000 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz!
还是将 0x0800 0000 映射到 0x0000 0000(由 AHB 总线映射)


2.3. 从嵌入式 SRAM 启动(内部 SRAM):【比较好奇】
在SRAM中运行代码 - EdgeAI Lab
2.3.1. 为什么可以从 SRAM 启动:
至于为什么STM32还能从SRAM启动,ST官方资料https://www.st.com/content/ccc/resource/technical/document/reference_manual/59/b9/ba/7f/11/af/43/d5/CD00171190.pdf/files/CD00171190.pdf/jcr:content/translations/en.CD00171190.pdf中的3.4节 给出的说明是:
STM32F10xxx微控制器实现了一个特殊的机制使得STM32不仅能够从Flash memory 和 System memory启动,也能够从SRAM启动。从内嵌SRAM启动:SRAM仅能在地址0x2000 0000处被访问。
STM32F10xxx microcontrollers implement a special mechanism to be able to boot also from SRAM and not only from main Flash memory and System memory.Boot from the embedded SRAM: SRAM is accessible only at address 0x2000 0000.
以上说明并不清楚,ST官方对此含糊其辞,从SRAM启动的具体细节无从知晓,但是通过实验我们发现:
- 将STM32设置为从SRAM启动(a. 配置启动模式引脚BOOT0=1,BOOT1=1;b. 并修改链接脚本将所有代码全部放入SRAM中)
- 系统复位后PC指针总是指向0x2000 0108。
- 所以我们在地址0x2000 0108插入设置SP指针和PC指针的指令就可以实现从SRAM启动了。
请注意:从SRAM启动与在SRAM中运行代码是两个不同的概念。
- 从SRAM启动:
-
- 也属于在SRAM中运行代码,但不同的是程序下载到SRAM后,在MCU不断电的情况下,程序可以一直运行,并且按下复位键后可以重新运行。
- 在SRAM中运行代码:
-
- 将所有的代码放到SRAM运行,此时MCU的启动模式可以是从Main Flash Memory启动
- 将部分代码放到SRAM运行,此时MCU的启动模式可以是从Main Flash Memory启动
- 关于在SRAM中运行代码,请参考这篇文章:在SRAM中运行代码 - EdgeAI Lab
2.3.2. 为什么需要从SRAM启动【应用】
可能的原因有以下几点(参考资料《ARM Cortex M3 & M4权威指南》15.7节MCU经典书籍 - EdgeAI Lab):
- 所使用的设备可能具有OTP ROM(仅可进行一次编程),因此在最终确定前,是不会将程序编程到芯片中的。
- 有些微控制器中没有内部Flash存储器,需要使用外部的存储器,在软件开发期间,可能会想用内部的SRAM进行测试。
- 对于产品测试或者特定方面的测试,不想改动Flash中现有的程序实现某些新功能的测试工作,此时可以将测试代码下载到SRAM中运行。【在 Flash 烧一次后,不想改变现有 Flash 程序,但是想调试,可以利用 SRAM 空间进行调试】
- 对于Flash存储器比较小的系统,可能想在启动阶段将程序从Flash复制到SRAM中以提高性能,并在SRAM中执行程序以达到最佳性能。
- 在 SRAM 中也是可以放一个小的 BootLoader 程序,也可以搞 IAP 下载【应用案例:Jlink 下载算法启动后跑到 SRAM 中】
2.3.3. 从 SRAM 启动:
实现原理:
- 还是将 0x2000 0000 映射到 0x0000 0000(由 AHB 总线映射)

实现步骤:MCU的三种启动方式 - EdgeAI Lab
拿 M3(F103C8T6,RAM大小为20K) 举例
- 修改启动模式
将引脚BOOT0,BOOT1都设置为1,将STM32配置为从SRAM启动。
- 设置中断向量表偏移
添加宏定义 VECT_TAB_SRAM

- 该宏定义影响的代码:
// system_stm32f10x.c
// SystemInit()
#ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#elseSCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
- 修改启动代码
按照如下所示修改startup_stm32f10x_md.s文件
; 此处省略n行代码; Vector Table Mapped to Address 0 at Reset
; 此处修改AREA RESET, DATA, READONLY 为 AREA RESET, CODE, READONLYAREA RESET, CODE, READONLYEXPORT __VectorsEXPORT __Vectors_EndEXPORT __Vectors_Size__Vectors DCD __initial_sp ; Top of StackDCD Reset_Handler ; Reset HandlerDCD NMI_Handler ; NMI HandlerDCD HardFault_Handler ; Hard Fault HandlerDCD MemManage_Handler ; MPU Fault Handler; 此处省略n行代码DCD USBWakeUp_IRQHandler ; USB Wakeup from suspend; 下面是需要新添加的内容:DCD 0DCD 0DCD 0DCD 0DCD 0DCD 0DCD 0LDR R0, =0x20000000LDR SP,[R0]LDR R0, =0x20000004 LDR PC,[R0]ALIGN 4
; 以上是需要添加的代码; 此处省略n行代码
- 修改链接脚本
按照下图所示方式,即可在Keil编辑器中打开链接脚本:
打开链接脚本文件后,将内容修改如下:
; 以STM32F103C8T6为例
; 从SRAM启动终端向量表(RESET段)必须位于启动空间的0地址
; InRoot$$Sections 必须位于root区域(执行地址与装载地址相同的区域)LR_IROM1 0x20000000 0x00005000 { ;装载地址为SRAM首地址RW_IRAM1 0x20000000 0x00005000 { ;执行地址==装载地址*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO).ANY (+RW +ZI)}
}
- 修改Keil中的Flash Download设置
因为是直接从SRAM启动并执行程序,不需要对Flash进行操作,所以把Flash相关操作全部去掉。

- 以上就是完整的配置,现在编译项目并点击调试,就能看到程序成功在SRAM中运行了。
- 关闭调试后,只要STM32不断电,SRAM中的程序就可以一直运行,并且按下复位键后程序会重新运行。
2.3.4. 【补充】在 SRAM 中运行代码:
实现步骤:在SRAM中运行代码 - EdgeAI Lab
我的原文笔记:https://www.yuque.com/u41716106/ni1clp/bhxgk39vmaev9p26?singleDoc#
《【个人理解】MCU三种启动方式(Boot选择)[主Flash/系统存储器(BootLoader)/嵌入式SRAM]》
相关文章:
【单片机开发】MCU三种启动方式(Boot选择)[主Flash/系统存储器(BootLoader)/嵌入式SRAM]
目录 参考资料: 利用 Boot 选择不同的启动方式: 单片机的存储结构(主 FLASH/系统存储器/嵌入式 SRAM): 1. Cortex-M 内核芯片——启动原理: 1.1. 启动流程: 1.2. 根据单片机的存储器映射和架构图:启动…...
跨库移植 SQL
背景 应用程序可能要基于不同数据库工作,各种数据库的 SQL 语法大体一致,但仍有些差别,结果就要改造这些 SQL,而这事通常只能手工调整,工作量大还容易出错。 完全自动改造 SQL 几乎是无法做到的,毕竟各种…...
(软件测试文档大全)测试计划,测试报告,测试方案,压力测试报告,性能测试,等保测评,安全扫描测试,日常运维检查测试,功能测试等全下载
1. 引言 1.1. 编写目的 1.2. 项目背景 1.3. 读者对象 1.4. 参考资料 1.5. 术语与缩略语 2. 测试策略 2.1. 测试完成标准 2.2. 测试类型 2.2.1. 功能测试 2.2.2. 性能测试 2.2.3. 安全性与访问控制测试 2.3. 测试工具 3. 测试技术 4. 测试资源 4.1. 人员安排 4.2. 测试环境 4.2.…...
Vue前端开发-路由跳转及带参数跳转
在Vue 3中,由于没有实例化对象this,因此,无法通过this去访问 $route对象,而是通过导入一个名为 useRouter 的方法,执行这个方法后,返回一个路由对象,通过这个路由对象就可以获取到当前路由中的信…...
服务器上安装 Node.js
在服务器上安装 Node.js 的过程根据你使用的操作系统和环境可能会有所不同。以下是一些常见的 Linux 发行版(如 Ubuntu 或 CentOS)上的安装步骤。 在基于 Red Hat/CentOS 的系统上安装 Node.js 设置 EPEL 仓库 如果没有启用 EPEL (Extra Packages for E…...
在阿里云/Linux环境搭建Gitblit服务
在阿里云/Linux环境搭建Gitblit服务 1. 整体描述2. 前期准备3. 安装步骤3.1 下载gitblit3.2 上传gitblit3.3 解压文件3.4 修改文件配置3.5 启动gitblit3.6 安全组配置 4. 总结 1. 整体描述 前段时间买了一个阿里云服务器,2核2G,3M固定带宽的配置&#x…...
MicroBlaze软核开发(二):GPIO
实现功能:使用 MicroBlaze软核,配置GPIO用拨码开关控制LED灯 Vivado版本:2018.3 目录 引言 vivado部分: 一、配置GPIO 二、生成HDL文件编译 SDK部分: 一、导出硬件启动SDK 二、新建应用程序工程 三、编写程序代…...
threejs相机辅助对象cameraHelper
为指定相机创建一个辅助对象,显示这个相机的视锥。 想要在场景里面显示相机的视锥,需要创建两个相机。 举个例子,场景中有个相机A,想要显示相机A的视锥,那么需要一个相机B,把B放在A的后面,两个…...
Luma 视频生成 API 对接说明
Luma 视频生成 API 对接说明 随着 AI 的应用变广,各类 AI 程序已逐渐普及。AI 已逐渐深入到人们的工作生活方方面面。而 AI 涉及的行业也越来越多,从最初的写作,到医疗教育,再到现在的视频。 Luma 是一个专业高质量的视频生成平…...
服务器数据恢复—EVA存储硬盘磁头和盘片损坏离线的数据恢复案例
服务器存储数据恢复环境&故障: 一台HP EVA存储中有23块硬盘,挂接到一台windows server操作系统的服务器。 EVA存储上有三个硬盘指示灯亮黄灯,此刻存储还能正常使用。管理员在更换硬盘的过程中,又出现一块硬盘对应的指示灯亮黄…...
【Python】深入探索Python类型检查:掌握 `typing` 模块的高级用法
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 随着代码复杂度的增加,类型安全性在现代开发中变得尤为重要。Python自3.5引入类型提示(type hints),为开发者提供了静态类型检查的能力,而typing模块则是这一系统的核心。本篇文章深入研究Python的类型提示及…...
Android学习15--charger
1 概述 最近正好在做关机充电这个,就详细看看吧。还是本着保密的原则,项目里的代码也不能直接用,这里就用的Github的。https://github.com/aosp-mirror 具体位置是:https://github.com/aosp-mirror/platform_system_core/tree/mai…...
顶会新宠!KAN-LSTM完美融合新方案
2024深度学习发论文&模型涨点之——KANLSTM KAN-LSTM混合预测模型是一种结合了自注意力机制(KAN, Key-attention network)和长短时记忆网络(LSTM)的深度学习模型,主要用于序列数据的预测任务,如时间序…...
JS中对象的浅拷贝,深拷贝和引用
JS中对象的浅拷贝,深拷贝和引用 浅拷贝和深拷贝的区别主要在于它们如何处理引用类型的数据(如数组和对象),而引用简而言之就是换了个变量名。 浅拷贝 引用:浅拷贝只复制对象的第一层属性,对于嵌套的对象或…...
思普企业运营平台 idsCheck Sql注入漏洞复现
0x01 产品描述: 思普企业运营平台是由贵阳思普信息技术有限公司自主研发的国内首款投融建管营云服务平台——...
FSWIND脉动风-风载时程生成器软件下载、安装及注册
1、软件下载 点击文末超链接下载 2、软件安装 以下操作,若被电脑杀毒软件提示风险,请加入白名单,软件无任何病毒和后台,请放心使用! 1)双击Fswind_setup.exe,启动安装程序 2)、点…...
spring通过RequestContextHolder获取HttpServletRequest对象
1.获取HttpServletRequest对象方法: public static HttpServletRequest getRequest() {ServletRequestAttributes attributes ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes());assert attributes ! null;return attributes.getRequest(…...
STM32编码器接口及编码器测速模板代码
编码器是什么? 编码器是一种将角位移或者角速度转换成一连串电数字脉冲的旋转式传感 器,我们可以通过编码器测量到底位移或者速度信息。编码器从输出数据类型上 分,可以分为增量式编码器和绝对式编码器。 从编码器检测原理上来分࿰…...
qt QNetworkAccessManager详解
1、概述 QNetworkAccessManager是QtNetwork模块中的一个核心类,它允许应用程序发送网络请求并接收响应。该类是网络通信的基石,提供了一种方便的方式来处理常见的网络协议,如HTTP、HTTPS等。QNetworkAccessManager对象持有其发送的请求的通用…...
部署 Vue 前端项目到 Linux
看看怎么把一个 Vue 3 项目部署到 Linux 服务器上。准备好你的咖啡,让我们愉快地度过这段部署时光! 前期准备 确保你已经在本地构建了 Vue 3 项目,并生成了 dist 文件夹。 npm run build构建完成后,你将看到一个新鲜出炉的 dis…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
3.3.1_1 检错编码(奇偶校验码)
从这节课开始,我们会探讨数据链路层的差错控制功能,差错控制功能的主要目标是要发现并且解决一个帧内部的位错误,我们需要使用特殊的编码技术去发现帧内部的位错误,当我们发现位错误之后,通常来说有两种解决方案。第一…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
C++ 基础特性深度解析
目录 引言 一、命名空间(namespace) C 中的命名空间 与 C 语言的对比 二、缺省参数 C 中的缺省参数 与 C 语言的对比 三、引用(reference) C 中的引用 与 C 语言的对比 四、inline(内联函数…...
MySQL账号权限管理指南:安全创建账户与精细授权技巧
在MySQL数据库管理中,合理创建用户账号并分配精确权限是保障数据安全的核心环节。直接使用root账号进行所有操作不仅危险且难以审计操作行为。今天我们来全面解析MySQL账号创建与权限分配的专业方法。 一、为何需要创建独立账号? 最小权限原则…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...
