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

stm32启动过程解析startup启动文件

1.STM32的启动过程模式

1.1 根据boot引脚决定三种启动模式

在这里插入图片描述

  1. 复位后,在 SYSCLK 的第四个上升沿锁存 BOOT 引脚的值。BOOT0 为专用引脚,而 BOOT1 则与 GPIO 引脚共用。一旦完成对 BOOT1 的采样,相应 GPIO 引脚即进入空闲状态,可用于其它用途。BOOT0与BOOT1引脚的不同值指向了三种启动方式:

    • 从主Flash启动。主Flash指的是STM32的内置Flash。选择该启动模式后,内置Flash的起始地址将被重映射到0x00000000地址,代码将在该处开始执行。一般我们使用JTAG或者SWD模式下载调试程序时,就是下载到这里面,重启后也直接从这启动。
    • 从系统存储器启动。系统储存器指的是STM32的内置ROM,选择该启动模式后,内置ROM的起始地址将被重映射到0x00000000地址,代码在此处开始运行。ROM中有一段出厂预置的代码,这段代码起到一个桥的作用,允许外部通过UART/CAN或USB等将代码写入STM32的内置Flash中。这段代码也被称为ISP(In System Programing)代码,这种烧录代码的方式也被称为ISP烧录。关于ISP、ICP和IAP之间的区别将在后续章节中介绍。
    • 从嵌入式SRAM中启动。显然,该方法是在STM32的内置SRAM中启动,选择该启动模式后,内置SRAM的起始地址将被重映射到0x00000000地址,代码在此处开始运行。这种模式由于烧录程序过程中不需要擦写Flash,因此速度较快,适合调试,但是掉电丢失。
  2. 总结:不同的配置决定了,MCU将何处映射到0x00000000。从这里又可以看到一点,MCU眼里只有0x00000000。至于为啥可以从Flash(0x08000000)启动,就是因为MCU内部做了映射。从其他位置启动时同理,如第一列,从Flash启动时,原本储存在0x0800000的程序映射到0x000000位置,,如下图是STM32F4xx中文参考手册中的图,可以看到类似的表述。同时,在下图中也展示了STM32F4xx中统一编址下,各内存的地址分配,注意一点,即使相应的内存被映射到了0x00000000起始的地址,通过其原来地址依然是可以访问的。

在这里插入图片描述

1.2 内存空间解释

  1. 上电序列或系统复位后,ARM处理器先从0x0000 0000地址获取栈顶值,再从0x0000 0004地址获得引导代码的基地址,然后从引导代码的基地址开始执行程序。所选引导源对应的存储空间会被映射到引导存储空间,即从0x0000 0000开始的地址空间。
  2. 如果片上SRAM(开始于0x2000 0000的存储空间)被选为引导源,用户必须在应用程序初始化代码中通过修改NVIC异常向量表和偏移地址将向量表重置到SRAM中。
  3. 当主FLASH存储器被选择作为引导源,从0x0800 0000开始的存储空间会被映射到引导存储空间。由于主FLASH存储器的Bank0或Bank1均可映射到地址0x0800 0000(通过配置SYSCFG_CFG0寄存器的FMC_SWP控制位),所以,微控制器可以使用该方法从Bank0或Bank1中启动。
  4. 为了使能引导块功能,选项字节中的BB控制位需要被置位。当该控制位被置位并且主FLASH存储器被选择作为引导源,微控制器从引导装载程序中启动并且引导装载程序跳至主FLASH存储器的Bank1中执行代码。在应用程序初始化代码中,用户必须通过修改NVIC异常向量表和偏移地址将向量表重置到Bank1基地址。

1.3 启动后bootloader做了什么?

在这里插入图片描述

  1. 根据BOOT引脚确定了启动方式后,处理器进行的第二大步就是开始从0x00000000地址处开始执行代码,而该处存放的代码正是bootloader即.s启动文件,名为startup_xxxx.s,在.s启动文件中指明了向量表,默认在0x08000000处,栈顶是一个栈顶指针,之后就是Reset_handler复位中断入口向量地址等等中断服务函数向量地址,每个地址4字节,所以是从MSP偏移0x00004字节处取出Reset_Handler。
  2. bootloader,也可以叫启动文件,每一种微控制器(处理器)都必须有启动文件,启动文件的作用便是负责执行微控制器从“复位”到“开始执行main函数”中间这段时间(称为启动过程)所必须进行的工作。

