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

ARM uboot 源码分析5 -启动第二阶段

一、start_armboot 解析6

1、console_init_f

在这里插入图片描述


(1) console_init_f 是 console(控制台)的第一阶段初始化。_f 表示是第一阶段初始化,_r 表示第二阶段初始化。有时候初始化函数不能一次一起完成,中间必须要夹杂一些代码,因此将完整的一个模块的初始化分成了 2 个阶段。(我们的 uboot 中 start_armboot 的 826 行进行了 console_init_r 的初始化)

在这里插入图片描述

在这里插入图片描述


(2) console_init_f 在 uboot/common/console.c 中,仅仅是对 gd->have_console 设置为 1 而已,其他事情都没做。


2、display_banner

在这里插入图片描述


(1) display_banner 用来串口输出显示 uboot 的 logo。
在**这**里插入图片描述


(2) display_banner 中使用 printf 函数向串口输出了 version_string 这个字符串。那么上面的分析表示, console_init_f 并没有初始化好 console, 怎么就可以 printf 了呢?

(3) 通过追踪 printf 的实现,发现 printf->puts,而 puts 函数中会判断当前 uboot 中 console 有没有被初始化好

如果 console 初始化好了,则调用 fputs 完成串口发送(这条线才是控制台);如果 console 尚未初始化好,则会调用 serial_puts (再调用 serial_putc 直接操作串口寄存器进行内容发送)

(4) 控制台也是通过串口输出,非控制台也是通过串口输出。究竟什么是控制台?和不用控制台的区别?

实际上分析代码会发现,控制台就是一个用软件虚拟出来的设备,这个设备有一套专用的通信函数(发送、接收···),控制台的通信函数,最终会映射到硬件的通信函数中来实现。uboot 中,实际上控制台的通信函数是直接映射到硬件串口的通信函数中的,也就是说 uboot 中用没用控制台,其实并没有本质差别

(5) 但是在别的体系中,控制台的通信函数映射到硬件通信函数时,可以用软件来做一些中间优化,譬如说缓冲机制。(操作系统中的控制台都使用了缓冲机制,所以有时候我们 printf 了内容,但是屏幕上并没有看到输出信息,就是因为被缓冲了。我们输出的信息只是到了 console 的 buffer 中,buffer 还没有被刷新到硬件输出设备上,尤其是在输出设备是LCD屏幕时)

(6) U_BOOT_VERSION 在 uboot 源代码中找不到定义,这个变量实际上是在 makefile 中定义的,然后在编译时生成的 include/version_autogenerated.h 中用一个宏定义来实现的。

在这里插入图片描述


3、print_cpuinfo

在这里插入图片描述

在这里插入图片描述

(1) uboot启动过程中:

CPU:  S5PV210@1000MHz(OK)APLL = 1000MHz, HclkMsys = 200MHz, PclkMsys = 100MHzMPLL = 667MHz, EPLL = 96MHzHclkDsys = 166MHz, PclkDsys = 83MHzHclkPsys = 133MHz, PclkPsys = 66MHzSCLKA2M  = 200MHz
Serial = CLKUART 

这些信息都是 print_cpuinfo 打印出来的。

(2) 回顾 ARM 裸机中时钟配置一章的内容,比对这里调用的函数中计算各种时钟的方法,自己去慢慢分析体会这些代码的原理和实现方法。


二、start_armboot 解析7

1、checkboard

在这里插入图片描述
在这里插入图片描述

(1) checkboard 看名字是检查、确认开发板的意思。这个函数的作用就是检查当前开发板是哪个开发板并且打印出开发板的名字。


2、init_func_i2c

在这里插入图片描述

(1) 这个函数实际没有被执行,X210 的 uboot 中并没有使用 I2C。如果将来我们的开发板要扩展 I2C 来接外接硬件,则在 x210_sd.h 中配置相应的宏即可开启。


3、uboot 学习实践

(1) 对 uboot 源代码进行完修改(修改内容根据自己的理解和分析来修改)

在这里插入图片描述

(2) make distclean 然后 make x210_sd_config 然后 make。

make distclean
make x210_sd_config
make -j8

在这里插入图片描述

