西安 网站搭建/自媒体平台注册入口
目录
1 问题一:内核移植时MTD分区问题
2 问题二:uboot的MTDPARTS_DEFAULT定义的MTD分区,bootargs中的文件系统分区,内核的mtd_partition smdk_default_nand_part定义的分区,三者要对应起来
3 问题三:uboot不再传tag地址了,那内核怎么知道bootargs的
5 问题五:linux内核官网的疑问
6 下载内核源码
7 安装交叉编译工具链
8 修改顶层Makefile
9 修改时钟频率
10 修改MTD分区
11 关闭软件ECC校验
12 支持yaffs文件系统
13 支持设备树
14 配置内核
14.1 make s3c2410_defconfig
15 编译内核和设备树文件
16 下载内核
17 参考文献
在移植linux内核之前,我先把韦老师的开发手册过了一遍,发现了好几个不太明白的问题,先把这些问题都弄明白再移植。
1 问题一:内核移植时MTD分区问题
Linux开发手册上,内核移植MTD分区那里,0地址保存的竟然是kernel,我记得之前0地址不都是保存的bootloader吗,
看到这里不理解,如果0地址保存的是kernel,那不是把bootloader覆盖了吗,搞不懂,一直没弄懂怎么回事,直到我往前翻,看到了uboot移植的介绍那里,我发现了这个
原来韦老师是把bootloader放到了norflash里面,怪不得nandflash的0就直接放kernel,因为我是先移植内核,先看的内核移植部分,所以没看到这里。 不过我移植内核的时候不会按老师这种方式做,我还是nandflash的0地址先放bootloader。
2 问题二:uboot的MTDPARTS_DEFAULT定义的MTD分区,bootargs中的文件系统分区,内核的mtd_partition smdk_default_nand_part定义的分区,三者要对应起来
这个是什么意思呢,就是uboot中有分区定义,如下
#define MTDIDS_DEFAULT "nand0=nandflash0"
#define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k@0(bootloader)," \"128k(device_tree)," \"128k(params)," \"4m(kernel)," \"-(root)"
这里uboot定义的是前面256k存放bootloader,然后接下来128k存放的是设备树,然后接下来128k存放的是参数,然后接下来4m保存的是内核,后面的是文件系统。
那么bootargs里面,root赋值就要是 root=/dev/mtdblock4
bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200";
然后内核中 就要这么定义,
static struct mtd_partition smdk_default_nand_part[] = {[0] = {.name = "bootloader",.size = SZ_256K,.offset = 0,},[1] = {.name = "device_tree",.offset = MTDPART_OFS_APPEND,.size = SZ_128K,},[2] = {.name = "params",.offset = MTDPART_OFS_APPEND,.size = SZ_128K,},[3] = {.name = "kernel",.offset = MTDPART_OFS_APPEND,.size = SZ_4M,},[4] = {.name = "rootfs",.offset = MTDPART_OFS_APPEND,.size = MTDPART_SIZ_FULL,}};
3 问题三:uboot不再传tag地址了,那内核怎么知道bootargs的
我看了韦老师的设备树里面用的uboot,他那里的uboot在调用theKernel的时候,第三个参数传进来的是设备树文件的地址,并没有传启动参数的保存地址也就是tag地址,那么内核怎么得到bootargs那些参数呢,这个问题也没想明白,在技术群里问了下,他们说可能是启动参数直接放设备树里面了,于是我去看了下设备树,在设备树中找到了下面一行,
chosen {bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200";};
原来是把启动参数放到设备树里面了。
但是,看了下新版的uboot源码,其实新版里面是可以传tag,也可以传设备树文件地址。新版源码如下图,
而韦老师是因为用的老版的uboot,但是又想在老板uboot里面支持设备树,所以韦老师修改如下
theKernel = (void (*)(int, int, uint))ntohl(hdr->ih_ep);+ /* 100ask for device tree, no initrd image used */
+ if (argc == 4) {
+ of_flat_tree = (char *) simple_strtoul(argv[3], NULL, 16);
+
+ if (be32_to_cpu(*(ulong *)of_flat_tree) == OF_DT_HEADER) {
+ printf ("\nStarting kernel with device tree at 0x%x...\n\n", of_flat_tree);
+
+ cleanup_before_linux ();
+ theKernel (0, bd->bi_arch_number, of_flat_tree);
+
+ } else {
+ printf("Bad magic of device tree at 0x%x!\n\n", of_flat_tree);
+ }
+
+ }
+
如果参数等于4就把设备树地址传给内核,这是因为使用设备树时候,我们输入的bootm命令是4个参数。
bootm <uImage_addr> // 无设备树,bootm 0x30007FC0
bootm <uImage_addr> <initrd_addr> <dtb_addr> // 有设备树
另外还一个问题就是在使用设备树的时候,如果也还是传输过来了bootargs,那么bootargs的优先级更高,
从设备树(dtb格式数据)中解析出bootargs_dts bootargs_正在起飞的蜗牛的博客-CSDN博客
(1)内核启动参数bootargs保存在设备树的chosen节点的bootargs属性;
(2)bootargs数据可以是在dts源文件中定义,也可以是uboot启动内核时传递给内核;
(3)优先级:uboot传递的bootargs参数优先级高于dts中定义的bootargs;
(4)如果是uboot传递的bootargs,在内核解压缩阶段就会调用atags_to_fdt()函数将tag中的bootargs参数转换成dtb的格式,写进dtb数据中;
这时候内核用的应该是zImage-dtb格式:vmlinuz/vmlinux、Image、zImage与uImage的区别_vmlinux和uimage_正在起飞的蜗牛的博客-CSDN博客
4 问题四:内核是怎么解析uboot传过来的tags地址或者设备树地址的
之前老的uboot里面,调用theKernel函数的时候,第三参数是tag地址也就是bootargs的那些地址,但是,新版的uboot里面,调用theKernel函数启动内核的时候,第三个参数可能是tags地址,也可能是设备树地址,那么内核肯定是两种方式都支持,那么是怎么支持的,这个我去看了下这一块的内核源码,先不看head.S了,直接去看start_kernel函数,
asmlinkage __visible void __init start_kernel(void)
{char *command_line;char *after_dashes;set_task_stack_end_magic(&init_task);smp_setup_processor_id();debug_objects_early_init();cgroup_init_early();local_irq_disable();early_boot_irqs_disabled = true;/** Interrupts are still disabled. Do necessary setups, then* enable them.*/boot_cpu_init();page_address_init();pr_notice("%s", linux_banner);setup_arch(&command_line);........//其他代码
然后看这里面的setup_arch函数,在arch/arm/kernel/setup.c里面,
void __init setup_arch(char **cmdline_p)
{const struct machine_desc *mdesc;setup_processor();/*这个__atags_pointer就是uboot穿进来的第三个参数,也就是tag地址或者设备树地址,然后这个setup_machine_fdt里面是对设备树是否有效,*/mdesc = setup_machine_fdt(__atags_pointer);if (!mdesc)mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);//上面判断设备树无效,那说明穿进来的就是tag地址了。那么解析tag。if (!mdesc) {early_print("\nError: invalid dtb and unrecognized/unsupported machine ID\n");early_print(" r1=0x%08x, r2=0x%08x\n", __machine_arch_type,__atags_pointer);if (__atags_pointer)early_print(" r2[]=%*ph\n", 16,phys_to_virt(__atags_pointer));dump_machine_table();}machine_desc = mdesc;
这里面首先是setup_machine_fdt函数,在这个setup_machine_fdt函数里面调用early_init_dt_verify函数判断是否是有效的设备树,然后再解析设备树。
/*** setup_machine_fdt - Machine setup when an dtb was passed to the kernel* @dt_phys: physical address of dt blob** If a dtb was passed to the kernel in r2, then use it to choose the* correct machine_desc and to setup the system.*/
const struct machine_desc * __init setup_machine_fdt(unsigned int dt_phys)
{const struct machine_desc *mdesc, *mdesc_best = NULL;#if defined(CONFIG_ARCH_MULTIPLATFORM) || defined(CONFIG_ARM_SINGLE_ARMV7M)DT_MACHINE_START(GENERIC_DT, "Generic DT based system").l2c_aux_val = 0x0,.l2c_aux_mask = ~0x0,MACHINE_ENDmdesc_best = &__mach_desc_GENERIC_DT;
#endifif (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys)))//判断是否有效的dtbreturn NULL;mdesc = of_flat_dt_match_machine(mdesc_best, arch_get_next_mach);if (!mdesc) {const char *prop;int size;unsigned long dt_root;early_print("\nError: unrecognized/unsupported ""device tree compatible list:\n[ ");dt_root = of_get_flat_dt_root();prop = of_get_flat_dt_prop(dt_root, "compatible", &size);while (size > 0) {early_print("'%s' ", prop);size -= strlen(prop) + 1;prop += strlen(prop) + 1;}early_print("]\n\n");dump_machine_table(); /* does not return */}/* We really don't want to do this, but sometimes firmware provides buggy data */if (mdesc->dt_fixup)mdesc->dt_fixup();early_init_dt_scan_nodes();
如果early_init_dt_verify函数判断不是有效的设备树,那么就调用setup_machine_tags函数,把第三个参数当成tag地址来解析,总结一下就是
setup_arch setup_machine_fdtif (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys)))//判断是否有效的dtbearly_init_dt_scan_nodes();mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);前面的没成立,那么说明传进来的不是设备树文件地址,而是启动参数的tag地址,那么这里是直接解析tag参数了,
5 问题五:linux内核官网的疑问
The Linux Kernel Archives
当我登录linux内核官网后,这里tarball是下载源码,然后后面我发现了两个东西patch和inc.patch,然后我鼠标放到patch提示Download patch to previous mainline,然后鼠标放到inc.patch提示Download incremental patch,搞不懂这两个有什么区别,然后我下载inc.patch发现名字是这样的patch-5.10.169-170.xz,那么这个应该是说5.10.169到5.10.170的补丁,但是patch是啥,在技术交流群里问了下,别人跟我说linux的主版本号,我还是不懂,然后我去查了下linux版本号问题,例如5.10.170.21吧,5.10是主版本好,170是次版本号,然后21是扩展版本号,所以这里的patch:Download patch to previous mainline意思是5.10.170针对5.10增加的补丁文件,好,懂了。
然后还一个就是官网主页只显示了几个内核版本,其他版本在上面的那个Http:Index of /pub/
6 下载内核源码
我去The Linux Kernel Archives
这里不下载最新的了,就用4.19.275吧,下载完之后用下面的命令解压。
xz -d linux-4.19.275.tar.xz
tar -xavf linux-4.19.275.tar
7 安装交叉编译工具链
这里用gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi.tar.xz,直接解压,然后设置环境变量就可以了,安装完之后我想看一下是否安装成功了,发现如下错误:
arm-linux-gcc --version
/usr/local/arm/4.3.2/bin/arm-linux-gcc: line 3: /usr/local/arm/4.3.2/bin/arm-none-linux-gnueabi-gcc: No such file or directory
网上搜了下,这是因为操作系统是64位的,而交叉编译工具链是32位的,所以需要安装下面的包兼容32位。
sudo apt-get install lib32z1
8 修改顶层Makefile
这里修改交叉编译工具链
#ARCH ?= $(SUBARCH)ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabi-
9 修改时钟频率
arch/arm/mach-s3c24xx/mach-smdk2440.c中将时钟频率修改为12M,
static void __init smdk2440_init_time(void)
{//s3c2440_init_clocks(16934400);s3c2440_init_clocks(12000000);samsung_timer_init();
}
10 修改MTD分区
arch/arm/mach-s3c24xx/common-smdk.c文件中,将代码
static struct mtd_partition smdk_default_nand_part[] = {[0] = {.name = "Boot Agent",.size = SZ_16K,.offset = 0,},[1] = {.name = "S3C2410 flash partition 1",.offset = 0,.size = SZ_2M,},[2] = {.name = "S3C2410 flash partition 2",.offset = SZ_4M,.size = SZ_4M,},[3] = {.name = "S3C2410 flash partition 3",.offset = SZ_8M,.size = SZ_2M,},[4] = {.name = "S3C2410 flash partition 4",.offset = SZ_1M * 10,.size = SZ_4M,},[5] = {.name = "S3C2410 flash partition 5",.offset = SZ_1M * 14,.size = SZ_1M * 10,},[6] = {.name = "S3C2410 flash partition 6",.offset = SZ_1M * 24,.size = SZ_1M * 24,},[7] = {.name = "S3C2410 flash partition 7",.offset = SZ_1M * 48,.size = MTDPART_SIZ_FULL,}
};
修改为下面的代码
static struct mtd_partition smdk_default_nand_part[] = {[0] = {.name = "bootloader",.size = SZ_256K,.offset = 0,},[1] = {.name = "device_tree",.offset = MTDPART_OFS_APPEND,.size = SZ_128K,},[2] = {.name = "params",.offset = MTDPART_OFS_APPEND,.size = SZ_128K,},[3] = {.name = "kernel",.offset = MTDPART_OFS_APPEND,.size = SZ_4M,},[4] = {.name = "rootfs",.offset = MTDPART_OFS_APPEND,.size = MTDPART_SIZ_FULL,}};
11 关闭软件ECC校验
修改arch/arm/mach-s3c24xx/common-smdk.c文件:
12 支持yaffs文件系统
Get Yaffs | Yaffs - A Flash File System for embedded use
yaffs官网上让用下面的命令下载
git clone git://www.aleph1.co.uk/yaffs2
然后需要运行文件系统里面的patch-ker.sh脚本文件,先./patch-ker.sh看一下使用说明
./patch-ker.sh
usage: ./patch-ker.sh c/l m/s kernelpathif c/l is c, then copy. If l then linkif m/s is m, then use multi version code. If s then use single version code
所以这里
13 支持设备树
这里移植内核的时候想把设备树也用上,然后参考了韦东山老师的设备树教程以及彭东林老师的这个博客:https://www.cnblogs.com/pengdonglin137/p/6241895.html
使用下面的设备树文件
// SPDX-License-Identifier: GPL-2.0
/** SAMSUNG SMDK2440 board device tree source** Copyright (c) 2018 weidongshan@qq.com* dtc -I dtb -O dts -o jz2440.dts jz2440.dtb*/#define S3C2410_GPA(_nr) ((0<<16) + (_nr))
#define S3C2410_GPB(_nr) ((1<<16) + (_nr))
#define S3C2410_GPC(_nr) ((2<<16) + (_nr))
#define S3C2410_GPD(_nr) ((3<<16) + (_nr))
#define S3C2410_GPE(_nr) ((4<<16) + (_nr))
#define S3C2410_GPF(_nr) ((5<<16) + (_nr))
#define S3C2410_GPG(_nr) ((6<<16) + (_nr))
#define S3C2410_GPH(_nr) ((7<<16) + (_nr))
#define S3C2410_GPJ(_nr) ((8<<16) + (_nr))
#define S3C2410_GPK(_nr) ((9<<16) + (_nr))
#define S3C2410_GPL(_nr) ((10<<16) + (_nr))
#define S3C2410_GPM(_nr) ((11<<16) + (_nr))/dts-v1/;/ {model = "SMDK24440";compatible = "samsung,smdk2440";#address-cells = <1>;#size-cells = <1>;memory@30000000 {device_type = "memory";reg = <0x30000000 0x4000000>;};
/*cpus {cpu {compatible = "arm,arm926ej-s";};};
*/ chosen {bootargs = "noinitrd root=/dev/mtdblock4 rw init=/linuxrc console=ttySAC0,115200";};led {compatible = "jz2440_led";reg = <S3C2410_GPF(5) 1>;};
};
将上述文件命名为jz2440.dts,放到arm/boot/dts/jz2440.dts
那同时要修改设备树里面的Makefile,增加 dtb-$(CONFIG_ARCH_S3C2440) += jz2440.dtb
前面设备树文件中compatible = "samsung,smdk2440";
那么在内核arch/arm/mach-s3c24xx/mach-smdk2440.c文件中首先增加如下定义
14 配置内核
14.1 make s3c2410_defconfig
我们首先使用make s3c2410_defconfig生成.config,然后再用make menuconfig图形化界面上微调。
make s3c2410_defconfig
然后发现报错
HOSTCC scripts/basic/fixdepHOSTCC scripts/kconfig/conf.oYACC scripts/kconfig/zconf.tab.c
/bin/sh: 1: bison: not found
scripts/Makefile.lib:196: recipe for target 'scripts/kconfig/zconf.tab.c' failed
make[1]: *** [scripts/kconfig/zconf.tab.c] Error 127
Makefile:557: recipe for target 's3c2410_defconfig' failed
make: *** [s3c2410_defconfig] Error 2
网上搜索发现用如下方法解决
sudo apt install bison flex
然后重新执行make s3c2410_defconfig,发现生成了.config,我们执行 make s3c2410_defconfig时所有配置项都被写到.config文件里面去了。
YACC scripts/kconfig/zconf.tab.cLEX scripts/kconfig/zconf.lex.cHOSTCC scripts/kconfig/zconf.tab.oHOSTLD scripts/kconfig/conf
#
# configuration written to .config
#
14.2 make menuconfig
然后我们执行make menuconfig,make menuconfig其实会去读上面生成的.config文件,然后会出现一个菜单供我们选择。
make menuconfig
这里加一个菜单使用说明:改菜单截图自https://www.cnblogs.com/lifexy/p/7342031.html
这里首先要配置支持yaff2文件系统。
File systems ---> [*] Miscellaneous filesystems ---><*> yaffs2 file system support
然后再Boot options里面发现设备树默认是选上的。
15 编译内核和设备树文件
配置完成之后用下面命令编译
make uImage -j8
报错
CALL scripts/checksyscalls.shCHK include/generated/compile.hKernel: arch/arm/boot/Image is readyKernel: arch/arm/boot/zImage is readyUIMAGE arch/arm/boot/uImage
"mkimage" command not found - U-Boot images will not be built
arch/arm/boot/Makefile:90: recipe for target 'arch/arm/boot/uImage' failed
make[1]: *** [arch/arm/boot/uImage] Error 1
arch/arm/Makefile:336: recipe for target 'uImage' failed
make: *** [uImage] Error 2
说明缺少 mkimage ,有两种解决办法:
- 利用uboot生成mkimage工具,然后拷贝到/usr/bin 目录下
- 输入 sudo apt-get install u-boot-tools 命令在线安装;
这里直接用
sudo apt-get install u-boot-tools
然后编译生成了uImage
CALL scripts/checksyscalls.shCHK include/generated/compile.hKernel: arch/arm/boot/Image is readyKernel: arch/arm/boot/zImage is readyUIMAGE arch/arm/boot/uImage
Image Name: Linux-4.19.275
Created: Thu Mar 9 13:45:42 2023
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3661464 Bytes = 3575.65 KiB = 3.49 MiB
Load Address: 30108000
Entry Point: 30108000Kernel: arch/arm/boot/uImage is ready
然后还要编译设备树文件:
make dtbs
生成arch/arm/boot/dts/jz2440.dtb。
16 下载内核
然后把uImage下载到开发板中,启动,发现卡住了。。。。。
NAND read: device 0 offset 0x40000, size 0x20000Reading data from 0x5f800 -- 100% complete.131072 bytes read: OK
## Booting image at 30007fc0 ...Image Name: Linux-4.19.275Created: 2023-03-09 6:59:04 UTCImage Type: ARM Linux Kernel Image (uncompressed)Data Size: 3660816 Bytes = 3.5 MBLoad Address: 30108000Entry Point: 30108000Verifying Checksum ... OK
OKStarting kernel with device tree at 0x32000000...
我也不知道错在哪里了,我去内核中的init/main.c中增加打印,
然后重新make uImage -j8,把内核下载进去,然后启动发现能打印出来
这说明内核已经到了start_kernel函数了,那我再加打印试试,
这样打印也看不出来啥问题,网上其他人在2440上移植内核的时候,看着都很顺利,不过他们没移植设备树,那我得问题很可能是移植设备树,然后有个什么地方我没弄好,我又回去去看了韦老师和彭东林老师的教程和博客。然后我发现了韦老师内核中有个这样的修改,
上面那段英文注释翻译过来是:目前有两种驱动程序可以为三星soc提供GPIO支持。对于支持设备树的平台,使用了新的pinctrl-samsung驱动程序,提供了GPIO和引脚控制接口。对于遗留(非dt)平台,使用这个驱动程序。
因为韦老师用了设备树文件,所以不注释掉的话,检测到设备树文件后,下面的那些初始化直接就不做了,但是韦老师的设备树文件又非常简单不完整,所以应该是内核少做了很多初始化工作,我把我的内核源码中这一块也注释掉,果然内核起来了。
内核起来了,但是还有个错误,这是文件系统的问题,内核移植就先到这里了。
17 参考文献
TQ2440(S3C2440)移植Linux-4.0.1内核全过程_觉皇不秃头的博客-CSDN博客
讓TQ2440也用上設備樹(1)
S3C2440 移植最新5.2linux内核
Linux设备树学习(三)uboot和Linux中的设备树移植
JZ2440支持设备树(1)-添加设备树之后kernel的启动参数跟dts里面不一致
Mini2440之linux内核移植
相关文章:

S3C2440移植Linux4.19.275内核以及过程中遇到的问题
目录 1 问题一:内核移植时MTD分区问题 2 问题二:uboot的MTDPARTS_DEFAULT定义的MTD分区,bootargs中的文件系统分区,内核的mtd_partition smdk_default_nand_part定义的分区,三者要对应起来 3 问题三:ubo…...

解忧杂货铺(二):UML时序图
目录 1、概述 2、UML时序图 2.1、什么是时序图 2.2、时序图的元素 2.2.1 角色(Actor) 2.2.2 对象(Object) 2.2.3 生命线(LifeLine) 2.2.4 控制焦点(Activation) 2.2.5 消息(Message) 2.2.6 自关联消息 2.2.7 组合片段 1、概述 在看AUTOSAR规范的时候发现时序图里面的…...

微信小程序的代码由哪些结构组成?
小程序官方建议把所有小程序的页面,都存放在pages 目录中,以单独的文件夹存在,如图所示: 其中,每个页面由4 个基本文件组成,它们分别是:js文件(页面的脚本文件,存放页面的数据、事件…...

Cloud Kernel SIG月度动态:发布 ANCK 新版本及 Plugsched v1.2.0
Cloud Kernel SIG(Special Interest Group):支撑龙蜥内核版本的研发、发布和服务,提供生产可用的高性价比内核产品。 01 2 月 SIG 整体进展 发布 ANCK 4.19.91-27.1 版本。 发布 ANCK 5.10.134-13.1 版本。 调度器热升级相关事…...

Jedis 使用详解(官方原版)
一、配置 Maven 依赖项Jedis也通过Sonatype作为Maven Dependency 分发。要配置它,只需将以下 XML 代码段添加到您的 pom.xml 文件中。<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>2.…...

关于Pytorch中的张量学习
关于Pytorch中的张量学习 张量的概念和创建 张量的概念 Tensor是pytorch中非常重要且常见的数据结构,相较于numpy数组,Tensor能加载到GPU中,从而有效地利用GPU进行加速计算。但是普通的Tensor对于构建神经网络还远远不够,我们需…...

基于Transformer的目标检测算法学习记录
前言 本文主要通过阅读相关论文了解当前Transformer在目标检测领域的应用与发展。 谷歌在 ICLR2020 上提出的 ViT(Vision Transformer)是将 Transformer 应用在视觉领域的先驱。从此,打开了Transformer进入CV领域的桥梁,NLP与CV几…...

嵌入式学习笔记——使用寄存器编程实现按键输入功能
文章目录前言模块介绍原理图编程思路前言 昨天,通过配置通用输出模式,实现了LED灯的点亮、熄灭以及流水等操作,解决了通用输出的问题,今天我们再借用最常见的输入模块,按键来实现一个按键控制LED的功能,重…...

打卡小达人之路:Spring Boot与Redis GEO实现商户附近查询
在当今社会,定位服务已经成为了各种应用的重要组成部分,比如地图、打车、美食等应用。如何在应用中实现高效的附近商户搜索功能呢?传统的做法是将商户的经纬度信息存储在关系型数据库中,然后使用SQL查询语句实现附近商户搜索功能。…...

Apache HTTP Server <2.4.56 mod_proxy_uwsgi 模块存在请求走私漏洞(CVE-2023-27522)
漏洞描述 Apache HTTP Server 是一个Web服务器软件。 该项目受影响版本存在请求走私漏洞。由于mod_proxy_uwsgi.c 中uwsgi_response方法对于源响应头缺少检查,当apache启用mod_proxy_uwsgi后,攻击者可利用过长的源响应头等迫使应转发到客户端的响应被截…...

JUC并发编程设计模式
一、保护性暂停 1.1 定义 即Guarded Suspension,用在一个线程等待另一 个线程的执行结果 要点 ● 有一个结果需要从一个线程传递到另一 个线程,让他们关联同一一个GuardedObject ● 如果有结果不断从一个线程到另一个线程那么可以使用消息队列(生产者…...

HTTPS加密解析
日升时奋斗,日落时自省 目录 1、加密解释 2、对称加密 3、非对称加密 4、证书 HTTPS(HyperText Transfer Protocol over Secure Socket Layer)也是一个应用层协议,是在HTTP协议的基础上引入了一个加密层 HTTP协议内容都是按…...

Python每日一练(20230309)
目录 1. 删除有序数组中的重复项 ★ 2. 二叉树的最小深度 ★★ 3. 只出现一次的数字 II ★★ 🌟 每日一练刷题专栏 C/C 每日一练 专栏 Python 每日一练 专栏 1. 删除有序数组中的重复项 给你一个有序数组 nums ,请你原地删除重复出现的元素…...

哈希表题目:数组的度
文章目录题目标题和出处难度题目描述要求示例数据范围解法思路和算法代码复杂度分析题目 标题和出处 标题:数组的度 出处:697. 数组的度 难度 4 级 题目描述 要求 给定一个非空且只包含非负数的整数数组 nums\texttt{nums}nums,数组的…...

初识rollup 打包、配置vue脚手架
rollup javascript 代码打包器,它使用了 es6 新标准代码模块格式。 特点: 面向未来,拥抱 es 新标准,支持标准化模块导入、导出等新语法。tree shaking 静态分析导入的代码。排除未实际引用的内容兼容现有的 commonJS 模块&#…...

软考网络工程师证书有用吗?
当然有用,但是拿到网络工程师证书的前提是对你自己今后的职业发展有帮助,用得到才能对你而言发挥它最大的好处。软考证书的具体用处:1.纳入我国高校人才培养和教学体系目前,软考已经被纳入高校人才培养和教学体系。在很多高校中&a…...

postgresql 自动备份 bat实现
postgres数据据备分,用cmd命令有些烦,写了个bat实现 BAT脚本中常用的注释命令有rem、@rem和:: rem、@rem和::用法都很简单,直接在命令后加上要注释的语句即可。例如下图,语言前加了rem,运行BAT时就会自动忽略这个句子。需要注释多行时,每行前面都要加上rem、@rem和::。…...

gdb:在命令行中会莫名暂停;detach-on-fork
这个没有捕获到断点的原因是,可能是多线程的问题,需要设置: set detach-on-fork off On Linux, if you want to debug both the parent and child processes, use the command: set detach-on-fork on/off on 默认设置,gdb会放弃子线程(或者父线程,受follow-fork-mode的…...

【3.9】RedisAOF日志、字符串、操作系统进程管理
4. 进程管理 进程、线程基础知识 什么是进程 我们编写的代码只是一个存储在硬盘的静态文件,通过编译后就会生成二进制可执行文件,当我们运行这个可执行文件后,它会被装载到内存中,接着 CPU 会执行程序中的每一条指令,…...

安装mayavi的成功步骤
这篇文章是python 3.6版本,windows系统下的安装,其他python版本应该也可以,下载对应的包即可。 一定不要直接pip install mayavi,这个玩意儿对vtk的版本有要求。 下载whl包 搞了很久不行,咱也别费那个劲了࿰…...

vue+echarts.js 实现中国地图——根据数值表示省份的深浅——技能提升
最近在写后台管理系统,遇到一个需求就是 中国地图根据数值 展示深浅颜色。 效果图如下: 直接上代码: 1.html部分 <div id"Map"></div>2.css部分——一定要设置尺寸 #Map {width: 100%;height: 400px; }3.js部分 …...

[oeasy]python0104_指示灯_显示_LED_辉光管_霓虹灯
编码进化 回忆上次内容 x86、arm、riscv等基础架构 都是二进制的包括各种数据、指令 但是我们接触到的东西 都是屏幕显示出来的字符 计算机 显示出来的 一个个具体的字型 计算机中用来展示的字型 究竟是 如何进化的 呢?🤔🤔 模拟电路时…...

Easy Deep Learning——卷积层
为什么需要卷积层,深度学习中的卷积是什么? 在介绍卷积之前,先引入一个场景 假设您在草地上漫步,手里拿着一个尺子,想要测量草地上某些物体的大小,比如一片叶子。但是叶子的形状各异,并且草地非…...

深入分析@Bean源码
文章目录一、源码时序图二、源码解析1. 运行案例程序启动类2. 解析AnnotationConfigApplicationContext类的AnnotationConfigApplicationContext(Class<?>... componentClasses)构造方法3. 解析AbstractApplicationContext类的refresh()方法4. 解析AbstractApplicationC…...

Web Components学习(1)
一、什么是web components 开发项目的时候为什么不手写原生 JS,而是要用现如今非常流行的前端框架,原因有很多,例如: 良好的生态数据驱动试图模块化组件化等 Web Components 就是为了解决“组件化”而诞生的,它是浏…...

Element-UI实现复杂table表格结构
Element-UI组件el-table用于展示多条结构类似的数据,可对数据进行排序、筛选、对比或其他自定义操作。将使用到以下两项,来完成今天demo演示:多级表头:数据结构比较复杂的时候,可使用多级表头来展现数据的层次关系。合…...

Azure AD 与 AWS 单一帐户SSO访问集成,超详细讲解,包括解决可能出现的错误问题
本教程介绍如何将 AWS Single-Account Access 与 Azure Active Directory (Azure AD) 相集成。 将 AWS Single-Account Access 与 Azure AD 集成后,可以: 在 Azure AD 中控制谁有权访问 AWS Single-Account Access。让用户使用其 Azure AD 帐户自动登录…...

lvgl 笔记 按钮部件 (lv_btn) 和 开关部件 (lv_switch)
按钮基础使用方法: lv_btn 和 lb_obj 使用方法一样,只是外表并不相同,基础创建方法只需一行代码。 lv_obj_t* btn lv_btn_create(lv_scr_act()); 添加大小和位置: lv_obj_t* btn lv_btn_create(lv_scr_act()); lv_obj_set_s…...

Python高频面试题——生成器(最通俗的讲解)
生成器定义在 Python 中,使用了 yield 的函数被称为生成器(generator)。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。 在调用生成器运行的过程中…...

品牌软文怎么写?教你几招
软文是什么?软文的本质就是广告,当然不是明晃晃的推销,而是自然隐晦地植入产品信息,引导更多用户自愿下单。 品牌软文对于写手的经验、内容的质量要求都相对较高,否则写出来的软文无法达到预期的效果。品牌软文怎么写…...