1.3 bootloader中对内存的搬移和初始化

本节针对程序在内置Flash中启动的情况进行分析。
在这里插入图片描述

  1. 我们知道烧录的镜像文件中包含只读代码段.text,已初始化数据段.data和未初始化的或者初始化为0的数据段.bss。代码段由于是只读的,所以是可以一直放在Flash中,CPU通过总线去读取代码执行就OK,但是.data段和.bss段由于会涉及读写,为了更高的读写效率是要一定搬到RAM中执行的,因此bootloader会执行很重要的一步,就是会在RAM中初始化.data和.bss段,搬移或清空相应内存区域。
  2. 因此我们知道,当启动方式选择的是从内置Flash启动的时候,代码依旧是在Flash中执行,而数据则会被拷贝到内部SRAM中,该过程是由bootloader完成的。bootloader在完成这些流程之后,就会将代码交给main函数开始执行用户代码。

1.4 ISP、IAP、ICP三种烧录方式

  • 虽然这个小节稍稍偏题,但是由于上面在3中启动方式中介绍过了ISP烧录,因此一并在此介绍剩下的两种烧录方式。

    1. ICP(In Circuit Programing)。在电路编程,可通过CPU的Debug Access Port 烧录代码,比如ARM Cortex的Debug Interface主要是SWD(Serial Wire Debug)或JTAG(Joint Test Action Group);
    2. ISP(In System Programing)。在系统编程,可借助MCU厂商预置的Bootloader 实现通过板载UART或USB接口烧录代码。
    3. IAP(In Applicating Programing)。在应用编程,由开发者实现Bootloader功能,比如STM32存储映射Code分区中的Flash本是存储用户应用程序的区间(上电从此处执行用户代码),开发者可以将自己实现的Bootloader存放到Flash区间,MCU上电启动先执行用户的Bootloader代码,该代码可为用户应用程序的下载、校验、增量/补丁更新、升级、恢复等提供支持,如果用户代码提供了网络访问功能,IAP 还能通过无线网络下载更新代码,实现OTA空中升级功能。
  • IAP和ISP 的区别。
    a、ISP程序一般是芯片厂家提供的。IAP一般是用户自己编写的
    b、ISP一般支持的烧录方式有限,只有串口等。IAP就比较灵活,可以灵活的使用各种通信协议烧录
    c、isp一般需要芯片进行一些硬件上的操作才行,IAP全部工作由程序完成,不需要去现场
    d、isp一般只需要按格式将升级文件通过串口发送就可以。IAP的话控制相对麻烦,如果是OTA的话还需要编写后台的。
    e、注意,这里介绍的bootloader功能显然跟之前介绍的启动文件bootloader有所区别,其目的是为了能接受外部镜像进行烧录,而不是为了运行普通用户程序。

2.启动文件startup_xxx.s(非GCC环境)

2.1 主要功能

  1. 在此我使用stm32f103-keil环境的启动文件startup_stm32f103xb.s为例进行简单的表述。startup_stm32f103xb.s是上电后执行的第一段代码:
    在这里插入图片描述
  2. 可看到该程序执行内容是:
1.初始化堆栈指针 SP=_initial_sp
2.初始化 PC 指针=Reset_Handler;并实现了复位的异常处理函数Reset_Handler
3.初始化中断向量表
4.配置系统时钟
5.调用 C 库函数_main 初始化用户堆栈,然后进入 main 函数。

2.2启动文件内容分析

0. 启动文件涉及的几个汇编命令
在这里插入图片描述

1. Stack栈
* 栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM 的大小。当程序较大时,需要修改栈的大小,不然可能会出现的HardFault的错误。
在这里插入图片描述