(3) 编译完成得到 u-boot.bin,然后去烧录。烧录方法按照 x210 刷机教程 讲的 linux 下使用 dd 命令来烧写的方法来烧写。

(4) 在 uboot_jiuding 文件夹下,就有 sd_fusing 烧录所需的文件。

在这里插入图片描述


注意,由于这个路径的文件是被九鼎官方编译过的,里面的文件是 64 bit 格式的;而我们的 linux 系统是 32 bit ,所以必须先make clean 清除后,重新编译生成文件。

在这里插入图片描述

烧写过程:
第一步:进入 sd_fusing 目录下
第二步:make clean
第三步:make

在这里插入图片描述

第四步:插入 SD 卡,ls /dev/sd* 得到 SD 卡在 ubuntu 中的设备号(一般是/dev/sdb,注意 SD 卡要连接到虚拟机 ubuntu 中,不要接到 windows 中)

在这里插入图片描述

注意,我们的 sd_fusing.sh 文件就是写的 /dev/sdb ,如有需要可以自行更改。

在这里插入图片描述


第五步:修改 sd_fusing.sh 文件:u-boot.bin.
在这里插入图片描述

./sd_fusing.sh /dev/sdb 完成烧录(注意不是 sd_fusing2.sh)。

在这里插入图片描述

(5) 总结:uboot 就是个庞大点复杂点的裸机程序而已,我们完全可以对他进行调试。调试的方法就是按照上面步骤,根据自己对代码的分析和理解对代码进行更改,然后重新编译烧录运行,根据运行结果来学习。


修改效果成功

在这里插入图片描述


三、start_armboot 解析8

1、dram_init

在这里插入图片描述
在这里插入图片描述

(1) dram_init 看名字是关于 DDR 的初始化。疑问:在汇编阶段已经初始化过 DDR 了,否则也无法 relocate 到这里的第二部分运行,怎么在这里又初始化 DDR ?

(2) dram_init 都是在给 gd->bd 里面关于 DDR 配置部分的全局变量赋值,让 gd->bd 数据记录下当前开发板的 DDR 的配置信息,以便uboot中使用内存。

(3) 从代码来看,其实就是初始化 gd->bd->bi_dram 这个结构体数组。


2、display_dram_config

在这里插入图片描述
在这里插入图片描述

(1) 看名字意思就是打印显示 dram 的配置信息。

(2) 启动信息中的:(DRAM: 512 MB) 就是在这个函数中打印出来的。


uboot bdinfo 命令

思考:如何在 uboot 运行中得知 uboot 的 DDR 配置信息?uboot 中有一个命令叫 bdinfo ,这个命令可以打印出 gd->bd 中记录的所有硬件相关的全局变量的值,因此可以得知 DDR 的配置信息。

DRAM bank   = 0x00000000
-> start    = 0x30000000
-> size     = 0x10000000
DRAM bank   = 0x00000001
-> start    = 0x40000000
-> size     = 0x10000000

在这里插入图片描述


3、init_sequence总结

(1) 都是板级硬件的初始化以及 gd、gd->bd 中的数据结构的初始化。譬如:
网卡初始化、机器码(gd->bd->bi_arch_number)、内核传参 DDR 地址(gd->bd->bi_boot_params)、Timer4 初始化为 10ms 一次、波特率设置(gd->bd->bi_baudrate和gd->baudrate)、console 第一阶段初始化(gd->have_console 设置为 1 )、打印uboot 的启动信息、打印 cpu 相关设置信息、检查并打印当前开发板名字、DDR 配置信息初始化(gd->bd->bi_dram)、打印 DDR 总容量。


四、start_armboot 解析9

1、CFG_NO_FLASH

在这里插入图片描述

在这里插入图片描述

(1) 虽然 NandFlashNorFlash 都是 Flash,但是一般 NandFlash 会简称为 Nand 而不是 Flash,一般讲 Flash 都是指的 Norflash。这里的 2 行代码是 Norflash 相关的

