S3C2440移植Linux4.19.275内核以及过程中遇到的问题

news2024/11/16 13:44:13

目录

1 问题一:内核移植时MTD分区问题

2 问题二:uboot的MTDPARTS_DEFAULT定义的MTD分区,bootargs中的文件系统分区,内核的mtd_partition smdk_default_nand_part定义的分区,三者要对应起来

3 问题三:uboot不再传tag地址了,那内核怎么知道bootargs的

4 问题四:内核是怎么解析uboot传过来的tags地址或者设备树地址的

5 问题五:linux内核官网的疑问

6 下载内核源码

7 安装交叉编译工具链

8 修改顶层Makefile

9 修改时钟频率

10 修改MTD分区

11 关闭软件ECC校验

12 支持yaffs文件系统

13 支持设备树

14 配置内核

14.1 make s3c2410_defconfig

14.2 make menuconfig

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_END

	mdesc_best = &__mach_desc_GENERIC_DT;
#endif

	if (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys)))//判断是否有效的dtb
		return 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_fdt
        if (!dt_phys || !early_init_dt_verify(phys_to_virt(dt_phys)))//判断是否有效的dtb
        early_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 kernelpath
 if c/l is c, then copy. If l then link
 if 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/fixdep
  HOSTCC  scripts/kconfig/conf.o
  YACC    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.c
  LEX     scripts/kconfig/zconf.lex.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  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.sh
  CHK     include/generated/compile.h
  Kernel: arch/arm/boot/Image is ready
  Kernel: arch/arm/boot/zImage is ready
  UIMAGE  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.sh
  CHK     include/generated/compile.h
  Kernel: arch/arm/boot/Image is ready
  Kernel: arch/arm/boot/zImage is ready
  UIMAGE  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:  30108000
  Kernel: arch/arm/boot/uImage is ready

然后还要编译设备树文件:

make dtbs

生成arch/arm/boot/dts/jz2440.dtb。

16 下载内核

然后把uImage下载到开发板中,启动,发现卡住了。。。。。


NAND read: device 0 offset 0x40000, size 0x20000

Reading data from 0x5f800 -- 100% complete.
 131072 bytes read: OK
## Booting image at 30007fc0 ...
   Image Name:   Linux-4.19.275
   Created:      2023-03-09   6:59:04 UTC
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3660816 Bytes =  3.5 MB
   Load Address: 30108000
   Entry Point:  30108000
   Verifying Checksum ... OK
OK

Starting 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内核移植

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/399292.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

kafka:linux 安装 kafka集群

kafka运行依赖于 jdk、zookeeper&#xff0c;kafka可视化工具选择kafka-eagle。所以要装的组件有&#xff1a;jdk、zookeeper、kafka、kafka-eagle一、安装jdk下载linux版本的jdk包&#xff0c;比如&#xff1a;jdk-8u192-linux-x64.tar.gz。将其复制到 /opt 目录下并解压&…

设计模式(十八)----行为型模式之策略模式

1、概述 先看下面的图片&#xff0c;我们去旅游选择出行模式有很多种&#xff0c;可以骑自行车、可以坐汽车、可以坐火车、可以坐飞机。 作为一个程序猿&#xff0c;开发需要选择一款开发工具&#xff0c;当然可以进行代码开发的工具有很多&#xff0c;可以选择Idea进行开发&a…

第十届省赛——7外卖店优先级

题目&#xff1a;“饱了么”外卖系统中维护着N 家外卖店&#xff0c;编号1~N。每家外卖店都有一个优先级&#xff0c;初始时(0 时刻) 优先级都为0。每经过1 个时间单位&#xff0c;如果外卖店没有订单&#xff0c;则优先级会减少1&#xff0c;最低减到0&#xff1b;而如果外卖店…

New Bing的详细申请步骤与实际功能测试效果展示

文章目录前言申请方式申请出错解决方案测试总结前言 微软表示&#xff0c;new bing正在使用对话式人工智能来创造一种新的浏览网络的方式。用户将能够像ChatGPT那样与Bing聊天&#xff0c;用自然语言提出问题和接受答案。 同时&#xff0c;微软宣布了其搜索引擎Bing的新版本&a…

汽车微控制器芯片F280039CPZRQ1、F280039CSPM、F280039CSPN规格参数

F280039CPZRQ1、F280039CSPM、F280039CSPN是C2000实时微控制器系列中的一款器件。C2000微控制器是可扩展、超低延迟器件&#xff0c;旨在提高电力电子设备的效率&#xff0c;包括但不限于&#xff1a;高功率密度、高开关频率&#xff0c;并支持使用 GaN和SiC技术。F280039CPZRQ…

6个常用Pycharm插件推荐,老手100%都用过

人生苦短 我用python 有些插件是下载后需要重启Pycharm才生效的 免费领源码、安装包&#xff1a;扣扣qun 903971231 PyCharm 本身已经足够优秀&#xff0c; 就算不使用插件&#xff0c; 也可以吊打市面上 90%的 Python 编辑器。 如果硬要我推荐几款实用的话&#xff0c; 那么…

Beats:在 Docker 中同时部署 Metricbeat 和 Elasticsearch

在本教程中&#xff0c;我们将部署一个 metricbeat 来监控正在运行的容器的健康状况和系统指标。 为什么需要监控&#xff0c;为什么需要 Metricbeat&#xff1f; 一个常见的问题&#xff0c;但很少有人回答。 首先&#xff0c;无论我们部署的是 docker 容器还是老式的金属箱&…