第32行:表示开辟栈的大小为 0X400(1KB),EQU是伪指令,相当于C 中的 define。
第34行:开辟一段可读可写数据空间,ARER 伪指令表示下面将开始定义一个代码段或者数据段。此处是定义数据段。ARER 后面的关键字表示这个段的属性。段名为STACK,可以任意命名;NOINIT 表示不初始化;READWRITE 表示可读可写,ALIGN=3,表示按照 8 字节对齐。
第35行:SPACE 用于分配大小等于 Stack_Size连续内存空间,单位为字节。
第37行: __initial_sp表示栈顶地址。栈是由高向低生长的。

2. Heap堆

  • 堆主要用来动态内存的分配,像malloc()函数申请的内存就在堆中。
    在这里插入图片描述
  • 开辟堆的大小为 0X200(512 字节),名字为 HEAP,NOINIT 即不初始化,可读可写,8字节对齐。__heap_base 表示对的起始地址,__heap_limit 表示堆的结束地址。
  • PRESERVE8用于指定当前文件的堆栈按照8字节对齐,THUMB表示后面的指令兼容THUMB指令,现在Cortex-M系列的都使用THUMB-2指令集,THUMB-2是32位的,兼容16位和32位的指令,是thumb的超集。
    3. 向量表
    * Cortex-M3 内核规定,起始地址必须存放栈顶指针,而第二个地址则必须存放复位中断入口向量地址,这样在 Cortex-M3 内核复位后,会自动从起始地址的下一个 32 位空间取出复位中断入口向量,跳转执行复位中断服务程序。Cortex-M3 内核固定了中断向量表的位置, 但是起始地址是可变化的,__initial_sp就是栈顶指针。
    * 向量表是一个WORD( 32 )数组,每个下标对应一种异常,该下标元素的值则是该 ESR 的入口地址。向量表在地址空间中的位置是可以设置的,通过 NVIC 中的一个重定位寄存器来指出向量表的地址。在复位后,该寄存器的值为 0。因此,在地址 0 (即 FLASH 地址 0)处必须包含一张向量表,用于初始时的异常分配。
    * 值得注意的是这里有个另类: 0 号类型并不是什么入口地址,而是给出了复位后 MSP 的初值,后面会具体讲解。
    在这里插入图片描述
    在这里插入图片描述
第55行:定义一块代码段,段名字是RESET,READONLY 表示只读。
第56-58行:使用EXPORT将3个标识符申明为可被外部引用,声明 __Vectors、__Vectors_End 和__Vectors_Size 具有全局属性。
第60行:__Vectors 表示向量表起始地址,DCD 表示分配 1 个 4 字节的空间。每行 DCD 都会生成一个 4 字节的二进制代码,中断向量表 存放的实际上是中断服务程序的入口地址。当异常(也即是中断事件)发生时,CPU 的中断系统会将相应的入口地址赋值给 PC 程序计数器,之后就开始执行中断服务程序。在60行之后,依次定义了中断服务程序的入口地址。
第121行:__Vectors_End 为向量表结束地址。
第123行:__Vectors_Size则是向量表的大小,向量表的大小是通过__Vectors 和__Vectors_End 相减得到的。

4. 复位程序Reset_Handler
* 复位程序是系统上电后执行的第一个程序,复位程序也是中断程序,只是这个程序比较特殊,因此单独提出来讲解。
在这里插入图片描述

第128行:定义了一个服务程序,PROC表示程序的开始。
第129行:使用EXPORT将Reset_Handler申明为可被外部引用,后面WEAK表示弱定义,如果外部文件定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。这里表示复位程序可以由用户在其他文件重新实现,这种写法在HAL库中是很常见的。
第130-131行:表示该标号来自外部文件,SystemInit()是一个库函数,在system_stm32f1xx.c中定义的,__main 是一个标准的 C 库函数,主要作用是初始化用户堆栈,这个是由编译器完成的,该函数最终会调用我们自己写的main函数,从而进入C世界中。
第132行:这是一条汇编指令,表示从存储器中加载SystemInit到一个寄存器R0的地址中。
第133行:汇编指令,表示跳转到寄存器R0的地址,并根据寄存器的 LSE 确定处理器的状态,还要把跳转前的下条指令地址保存到 LR。
第134行:和132行是一个意思,表示从存储器中加载__main到一个寄存器R0的地址中。
第135行:和133稍微不同,这里跳转到至指定寄存器的地址后,不会返回。
第136行:和PROC是对应的,表示程序的结束。