(2) flash_init 执行的是开发板中对应的 NorFlash 的初始化、display_flash_config 打印的也是 NorFlash 的配置信息(Flash: 8 MB 就是这里打印出来的)。但是实际上 X210 中是没有 Norflash 的。所以这两行代码是可以去掉的(我也不知道为什么没去掉?猜测原因有可能是去掉这两行代码,会导致别的地方工作不正常,需要花时间去移植调试,然后移植的人就懒得弄。实际上不去掉,除了显示有 8MB Flash 实际没用之外,也没有别的影响)

CONFIG_VFD 和 CONFIG_LCD 是显示相关的,这个是 uboot 中自带的 LCD 显示的软件架构。但是实际上我们用 LCD 而没有使用 uboot 中设置的这套软件架构,我们自己在后面自己添加了一个 LCD 显示的部分。

在这里插入图片描述


2、mem_malloc_init

在这里插入图片描述
在这里插入图片描述

(1) mem_malloc_init 函数用来初始化 uboot 的堆管理器。

(2) uboot 中自己维护了一段堆内存,肯定自己就有一套代码来管理这个堆内存。有了这些东西 uboot 中你也可以 malloc、free 这套机制来申请内存和释放内存。我们在 DDR 内存中给堆预留了 896KB 的内存。


3、代码实践,去掉 Flash 看会不会出错。

结论:加上CONFIG_NOFLASH 宏之后编译出错,说明代码移植的不好,那个文件的包含没有被这个宏控制。于是乎移植的人就直接放这没管。


五、start_armboot 解析10

1、开发板独有初始化:mmc 初始化

在这里插入图片描述

(1) 从536 到 768 行,是开发板独有的初始化。意思是三星用一套 uboot 同时满足了好多个系列型号的开发板,然后在这里把不同开发板自己独有的一些初始化写到了这里。用 #if 条件编译配合 CONFIG_xxx 宏来选定特定的开发板。

(2) X210 相关的配置在 599 行到 632 行。
在这里插入图片描述


(3) mmc_initialize 看名字就应该是 MMC 相关的一些基础的初始化,其实就是用来初始化 SoC 内部的 SD/MMC 控制器的。函数在 uboot/drivers/mmc/mmc.c 里

(4) uboot 中对硬件的操作(譬如网卡、SD 卡···)都是借用的 linux 内核中的驱动来实现的,uboot 根目录底下有个 drivers 文件夹,这里面放的全都是从 linux 内核中移植过来的各种驱动源文件。

(5) mmc_initialize 是具体硬件架构无关的一个 MMC 初始化函数,所有的使用了这套架构的代码,都调用这个函数来完成 MMC 的初始化。mmc_initialize 中再调用 board_mmc_initcpu_mmc_init 来完成具体的硬件的 MMC 控制器初始化工作。

在这里插入图片描述


(6) cpu_mmc_init 在 uboot/cpu/s5pc11x/cpu.c 中,这里面又间接的调用了 drivers/mmc/s3c_mmcxxx.c 中的驱动代码来初始化硬件 MMC 控制器。这里面分层很多,分层的思想一定要有,否则完全就糊涂了。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


六、start_armboot 解析11

1、env_relocate

在这里插入图片描述

(1) env_relocate 是环境变量的重定位,完成从 SD 卡中将环境变量读取到 DDR 中的任务。

(2) 环境变量到底从哪里来?SD 卡中有一些(8个)独立的扇区作为环境变量存储区域的。但是我们烧录/部署系统时,我们只是烧录了 uboot 分区、kernel 分区和 rootfs 分区,根本不曾烧录 env 分区

所以当我们烧录完系统,第一次启动时 ENV 分区是空的,本次启动 uboot 尝试去 SD 卡的 ENV 分区读取环境变量时失败(读取回来后进行 CRC 校验时失败),我们 uboot 选择从 uboot 内部代码中设置的一套默认的环境变量出发来使用(这就是默认环境变量)。

这套默认的环境变量在本次运行时,会被读取到 DDR 中的环境变量中,然后被写入(也可能是你saveenv时写入,也可能是uboot设计了第一次读取默认环境变量后就写入)SD 卡的 ENV 分区。然后下次再次开机时,uboot 就会从 SD 卡的 ENV 分区读取环境变量到 DDR 中,这次读取就不会失败了。