代码随想录算法训练营第二十三天 | 669. 修剪二叉搜索树

打卡第23天&#xff0c;这一章节二叉树最后一天&#xff0c;难度渐渐上来了。 今日任务 669.修剪二叉搜索树108.将有序数组转换为二叉搜索树538.把二叉搜索树转换为累加树 669. 修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。…

中介效应分析-方法和模型发展【论文详解】

中介效应分析-方法和模型发展 – 潘登同学的论文精读 文章目录中介效应分析-方法和模型发展 -- 潘登同学的论文精读检验中介效应流程直接效应、间接效应与总效应完全中介与部分中介Stata代码考虑自变量X对因变量Y的影响, 如果X通过影响变量M而对Y产生影响, 则称M为中介变量。Yc…

VMware15配置NAT模式联通网络

最近为了测试C# 开发的桌面应用程序悬浮球的兼容性&#xff0c;在虚拟机上安装了win7系统和xp系统&#xff0c;之前也安装过黑苹果系统&#xff0c;但是win系统倒是第一次安装&#xff0c;在win7系统联网的时候&#xff0c;踩了一些坑&#xff0c;整理纪录一下。 设置主物理机配…

【JVM篇1】认识JVM,内存区域划分,类加载机制

目录 一、JVM内存区域划分 ①程序计数器(每个线程都有一个) ②栈&#xff1a;保存了局部变量和方法调用的信息(每一个线程都有一个栈) 如果不停地调用方法却没有返回值&#xff0c;会产生什么结果 ③堆(每一个进程都有一个堆&#xff0c;线程共享一个堆) 如何区分一个变量是…

【C++】C++11新特性——基础特性

文章目录一、列表初始化1.1 {}初始化1.2 initializer_list类型二、类型推导2.1 auto2.2 auto注意事项2.3 decltype三、新增与改进3.1 nullptr3.2 范围for3.3 array3.4 forward_list3.5 unordered系列3.6 final与override一、列表初始化 1.1 {}初始化 C11 引入了一个新的初始化…

[数据结构与算法(严蔚敏 C语言第二版)]第1章 绪论(章节题库+答案解析)

练习 选择题 算法的计算量的大小称为计算的&#xff08; &#xff09;。 A&#xff0e;效率 B&#xff0e;复杂性 C&#xff0e;现实性 D&#xff0e;难度 计算机算法指的是解决问题的步骤序列&#xff0c;它必须具备&#xff08; &#xff09;三个特性。 A&#xff0e;可执行…

“快速掌握如何用FFmpeg在Python中截取定时间隔的MP4视频画面“

目录 简介&#xff1a; 源代码&#xff1a; 源代码说明&#xff1a; 这段代码中&#xff0c;首先定义了输入视频文件名、字体文件路径和输出图像文件名格式。然后使用subprocess模块的call函数调用FFmpeg命令。FFmpeg命令被定义为一个列表&#xff0c;其中每个元素都是命令中…

RocketMQ5.0.0消息消费<二> _ 消息队列负载均衡机制

目录 一、消费队列负载均衡概览 二、消费队列负载均衡实现 1. 负载均衡UML 2. 启动RebalanceService线程 3. PUSH模式负载均衡 三、负载均衡策略 四、参考资料 一、消费队列负载均衡概览 RocketMQ默认一个主题下有4个消费队列&#xff0c;集群模式下同一消费组内要求每个…

合并链表相关的练习

目录 一、合并两个有序链表 二、两数相加 一、合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4] 示例 2&…

熬夜30天吃透这九大Java核心专题,我收割了3个大厂offer

这次一共收割了3个大厂offer&#xff0c;分别是蚂蚁金服、美团和网易&#xff0c;特意分享这次对我帮助非常大的宝典资料&#xff0c;一共涉及九大核心专题&#xff0c;分别是计算机网络、操作系统、MySQL、Linux、JAVA、JVM、Redis、消息队列与分布式、网站优化相关&#xff0…

MySQL8启动错误“Neither found #innodb_redo subdirectory, nor ib_logfile* files”

今天做MySQL备份文件回复测试,用来检验MySQL备份文件可用性。 MySQL版本8.0.32 备份文件为腾讯云MySQL实例,版本8.0 使用xtrabackup恢复备份。执行过程顺利,启动MySQL时发生错误。提示如下: 注意,这里使用了systemctl stop mysql。虽然启动失败了,但是如果不执行这条…

全国青少年软件编程(Scratch)等级考试一级真题——2019.9

青少年软件编程&#xff08;Scratch&#xff09;等级考试试卷&#xff08;一级&#xff09;分数&#xff1a;100 题数&#xff1a;37一、单选题(共25题&#xff0c;每题2分&#xff0c;共50分)1.小明在做一个采访的小动画&#xff0c;想让主持人角色说“大家好&#xff01;”3秒…

AcWing 3555. 二叉树

第一种做法是dfs。但是注意&#xff0c;如果是非常单纯的dfs&#xff0c;要把每个节点可以到达的所有节点都记录下来&#xff08;父节点两个子节点&#xff09;。如果只记录了子节点&#xff0c;没记录父节点&#xff0c;就失去了一个方向&#xff0c;肯定出错。 例如求2和6之…