5. 中断服务程序

  • 我们平时要使用哪个中断,就需要编写相应的中断服务程序,只是启动文件把这些函数留出来了,但是内容都是空的,真正的中断复服务程序需要我们在外部的 C 文件里面重新实现,这里只是提前占了一个位置罢了。
    * 这部分没啥好说的,和服务程序类似的,只需要注意‘B .’语句,B表示跳转,这里跳转到一个‘.’,即表示无线循环。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    6. 堆栈初始化
    • 堆栈初始化是由一个IF条件来实现的,MICROLIB的定义与否决定了堆栈的初始化方式。

    • 这个定义是在Options->Target中设置的
      *

    • 需要注意的是,ALIGN表示对指令或者数据存放的地址进行对齐,缺省表示4字节对齐。

    • 如果没有定义 __MICROLIB , 则采用双段存储器模式,即堆区和栈区是分开的(如果不采用双段模式,因为堆和栈增长的方向是相反的,如果撞上了,程序会崩溃),且声明标号__user_initial_stackheap 具有全局属性,让用户自己来初始化堆栈。

在这里插入图片描述

以上就是Startup文件全部内容

3.启动文件分析(GCC环境)

GCC环境下STM32 的启动出除了需要 startup_xxxx.s 文件,还需要一个链接文件 .ld 文件:
在这里插入图片描述

3.1 .ld 链接文件

先从STM32L051C8Tx_FLASH.ld 文件来看,链接文件主要制定了入口函数,堆栈大小和数据段的整体布局。

3.1.1 开辟栈空间和堆空间

指定入口地址,开辟栈空间和堆空间:
在这里插入图片描述

第53行:指定入口地址为Reset_Handler复位中断
第56行:最大的RAM地址
第58-59行:指定堆、栈大小

3.1.2 指定布局

指定各数据段的布局:
在这里插入图片描述

第69行:输出文件布局
第72-79行:向量表,放在最前面
第80-94行:制定text段,存放代码
第97-103行:只读数据段

在这里插入图片描述

第134行:保存.data的地址
第137-146行:指定数据段在RAM中,只是刚开始保存在FLASH中,启动的时候拷贝到RAM
第150-162行:指定.bss段
第165-173行:最后根据前面定义的堆栈大小指定堆栈段

3.2 .s启动文件

3.2.1 基本说明

startup_stm32l051xx.s开头部分是基本说明:
在这里插入图片描述

第29行:CPU类型
第44行:thumb指令集
第38-46行:_sidata保存.data地址的变量,_sdata保存.data段的起始地址, _edata保存.data段的结束地址, _sbss保存.bss起始地址, _ebss保存.bss结束,这几个都在链接文件中定义

3.2.2 Reset_Handler

  • Reset_Handler 是程序最开始执行的地方,设置栈顶指针:
    在这里插入图片描述
第58-60行:.section设置新的代码段,.weak申明,.type将Reset_Handler指定为函数
第64行:系统初始化时钟
第67-70行:将.data段从flash放到RAM中去

3.2.3 跳转到SystemInit 和 main

回过头来看一下前面讲到的启动文件所做的工作:

设置堆栈指针 SP = _initial_sp
设置PC指针 = Reset_Handler
配置系统时钟
配置外部 SRAM 用于程序变量等数据存储(可选)
调用C库的 _main 函数,最终调用main函数

最终这里也是跳转到了main函数:

在这里插入图片描述

3.2.4 中断向量表部分

  • _estack是栈顶的值,这个值保存在flash的0地址出,flash的地址为0x08000000,所以0x08000000保存_estack的值,接下来就是Reset_Handler,和编译器环境中的启动文件部分一样
    在这里插入图片描述