(3) 真正的从 SD 卡到 DDR 中重定位 ENV 的代码是在 env_relocate_spec 内部的 movi_read_env 完成的。

在这里插入图片描述

在这里插入图片描述


七、start_armboot 解析12

1、IP地址、MAC地址的确定

在这里插入图片描述

(1) 开发板的 IP 地址是在 gd->bd 中维护的,来源于环境变量 ipaddr。 getenv 函数用来获取字符串格式的 IP 地址,然后用 string_to_ip 将字符串格式的 IP 地址转成字符串格式的点分十进制格式。

(2) IP 地址由 4 个 0-255 之间的数字组成,因此一个 IP 地址在程序中最简单的存储方法就是一个 unsigend int 。但是人类容易看懂的并不是这种类型,而是点分十进制类型(192.168.1.2)。这两种类型可以互相转换


2、devices_init

在这里插入图片描述

在这里插入图片描述

(1) devices_init 看名字就是设备的初始化。这里的设备指的就是开发板上的硬件设备。放在这里初始化的设备都是驱动设备,这个函数本来就是从驱动框架中衍生出来的。uboot 中很多设备的驱动是直接移植 linux 内核的(譬如网卡、SD卡),linux 内核中的驱动都有相应的设备初始化函数。linux 内核在启动过程中就有一个 devices_init (名字不一定完全对,但是差不多),作用就是集中执行各种硬件驱动的 init 函数。

(2) uboot 的这个函数其实就是从 linux 内核中移植过来的,它的作用也是去执行所有的从 linux 内核中继承来的那些硬件驱动的初始化函数


3、jumptable_init

在这里插入图片描述

(1) jumptable 跳转表,本身是一个函数指针数组,里面记录了很多函数的函数名。看这阵势是要实现一个函数指针到具体函数的映射关系,将来通过跳转表中的函数指针就可以执行具体的函数。这个其实就是在用 C 语言实现面向对象编程。在 linux 内核中有很多这种技巧。

(2) 通过分析发现跳转表只是被赋值从未被引用,因此跳转表在 uboot 中根本就没使用。

在这里插入图片描述


八、start_armboot 解析13

1、console_init_r

在这里插入图片描述

(1) console_init_f 是控制台的第一阶段初始化,console_init_r 是第二阶段初始化。实际上第一阶段初始化并没有实质性工作,第二阶段初始化才进行了实质性工作

(2) console_init_r 就是 console 的纯软件架构方面的初始化(说白了就是去给 console 相关的数据结构中填充相应的值),所以属于纯软件配置类型的初始化。

(4) uboot 的 console 实际上并没有干有意义的转化,它就是直接调用的串口通信的函数。所以用不用 console 实际并没有什么分别。(在 linux 内 console 就可以提供缓冲机制等不用 console 不能实现的东西)。

在这里插入图片描述


2、enable_interrupts

在这里插入图片描述

(1) 看名字应该是中断初始化代码。这里指的是 CPSR 中总中断标志位的使能。

(2) 因为我们 uboot 中没有使用中断,因此没有定义 CONFIG_USE_IRQ 宏,因此我们这里这个函数是个空壳子。

在这里插入图片描述


(3) uboot 中经常出现一种情况就是,根据一个宏是否定义了来条件编译决定是否调用一个函数内部的代码。uboot 中有 2 种解决方案来处理这种情况:方案一:在调用函数处使用条件编译,然后函数体实际完全提供代码。方案二:在调用函数处直接调用,然后在函数体处提供 2 个函数体,一个是有实体的一个是空壳子,用宏定义条件编译来决定实际编译时编译哪个函数进去。


3、loadaddr、bootfile 两个环境变量

在这里插入图片描述

(1) 这两个环境变量都是内核启动有关的,在启动 linux 内核时会参考这两个环境变量的值。


4、board_late_init

在这里插入图片描述

(1) 看名字这个函数就是开发板级别的一些初始化里比较晚的了,就是晚期初始化。所以晚期就是前面该初始化的都初始化过了,剩下的一些必须放在后面初始化的就在这里了。侧面说明了开发板级别的硬件软件初始化告一段落了。

(2) 对于 X210 来说,这个函数是空的。

在这里插入图片描述


九、start_armboot解析14

1、eth_initialize

在这里插入图片描述

(1) 看名字应该是网卡相关的初始化。这里不是 SoC 与网卡芯片连接时,SoC 这边的初始化,而是网卡芯片本身的一些初始化。

(2) 对于 X210(DM9000)来说,这个函数是空的。X210 的网卡初始化在 board_init 函数中,网卡芯片的初始化在驱动中

在这里插入图片描述

在这里插入图片描述


2、x210_preboot_init(LCD和logo显示)

在这里插入图片描述

(1) x210 开发板在启动起来之前的一些初始化,以及 LCD 屏幕上的 logo 显示。

在这里插入图片描述


3、check menukey to update from sd

在这里插入图片描述

(1) uboot 启动的最后阶段设计了一个自动更新的功能。就是:我们可以将要升级的镜像放到 SD 卡的固定目录中,然后开机时在 uboot 启动的最后阶段检查升级标志(是一个按键。按键中标志为 “LEFT” 的那个按键,这个按键如果按下则表示 update mode,如果启动时未按下则表示 boot mode)。如果进入 update mode,则 uboot 会自动从 SD 卡中读取镜像文件然后烧录到 iNand 中;如果进入 boot mode ,则 uboot 不执行 update,直接启动正常运行。

(2) 这种机制能够帮助我们快速烧录系统,常用于量产时用 SD 卡进行系统烧录部署。


4、死循环

在这里插入图片描述

(1) 解析器

在这里插入图片描述


(2) 开机倒数自动执行

在这里插入图片描述


(3) 命令补全

在这里插入图片描述


十、uboot 启动第 2 阶段总结

1、启动流程回顾、重点函数标出

(1) 第二阶段主要是对开发板级别的硬件、软件数据结构进行初始化。

(2) 代码流程顺序

    init_sequencecpu_init	空的board_init	网卡、机器码、内存传参地址dm9000_pre_init			网卡gd->bd->bi_arch_number	机器码gd->bd->bi_boot_params	内存传参地址interrupt_init	定时器env_initinit_baudrate	gd数据结构中波特率serial_init		空的console_init_f	空的display_banner	打印启动信息print_cpuinfo	打印CPU时钟设置信息checkboard		检验开发板名字dram_init		gd数据结构中DDR信息display_dram_config	打印DDR配置信息表mem_malloc_init		初始化uboot自己维护的堆管理器的内存mmc_initialize		inand/SD卡的SoC控制器和卡的初始化env_relocate		环境变量重定位gd->bd->bi_ip_addr	gd数据结构赋值gd->bd->bi_enetaddr	gd数据结构赋值devices_init		空的jumptable_init		不用关注的console_init_r		真正的控制台初始化enable_interrupts	空的loadaddr、bootfile 	环境变量读出初始化全局变量board_late_init		空的eth_initialize		空的x210_preboot_init	LCD初始化和显示logocheck_menu_update_from_sd	检查自动更新main_loop			主循环

2、启动过程特征总结

(1) 第一阶段为汇编阶段、第二阶段为 C 阶段;

(2) 第一阶段在 SRAM 中、第二阶段在 DRAM 中;

(3) 第一阶段注重 SoC 内部、第二阶段注重 SoC 外部 Board 内部;


3、移植时的注意点

(1) x210_sd.h 头文件中的宏定义;

(2) 特定硬件的初始化函数位置(譬如网卡)。


源自朱有鹏老师.

相关文章:

ARM uboot 源码分析5 -启动第二阶段

一、start_armboot 解析6 1、console_init_f (1) console_init_f 是 console(控制台)的第一阶段初始化。_f 表示是第一阶段初始化,_r 表示第二阶段初始化。有时候初始化函数不能一次一起完成,中间必须要夹杂一些代码,…...

【ip neigh】管理IP邻居( 添加ARP\NDP静态记录、删除记录、查看记录)

一、邻居管理存在状态 1、NUD_NONE: 初始状态。当一个新的路由缓存条目被创建时,arp_bind_neighbour()函数被调用.如果找不到相匹配的ARP缓存条目, neigh_alloc()将创建一个新的ARP缓存条目并设置状态为NUD_NONE. 2、NUD_INCOMPLETE:未完成状…...