参考

  1. https://blog.csdn.net/Setul/article/details/121685929
  2. https://jiayu.blog.csdn.net/article/details/135032170?fromshare=blogdetail&sharetype=blogdetail&sharerId=135032170&sharerefer=PC&sharesource=tao_sc&sharefrom=from_link
  3. https://blog.csdn.net/zhuimeng_ruili/article/details/119709888
  4. https://blog.csdn.net/weixin_42328389/article/details/120656722?fromshare=blogdetail&sharetype=blogdetail&sharerId=120656722&sharerefer=PC&sharesource=tao_sc&sharefrom=from_link

相关文章:

stm32启动过程解析startup启动文件

1.STM32的启动过程模式 1.1 根据boot引脚决定三种启动模式 复位后,在 SYSCLK 的第四个上升沿锁存 BOOT 引脚的值。BOOT0 为专用引脚,而 BOOT1 则与 GPIO 引脚共用。一旦完成对 BOOT1 的采样,相应 GPIO 引脚即进入空闲状态,可用于…...

SystemVerilog学习——构造函数new

一、概述 在 SystemVerilog 中,new 是一个构造函数,用于创建类的实例(即对象)。它在面向对象编程(OOP)中起着重要作用,负责实例化一个对象并进行初始化。与传统编程语言(如 C 或 Jav…...

力扣题目总结

1.游戏玩法分析IV AC: select IFNULL(round(count(distinct(Result.player_id)) / count(distinct(Activity.player_id)), 2), 0) as fraction from (select Activity.player_id as player_idfrom (select player_id, DATE_ADD(MIN(event_date), INTERVAL 1 DAY) as second_da…...

Java API 进阶指南:从核心API到高级应用的全面提升

文章目录 Java API 进阶学习指南1. 深入理解核心API1.1 集合框架(Collections Framework)1.2 输入输出流(I/O Streams)1.3 并发编程(Concurrency)1.4 反射(Reflection)1.5 泛型&…...

esp32c3开发板通过micropython的ubluetooth库连蓝牙设备

ESP32-C3开发板是一款高性能、低功耗的微控制器,搭载了Espressif自家的RISC-V处理器。通过MicroPython,一种面向微控制器的精简版Python编程语言,开发者可以轻松地为ESP32-C3编写代码。MicroPython的ubluetooth库使得ESP32-C3能够通过蓝牙与各…...

leetcode hot100【LeetCode 35.搜索插入位置】java实现

LeetCode 35.搜索插入位置 题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用 O(log n) 的时间复杂度来实现。 示例 1: 输入: nums [1,3,5,6…...

我们要用平凡来诠释非凡

#孟晚舟香港中文大学演讲# #华为价值观念# #并非站在山顶才能被看见# #传递正确的价值观# #如果信仰有颜色,那一定是中国红# #送给自己的价值理念# 在信息大爆炸的时代,很多同学都希望尽可能的抓取更多的知识,尽可能的不要遗漏任何热点…...

synchronized和volatile区别

synchronized和volatile是Java并发编程中两种重要的同步机制,它们之间存在明显的区别。以下是对这两者的详细比较: 一、基本定义与作用 synchronized 是一个用于实现线程同步的关键字。可以用来锁住方法或代码块,从而确保在同一时刻只有一个…...

125.验证回文串-力扣(LeetCode)

题目: 解题思路: 首先进行移除非字母数字字符,并将大写字符转换为小写字符的操作。这个过程中,主要利用快慢指针的方式来进行移除操作,通过加32将大写字符转换为小写字符。完成后,将前一半的数据与后一半的…...

线程间通信:wait和notify

线程间通信:wait和notify 1、Object的wait和notify方法 Java中的Object类提供了两个重要的方法,用于线程间的通信和同步:wait()方法和notify()方法 wait()方法的定义 方法签名:public final void wait() throws InterruptedEx…...

风险识别和管理的工具

1.‌风险识别工具和根本原因识别在项目管理中非常重要,常用的工具包括 因果图根本原因识别RCA鱼骨图 因果图 因果图是一种图形工具,用于识别问题或风险的根本原因。它通过将问题或风险因素与可能的根本原因联系起来,帮助团队更深入地了解问…...

qt之QFTP对文件夹(含嵌套文件夹和文件)、文件删除下载功能

一、前言 主要功能如下: 1.实现文件夹的下载和删除,网上很多资料都是单独对某个路径的文件操作的,并不能对文件夹操作 2.实现目标机中含中文名称自动转码,有些系统编码方式不同,下载出来的文件会乱码 3.实现ftp功能…...

为何数据库推荐将IPv4地址存储为32位整数而非字符串?

目录 一、IPv4地址在数据库中的存储方式? 二、IPv4地址的存储方式比较 (一)字符串存储 vs 整数存储 (二)IPv4地址"192.168.1.8"说明 三、数据库推荐32位整数存储方式原理 四、存储方式对系统性能的影响…...

Mybatis框架之责任链模式 (Chain of Responsibility Pattern)

在 MyBatis 框架中,责任链模式 (Chain of Responsibility Pattern) 被广泛应用于多个功能模块中,例如 插件拦截器、SQL 执行流程中的拦截器链、动态 SQL 的解析与处理等。这种设计模式为 MyBatis 提供了高度的扩展性和灵活性,使其能够轻松应对…...

C++ Stack和Queue---单向守护与无尽等待:数据结构的诗意表达

公主请阅 容器适配器容器适配器的特点 栈和队列的模拟实现deque的介绍1. 内存开销较高2.随机访问性能略低于 vector3. 与指针或迭代器的兼容性r4. 不适合用于需要频繁中间插入和删除的场景5. 在特定平台上的实现不一致6. 缺乏shrink_to_fit支持总结 题目 priority_queue 优先级…...

深入理解Java包装类与泛型的应用

今天我将带领大家进入Java包装类和泛型应用的学习。 我的个人主页 我的Java-数据结构专栏 :Java-数据结构,希望能帮助到大家。 一、Java包装类基础 二、Java泛型基础 三、Java包装类与泛型的结合 四、Java泛型进阶 五、Java包装类与泛型实战 一、Ja…...

【机器学习chp4】特征工程

推荐文章1,其中详细分析了为什么L1正则化可以实现特征选择(特征剔除) 【王木头 L1、L2正则化】三个角度理解L1、L2正则化的本质-CSDN博客 推荐文章2,里面详细分析了奇异值分解 【线性代数】矩阵变换-CSDN博客 本文遗留问题&#…...

LeetCode螺旋矩阵

快一个月没刷题了,最近工作有些忙,今天闲下来两小时,刷一道 题目描述 给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。 示例 1: 输入:matrix [[1,2,3],[4…...

第十五届蓝桥杯JAVA的B组题目详情解析

(第一个填空太简单,就不写了,根本不用代码,直接excel计算) 目录 蓝桥杯第二个填空,类斐波那契循环数 蓝桥杯JAVA.b组第三题 -分布式队列(模拟) 食堂(蓝桥杯D题) ​编辑 星际旅行(Floyd佛洛依德) 其余的有点变态,感觉学了好像…...

在几分钟内将数据从 Oracle 迁移到 ClickHouse

ClickHouse 是一个开源的面向列的数据库管理系统。它在实时数据处理方面的出色性能显着增强了数据分析和业务洞察力。将数据从 Oracle 迁移到 ClickHouse 可以释放数据在决策中的力量,这是单独使用 Oracle 无法实现的。 本教程介绍如何使用 BladePipe 将数据从 Orac…...

RestClient

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

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子,用于处理异步操作(如数据加载)中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误:捕获在 loader 或 action 中发生的异步错误替…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...

docker详细操作--未完待续

docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

MongoDB学习和应用(高效的非关系型数据库)

一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...

Java 加密常用的各种算法及其选择

在数字化时代,数据安全至关重要,Java 作为广泛应用的编程语言,提供了丰富的加密算法来保障数据的保密性、完整性和真实性。了解这些常用加密算法及其适用场景,有助于开发者在不同的业务需求中做出正确的选择。​ 一、对称加密算法…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...