Java程序员线上排查问题神器-Arthas

文章目录前言一、Arthas是什么?二、快速入门1.下载2.如何运行三、常用命令1.dashboard2.trace总结前言 最近公司项目版本迭代升级,在开发新需求导致没什么时间写博客。 在开发需求的过程中,我写了一个接口,去批量调内部已经写好…...

上市公司企业持续创新能力、创新可持续性(原始数据+计算代码+计算结果)(2008-2021年)

数据来源:自主计算 时间跨度:2008-2021年 区域范围:沪深A股上市公司 指标说明: 参考何郁冰(2017)[1]的做法,将持续创新作为独立研究变量,同时采用创新投入指标(研发经费) 和创新…...

华为OD机试 - 考古学家(JS)

考古学家 题目 有一个考古学家发现一个石碑 但是很可惜 发现时其已经断成多段 原地发现N个断口整齐的石碑碎片 为了破解石碑内容 考古学家希望有程序能帮忙计算复原后的石碑文字组合数 你能帮忙吗 备注: 如果存在石碑碎片内容完全相同,则由于碎片间的顺序不影响复原后的碑…...

Leetcode.2100 适合打劫银行的日子

题目链接 Leetcode.2100 适合打劫银行的日子 Rating : 1702 题目描述 你和一群强盗准备打劫银行。给你一个下标从 0开始的整数数组 security,其中 security[i]是第 i天执勤警卫的数量。日子从 0开始编号。同时给你一个整数 time。 如果第 i天满足以下所…...

linux ubuntu查日志信息以及错误排查

目录 一、linux的日志文件 1、常用日志文件 2、其他日志文件 二、历史日志的查看 1、查看Logrotate的配置信息 2、查看日志配置 一、linux的日志文件 Linux系统中最有趣的(可能也是最重要的)目录之一是/var/log。根据文件系统层次结构标准,在系统中运行的大多数…...

DOS经典软件,落下帷幕,新型国产平台,蓬勃发展

提起DOS时代,总让人难以忘怀,陷入深深回忆中,风靡一时的许多软件,如今早已不在,这几款被称为DOS必装的软件,更是让人惋惜。 你还记得这图吗?堪称DOS系统最经典的软盘复制与映像生成软件&#xf…...

MongoDB数据存储格式

前言 之前分享了MongoDB的基本命名和视图等信息,本文分享一下MongoDB的数据存储类型,使用方式。基础的MongoDB信息就学习完啦,之后会继续分享MongoDB进阶的一些东西。 MongoDB数据存储格式前言1 文件结构1.2 字段名称2 点符号2.2 嵌入式文件…...

ARC126D Pure Straight

ARC126D Pure Straight 题目大意 给一个长度为nnn的整数序列A(a1,a2,…,an)A(a_1,a_2,\dots,a_n)A(a1​,a2​,…,an​),其中ai∈[1,k]a_i\in [1,k]ai​∈[1,k]。 你可以做如下操作任意次: 交换相邻两个元素 求最小的操作次数,使得序列AA…...

基于RK3588的嵌入式linux系统开发(四)——uboot镜像下载(基于RKDevTool工具)

官方提供的SDK中包含RKDevTool工具(RKDevTool_Release_v2.92)和相应的驱动(DriverAssitant_v5.1.1)。本节主要介绍在windows操作系统环境下利用RKDevTool下载以上生成的uboot镜像和bootloader镜像。注意:本节使用的板卡…...

设计模式之策略模式与责任链模式详解和应用

目录1.策略模式1.1 目标1.2.内容定位1.3.定义1.4.应用场景1.5.促销优惠业务场景1.6 用策略模式实现选择支付方式的业务场景1.7 策略模式在框架源码中的体现1.8 策略模式的优缺点2 责任链模式2.1 责任链楼式的应用场景2.2 利用责任链模式进行数据校验拦截2.3 责任链模式和建造者…...

广度优先搜索(BFS)-蓝桥杯

一、BFS搜索的原理BFS搜索的原理:“逐层扩散”,从起点出发,按层次从近到远,逐层先后搜索。编码:用队列实现。应用:BFS一般用于求最短路径问题,BFS的特点是逐层搜索,先搜到的层离起点…...

Java Type类

文章目录Type简介Type分类1. 原始类型(Class)2. 参数化类型(ParameterizedType)3. 类型变量(TypeVariable)4. 通配符类型(WildcardType)5. 泛型数组类型(GenericArrayType)Type简介 Type是Java编程语言中所有类型的公共高级接口。它们包括原始类型、参数化类型、数组类型、类型…...

Springboot扩展点之CommandLineRunner和ApplicationRunner

Springboot扩展点系列:Springboot扩展点之ApplicationContextInitializerSpringboot扩展点之BeanFactoryPostProcessorSpringboot扩展点之BeanDefinitionRegistryPostProcessorSpringboot扩展点之BeanPostProcessorSpringboot扩展点之InstantiationAwareBeanPostPro…...

ngixn 常用配置之文件类型与自定义 log

大家好,我是 17 。 总结了一些 nginx 的常用配置。从入口文件开始,今天讲一下文件类型和自定义log 为了讲述方便,环境为 CentOS 7, nginx 版本 1.21。 配置文件入口 /etc/nginx/nginx.conf这是入口文件,这个文件里…...

【100个 Unity实用技能】 | Unity 通过自定义菜单将资源导出

Unity 小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。Unity 平台提供一整套完善的软件解决方案&#xff…...

0.3调试opencv源码的两种方式

调试opencv源码的两种方式 上两篇我们分别讲了如何配置opencv环境,以及如何编译opencv源码方便我们阅读。但我们还是无法调试我们的代码,无法以我们的程序作为入口来一步一步单点调试看opencv是如何执行的。 【opencv源码解析0.1】VS如何优雅的配置ope…...

Redis的常见操作和Session的持久化

安装Redis使用yum命令,直接将redis安装到linux服务器:yum -y install redis启动redis使用以下命令,以后台运行方式启动redis:redis -server /etc/redis.conf &操作redis使用以下命令启动redis客户端:redis-cli设置…...

TypeScript笔记(二)

背景 上一篇文章我们介绍了TypeScript的一些特性,主要是其与JavaScript的比较,接下来我们将会开始学习Type的语法,这篇文章将会介绍TypeScript的数据类型。 原始数据类型 TypeScript是JavaScript的超集,TypeScript的数据类型就…...

【MyBatis】源码学习 03 - 类型处理器 TypeHandler

文章目录前言参考目录学习笔记1、type 包中类的归类总结2、类型处理器2.1、TypeReference 类3、类型注册表3.1、TypeHandlerRegistry#getTypeHandler前言 本文内容对应的是书本第 8 章的内容,主要是关于类型处理器 TypeHandler 的学习。 这一章节的学习有些地方理…...

建造《流浪地球2》中要毁灭人类的超级量子计算机MOSS的核心量子技术是什么?

1.《流浪地球2》中的量子计算机 2023年中国最火的电影非《流浪地球2》莫属,在《流浪地球2》中有一个人工智能机器人MOSS ,它的前身是“550W”超级量子计算机,“MOSS”是它给自己起的名字(“550W”倒转180度就是“MOSS”&#xff…...

数据结构~七大排序算法(Java实现)

目录 插入排序 直接插入排序 希尔排序 选择排序 直接选择排序 堆排序 交换排序 冒泡排序 快速排序 递归实现 优化版本 归并排序 插入排序 直接插入排序 public class MySort {public static void insertSort(int[] array) {for (int i 1; i < array.length;…...

python练习

项目场景一&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 问题描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶…...

RPC-thrift实践

参考&#xff1a;https://www.cnblogs.com/52fhy/p/11146047.html 参考&#xff1a;https://juejin.cn/post/7138032523648598030 实践 安装thrift brew install thriftthrift -version 编写thrift文件 新建文件夹thrift新建文件 结构体文件 Struct.thrift 服务文件 Service.…...

Maven:工程的拆分与聚合

Maven 拆分与聚合创建父工程创建子模块pom.xml配置示例拆分与聚合 在 Maven 中, 拆分是将一个完整的项目分成一个个独立的小模块,聚合是将各个模块进一步组合,形成一个完整的项目。接下来简单示例拆分与聚合的过程。 创建父工程 父工程,一个pom工程,目录结构简单,只需有…...

使用uniapp创建小程序和H5界面

uniapp的介绍可以看官网&#xff0c;接下来我们使用uniapp创建小程序和H5界面&#xff0c;其他小程序也是可以的&#xff0c;只演示创建这2个&#xff0c;其实都是一套代码&#xff0c;只是生成的方式不一样而已。 uni-app官网 1.打开HBuilder X 选择如图所示&#xff0c;下…...

密度峰值聚类算法(DPC)

密度峰值聚类算法目录DPC算法1.1 DPC算法的两个假设1.2 DPC算法的两个重要概念1.3 DPC算法的执行步骤1.4 DPC算法的优缺点matlab代码密度计算函数计算delta寻找聚类中心点聚类算法目录 DPC算法 1.1 DPC算法的两个假设 1&#xff09;类簇中心被类簇中其他密度较低的数据点包围…...

RabbitMQ相关问题

文章目录避免重复消费(保证消息幂等性)消息积压上线更多的消费者&#xff0c;进行正常消费惰性队列消息缓存延时队列RabbitMQ如何保证消息的有序性&#xff1f;RabbitMQ消息的可靠性、延时队列如何实现数据库与缓存数据一致&#xff1f;开启消费者多线程消费避免重复消费(保证消…...

操作系统 三(存储管理)

一、 存储系统的“金字塔”层次结构设计原理&#xff1a;cpu自身运算速度很快。内存、外存的访问速度受到限制各层次存储器的特点&#xff1a;1&#xff09;主存储器&#xff08;主存/内存/可执行存储器&#xff09;保存进程运行时的程序和数据&#xff0c;内存的访问速度远低于…...

怎么制作网站主题/营销推广活动策划

你应该认真对待Sprint目标的8个理由 在sprint期间&#xff0c;开发团队可以讨论并跟踪与sprint目标相关的进度。这有助于监控和评估整个sprint过程中的进展。冲刺目标 (Sprint Goal) 为构建产品增量提供了一个理由: 在“冲刺”的末尾&#xff0c;团队应该产生一个潜在的可发布…...

阿里云服务器学生优惠/宁波seo外包平台

1、测试心理 上文中曾经提到过研发和测试在思路和观念上的一些矛盾。多数情况下&#xff0c;研发工程师并不精通软件测试的思路&#xff0c;因此可能会认为测试无非就是走一个流程&#xff0c;认为“软件测试就是证明软件不存在错误的过程”&#xff0c;或者“测试的目的在于证…...

重庆疫情新闻发布会/网站seo优化分析

SQL映射 SQL映射文件 SQL映射xml文件是所有sql语句放置的地方&#xff0c;不同于JDBC连接的方法&#xff0c;需要构造方法&#xff0c;写statement和resultset语句才可以调用指定的sql语句&#xff0c;只需要把所有的sql语句写在配置文件中&#xff0c;根据不同的id&#xff0c…...

wordpress孵化器主题/济宁百度推广开户

事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性&#xff0c;称为 ACID&#xff08;原子性、一致性、隔离性和持久性&#xff09;属性&#xff0c;只有这样才能成为一个事务。事务管理特性&#xff0c;强制保持事务的原子性和一致性。事务启动之后…...

广州营销型网站建设公司哪家名气大/制作网站

需求说明&#xff1a; /* *需求说明: *获取元素&#xff1a;tBodies,tHead,tFoot,rows,cells *表格的创建 *数据添加 *隔行变色 *删除操作&#xff0c;剩余表格重新计算&#xff0c;实现隔行变色*/HTML: <table id"table1"><tbody><tr><th>编…...

怎样给网站做百度推广/百度网址输入

本节书摘来自异步社区《Python数据分析》一书中的第1章&#xff0c;第1.9节&#xff0c;作者【印尼】Ivan Idris&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看 1.9 从何处寻求帮助和参考资料 在流行的软件开发论坛Stack Overflow上&#xff0c;也有数以百计…...