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

OpenWrt kernel install分析(2)

一. 前言

        接下来分析make -C image compile install TARGET_BUILD=。

二. Makefile分析

1. 命令首先运行target/linux/mediatek/image/Makefile,该文件内容如下:

target/linux/mediatek/image/Makefile:
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/image.mk......# build signed fit
define Build/fit-sign$(TOPDIR)/scripts/mkits.sh \-D $(DEVICE_NAME) \-o $@.its \-k $@ \$(if $(word 2,$(1)),-d $(word 2,$(1))) -C $(word 1,$(1)) \-a $(KERNEL_LOADADDR) \-e $(if $(KERNEL_ENTRY),$(KERNEL_ENTRY),$(KERNEL_LOADADDR)) \-c $(if $(DEVICE_DTS_CONFIG),$(DEVICE_DTS_CONFIG),"config-1") \-A $(LINUX_KARCH) \-v $(LINUX_VERSION) \-s $(KDIR)/$(DEVICE_NAME)-u-boot-script \$(if $(FIT_KEY_NAME),-S $(FIT_KEY_NAME)) \$(if $(FW_AR_VER),-r $(FW_AR_VER))PATH=$(LINUX_DIR)/scripts/dtc:$(PATH) mkimage \-f $@.its \$(if $(FIT_KEY_DIR),-k $(FIT_KEY_DIR)) \-r \$@.new@mv $@.new $@
endef# default all platform image(fit) build 
define Device/DefaultPROFILES = Default $$(DEVICE_NAME)KERNEL_NAME := ImageKERNEL = kernel-bin | lzma | \fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtbKERNEL_INITRAMFS = kernel-bin | lzma | \fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtbFILESYSTEMS := squashfsDEVICE_DTS_DIR := $(DTS_DIR)IMAGES := sysupgrade.binIMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | \pad-rootfs | append-metadataFIT_KEY_DIR :=FIT_KEY_NAME :=
endefinclude $(SUBTARGET).mkdefine Image/Build$(call Image/Build/$(1),$(1))
endef$(eval $(call BuildImage))

        BuildImage在include/image.mk中定义,install目标在里面,代码如下:

include/image.mk:
define BuildImage......download:prepare:compile:clean:image_prepare:ifeq ($(IB),).PHONY: download prepare compile clean image_prepare kernel_prepare install install-imagescompile:$(call Build/Compile)clean:$(call Build/Clean)image_prepare: compilemkdir -p $(BIN_DIR) $(KDIR)/tmprm -rf $(BUILD_DIR)/json_info_files$(call Image/Prepare)elseimage_prepare:mkdir -p $(BIN_DIR) $(KDIR)/tmpendifkernel_prepare: image_prepare$(call Image/Build/targz)$(call Image/Build/cpiogz)$(call Image/BuildKernel)$(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(if $(IB),,$(call Image/BuildKernel/Initramfs)))$(call Image/InstallKernel)$(foreach device,$(TARGET_DEVICES),$(call Device,$(device)))install-images: kernel_prepare $(foreach fs,$(filter-out $(if $(UBIFS_OPTS),,ubifs),$(TARGET_FILESYSTEMS) $(fs-subtypes-y)),$(KDIR)/root.$(fs))$(foreach fs,$(TARGET_FILESYSTEMS),$(call Image/Build,$(fs)))install: install-images$(call Image/Manifest)endef

        由上可知,install依赖于install-images,install-images依赖于kernel_prepare,kernel_prepare依赖于image_prepare,由于IB未定义,所以image_prepare定义如下:

compile:$(call Build/Compile)clean:$(call Build/Clean)image_prepare: compilemkdir -p $(BIN_DIR) $(KDIR)/tmprm -rf $(BUILD_DIR)/json_info_files$(call Image/Prepare)

image_prepare依赖于compile,这里,Build/Compile并未定义,所以什么都不干

注意:image_prepare在另一处也有定义,如下:

ifndef IB
define Device/Build/dtbifndef BUILD_DTS_$(1)BUILD_DTS_$(1) := 1$(KDIR)/image-$(1).dtb: FORCE$(call Image/BuildDTB,$(strip $(2))/$(strip $(3)).dts,$$@)image_prepare: $(KDIR)/image-$(1).dtbendifendef
endif

        这里在执行完上面compile依赖,接下来会完成$(KDIR)/image-$(1).dtb这个依赖,也就是生成设备树文件。

这种有两个相同目标的执行过程,下面用一个简单案例解释,如下:

act1:@echo "act1"act2:@echo "act2"target:act1target:act2@echo "target finish"all: target@echo "all finish"

     这里有两个target目标,分别依赖act1和act2,注意,一个target是有执行动作的,一个没有,这里先执行act2依赖,再act1依赖,执行结果如下:

act2
act1
target finish
all finish

 回到分析,

ifndef IB
define Device/Build/dtbifndef BUILD_DTS_$(1)BUILD_DTS_$(1) := 1$(KDIR)/image-$(1).dtb: FORCE$(call Image/BuildDTB,$(strip $(2))/$(strip $(3)).dts,$$@)image_prepare: $(KDIR)/image-$(1).dtbendifendef
endif

$(KDIR)/image-$(1).dtb也是一个目标,动作为$(call Image/BuildDTB,$(strip $(2))/$(strip $(3)).dts,$$@),Image/BuildDTB定义如下,

define Image/BuildDTB$(TARGET_CROSS)cpp -nostdinc -x assembler-with-cpp \-I$(DTS_DIR) \-I$(DTS_DIR)/include \-I$(LINUX_DIR)/include/ \-undef -D__DTS__ $(3) \-o $(2).tmp $(1)$(LINUX_DIR)/scripts/dtc/dtc -O dtb \-i$(dir $(1)) $(DTC_FLAGS) $(4) \-o $(2) $(2).tmp$(RM) $(2).tmp
endef

完整命令展开如下:

aarch64-openwrt-linux-musl-cpp -nostdinc -x assembler-with-cpp -I/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/arch/arm64/boot/dts -I/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/arch/arm64/boot/dts/include -I/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/include/ -undef -D__DTS__  -o /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/image-mt7981-spim-nor-rfb.dtb.tmp /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
aarch64-openwrt-linux-musl-cpp -nostdinc -x assembler-with-cpp -I/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/arch/arm64/boot/dts -I/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/arch/arm64/boot/dts/include -I/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/include/ -undef -D__DTS__ -o /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/image-mt7981-spim-nor-rfb.dtb.tmp /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/arch/arm64/boot/dts/mediatek/mt7981-spim-nor-rfb.dts
/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/scripts/dtc/dtc -O dtb -i/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/arch/arm64/boot/dts/mediatek/ -Wno-unit_address_vs_reg -Wno-simple_bus_reg -Wno-unit_address_format -Wno-pci_bridge -Wno-pci_device_bus_num -Wno-pci_device_reg -Wno-avoid_unnecessary_addr_size -Wno-alias_paths -Wno-graph_child_address -Wno-graph_port -Wno-unique_unit_address  -o /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/image-mt7981-spim-nor-rfb.dtb /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/image-mt7981-spim-nor-rfb.dtb.tmp

注意:

        Device/Build/dtb是由下面代码展开得到的:

$(foreach device,$(TARGET_DEVICES),$(call Device,$(device)))

TARGET_DEVICES定义在target/linux/mediatek/image/mt7981.mk 中,可以如下:

openwrt# grep -rn "TARGET_DEVICES" target/linux/mediatek/image/mt7981.mk 
10:TARGET_DEVICES += mt7981-spim-nor-rfb
27:TARGET_DEVICES += mt7981-spim-nand-2500wan-gmac2
44:TARGET_DEVICES += mt7981-spim-nand-rfb
61:TARGET_DEVICES += mt7981-spim-nand-gsw
74:TARGET_DEVICES += mt7981-emmc-rfb
87:TARGET_DEVICES += mt7981-sd-rfb
104:TARGET_DEVICES += mt7981-snfi-nand-2500wan-p5
113:TARGET_DEVICES += mt7981-fpga-spim-nor
130:TARGET_DEVICES += mt7981-fpga-snfi-nand
147:TARGET_DEVICES += mt7981-fpga-spim-nand
160:TARGET_DEVICES += mt7981-fpga-emmc
173:TARGET_DEVICES += mt7981-fpga-sd

Device的定义如下:

define Device$(call Device/InitProfile,$(1))$(call Device/Init,$(1))$(call Device/Default,$(1))$(call Device/$(1),$(1))$(call Device/Check,$(1))$(call Device/$(if $(DUMP),Dump,Build),$(1))endef

        Device/Default定义在target/linux/mediatek/image/Makefile,内容如下:

define Device/DefaultPROFILES = Default $$(DEVICE_NAME)KERNEL_NAME := ImageKERNEL = kernel-bin | lzma | \fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtbKERNEL_INITRAMFS = kernel-bin | lzma | \fit lzma $$(KDIR)/image-$$(firstword $$(DEVICE_DTS)).dtbFILESYSTEMS := squashfsDEVICE_DTS_DIR := $(DTS_DIR)IMAGES := sysupgrade.binIMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | \pad-rootfs | append-metadataFIT_KEY_DIR :=FIT_KEY_NAME :=
endef

        Device/$(1):由于$(1)=mt7981-spim-nor-rfb,表示Device/mt7981-spim-nor-rfb,定义在target/linux/mediatek/image/mt7981.mk,内容如下:

define Device/mt7981-spim-nor-rfbDEVICE_VENDOR := MediaTekDEVICE_MODEL := mt7981-spim-nor-rfbDEVICE_DTS := mt7981-spim-nor-rfbDEVICE_DTS_DIR := $(DTS_DIR)/mediatekSUPPORTED_DEVICES := mediatek,mt7981-spim-nor-rfb
endef
TARGET_DEVICES += mt7981-spim-nor-rfb

        由于DUMP未定义,$(call Device/$(if $(DUMP),Dump,Build),$(1))为Device/Build。

2. Device/Build展开如下

define Device/Build$$(eval $$(foreach image,$$(IMAGES), \$$(foreach fs,$$(filter $(TARGET_FILESYSTEMS),$$(FILESYSTEMS)), \$$(call Device/Build/per-device-fs,$$(fs),$$(image),$(1)))))$(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(call Device/Build/initramfs,$(1)))$(call Device/Build/kernel,$(1),$$(filter $(TARGET_FILESYSTEMS),$$(FILESYSTEMS)))$$(eval $$(foreach compile,$$(COMPILE), \$$(call Device/Build/compile,$$(compile),$(1))))$$(eval $$(foreach image,$$(IMAGES), \$$(foreach fs,$$(filter $(TARGET_FILESYSTEMS),$$(FILESYSTEMS)), \$$(call Device/Build/image,$$(fs),$$(image),$(1)))))$$(eval $$(foreach artifact,$$(ARTIFACTS), \$$(call Device/Build/artifact,$$(artifact))))endef

         注意:这里Device/Build/initramfs是关键,内存根文件系统只会执行到这个,Device/Build/initramfs,内容如下:

define split_args
$(foreach data, \$(subst |,$(space),\$(subst $(space),^,$(1))), \$(call $(2),$(strip $(subst ^,$(space),$(data)))))
endefdefine build_cmd
$(if $(Build/$(word 1,$(1))),,$(error Missing Build/$(word 1,$(1))))
$(call Build/$(word 1,$(1)),$(wordlist 2,$(words $(1)),$(1)))endefdefine concat_cmd
$(call split_args,$(1),build_cmd)
endefifndef IB
define Device/Build/initramfs$(call Device/Export,$(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE),$(1))$$(_TARGET): $$(if $$(KERNEL_INITRAMFS),$(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE) \$$(if $$(CONFIG_JSON_OVERVIEW_IMAGE_INFO), $(BUILD_DIR)/json_info_files/$$(KERNEL_INITRAMFS_IMAGE).json,))$(KDIR)/$$(KERNEL_INITRAMFS_NAME):: image_prepare$(BIN_DIR)/$$(KERNEL_INITRAMFS_IMAGE): $(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE)cp $$^ $$@$(KDIR)/tmp/$$(KERNEL_INITRAMFS_IMAGE): $(KDIR)/$$(KERNEL_INITRAMFS_NAME) $(CURDIR)/Makefile $$(KERNEL_DEPENDS) image_prepare@rm -f $$@$$(call concat_cmd,$$(KERNEL_INITRAMFS))......
endef
endif

         注意:这里concat_cmd非常重要,lzma压缩,mkits.sh制作its文件以及mkimage打包最终镜像都是这里完成。展开结果命令如下:

        rm -f /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bincp /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/Image-initramfs /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin/home/work/openwrt/staging_dir/host/bin/lzma e /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin -lc1 -lp2 -pb2  /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin.new@mv /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin.new /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin/home/work/openwrt/scripts/mkits.sh -D mt7981-spim-nor-rfb -o /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin.its -k /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin -d /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/image-mt7981-spim-nor-rfb.dtb -C lzma -a 0x48080000 -e 0x48080000  -c "config-1" -A arm64 -v 5.4.203 PATH=/home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/linux-5.4.203/scripts/dtc:/home/work/openwrt/staging_dir/toolchain-aarch64_cortex-a53_gcc-8.4.0_musl/bin:/home/work/openwrt/staging_dir/toolchain-aarch64_cortex-a53_gcc-8.4.0_musl/bin:/home/work/openwrt/staging_dir/toolchain-aarch64_cortex-a53_gcc-8.4.0_musl/bin:/home/work/openwrt/staging_dir/host/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/work/openwrt/staging_dir/toolchain-aarch64_cortex-a53_gcc-8.4.0_musl/bin/ mkimage -f /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin.its /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin.new@mv /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin.new /home/work/openwrt/build_dir/target-aarch64_cortex-a53_musl/linux-mediatek_mt7981/tmp/openwrt-mediatek-mt7981-mt7981-spim-nor-rfb-initramfs-kernel.bin

        $$(eval $$(foreach compile,$$(COMPILE), $$(call Device/Build/compile,$$(compile),$(1))))展开如下:

Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-spim-nor-rfb)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-spim-nand-2500wan-gmac2)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-spim-nand-rfb)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-spim-nand-gsw)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-emmc-rfb)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-sd-rfb)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-snfi-nand-2500wan-p5)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-fpga-spim-nor)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-fpga-snfi-nand)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-fpga-spim-nand)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-fpga-emmc)))
Makefile:91: $(eval $(foreach compile,$(COMPILE), $(call Device/Build/compile,$(compile),mt7981-fpga-sd)))

        由于$(COMPILE)为空,所以这块执行没有效果。

接下来,

$$(eval $$(foreach image,$$(IMAGES), \$$(foreach fs,$$(filter $(TARGET_FILESYSTEMS),$$(FILESYSTEMS)), \$$(call Device/Build/image,$$(fs),$$(image),$(1)))))

        由于TARGET_FILESYSTEMS是要编译的镜像格式类型,如下:

fs-types-$(CONFIG_TARGET_ROOTFS_SQUASHFS) += squashfs
fs-types-$(CONFIG_TARGET_ROOTFS_JFFS2) += $(addprefix jffs2-,$(JFFS2_BLOCKSIZE))
fs-types-$(CONFIG_TARGET_ROOTFS_JFFS2_NAND) += $(addprefix jffs2-nand-,$(NAND_BLOCKSIZE))
fs-types-$(CONFIG_TARGET_ROOTFS_EXT4FS) += ext4
fs-types-$(CONFIG_TARGET_ROOTFS_UBIFS) += ubifs
fs-subtypes-$(CONFIG_TARGET_ROOTFS_JFFS2) += $(addsuffix -raw,$(addprefix jffs2-,$(JFFS2_BLOCKSIZE)))TARGET_FILESYSTEMS := $(fs-types-y)

        由于CONFIG_TARGET_ROOTFS_SQUASHFS等我都没选,所以,TARGET_FILESYSTEMS为空,这里也是不执行的。可以看出Device/Build/image的作用是生成不同文件系统的镜像。

接下来,

$$(eval $$(foreach artifact,$$(ARTIFACTS), \$$(call Device/Build/artifact,$$(artifact))))

        由于ARTIFACTS变量为空,所以,这里Device/Build/artifact什么也不干。

三. 总结

这里需要注意的以下几点:

1. image_prepare有两个目标,有动作的这个目标做的事情很少,没有目标的依赖是用于编译设备树的,要非常注意。

2. 由于编译选项没选,Image/Build/targz,Image/Build/cpiogz这里什么也不做,Image/BuildKernelImage/InstallKernel没有定义(可能是用于自定义的,这里没用到而已),这里什么也不做。

3. $(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(if $(IB),,$(call Image/BuildKernel/Initramfs))),这里结果为$(call Image/BuildKernel/Initramfs),继续展开为$(call Image/Build/Initramfs),但是Image/Build/Initramfs未定义,所以这里什么也不干,也是用于自定义的。

4. $(foreach device,$(TARGET_DEVICES),$(call Device,$(device))),这里TARGET_DEVICES定义在mt7981.mk中,表示不同的镜像(spi-nor,spi-nand,emmc等等),Device宏里面要关注Device/Default和Device/Build,Device/Default定义在target/linux/mediatek/image/Makefile中,定义了一些镜像相关的变量,Device/Build中要关注$(if $(CONFIG_TARGET_ROOTFS_INITRAMFS),$(call Device/Build/initramfs,$(1))),结果是$(call Device/Build/initramfs,$(1)),重点要关注$$(call concat_cmd,$$(KERNEL_INITRAMFS))这里,这里面打包了最终的镜像(lzma压缩,its文件生成,mkimage都在这里执行)。

相关文章:

OpenWrt kernel install分析(2)

一. 前言 接下来分析make -C image compile install TARGET_BUILD。 二. Makefile分析 1. 命令首先运行target/linux/mediatek/image/Makefile,该文件内容如下: target/linux/mediatek/image/Makefile: include $(TOPDIR)/rules.mk include $(INCLUDE_DIR)/image.…...

【计算机网络】传输层协议——TCP(下)

文章目录 1. 三次握手三次握手的本质是建立链接,什么是链接?整体过程三次握手过程中报文丢失问题为什么2次握手不可以?为什么要三次握手? 2. 四次挥手整体过程为什么要等待2MSL 3. 流量控制4. 滑动窗口共识滑动窗口的一般情况理解…...

Vue前端页面打印

前端依赖10-插件"print-js": “^1.6.0” 一:简介 print-js 是一个 Vue.js 插件,用于在 Vue.js 项目中实现打印功能。它依赖于 print-js 库,所以需要安装这个库。 能实现以下功能: PDF打印(默认&#xff…...

Visual Studio将C#项目编译成EXE可执行程序

经常看文章时会收获不少实用工具,有的在github上是编译好的,有的则是未编译的项目文件。所以经常会使用Visual Studio编译项目文件成exe可执行程序,以下为编译的流程。 第一步,从github上下载项目文件,举个例子&#…...

git把某一次commit修改过的文件打包导出(git)

1、使用命令把修改的文件打包导出:打包某次commit: git diff-tree -r --no-commit-id --name-only f4710c4a32975904b00609f3145c709f31392140 | xargs tar -rf xxx_1.1.tar 2、使用命令把某次节点后的文件导出: window 下: git diff f4710c4a32975904b00609f3145c709f31392…...

Vue3 Ajax(axios)异步

文章目录 Vue3 Ajax(axios)异步1. 基础1.1 安装Ajax1.2 使用方法1.3 浏览器支持情况 2. GET方法2.1 参数传递2.2 实例 3. POST方法4. 执行多个并发请求5. axios API5.1 传递配置创建请求5.2 请求方法的别名5.3 并发5.4 创建实例5.5 实例方法5.6 请求配置项5.7 响应结构5.8 配置…...

idea2023全量方法debug

为什么要全量debug 刚上手项目或者研读开源项目源码的时候,我们对项目的结构,尤其是功能链路非常陌生,想要debug根本不知道断点打在哪,光靠文件名类名或者方法名去猜也不是个事。这时候只要配置一下全量debug模式,就能…...

Docker镜像解析获取Dockerfile文件

01、概述 当涉及到容器镜像的安全时,特别是在出现镜像投毒引发的安全事件时,追溯镜像的来源和解析Dockerfile文件是应急事件处理的关键步骤。在这篇博客中,我们将探讨如何从镜像解析获取Dockerfile文件,这对容器安全至关重要。 02…...

使用maven命令打jar包

参考:https://blog.csdn.net/qq_27525611/article/details/123487255 https://blog.csdn.net/qq_35860138/article/details/82701919 小伙伴给我的项目自己尝试命令行打包遇到的坑,简单记录下 // 打包(1.8环境下打的,17会报错&…...

【多线程】死锁 详解

死锁 一. 死锁是什么二. 死锁的场景1. 一个线程一把锁2. 两个线程两把锁3. N 个线程 M 把锁 三. 死锁产生的四个必要条件四. 如何避免死锁 一. 死锁是什么 死锁是这样一种情形: 多个线程同时被阻塞,因为每个进程都在等其他线程释放某些资源,…...

成考[专升本政治]科目必背知识点

1. 马克思主义哲学研究的对象是:关于自然、社会、思维发展的一般规律。 2. 对待马克思主义的科学态度是:坚持和发展。 3. 物质的唯一特性是客观实在性。这里的客观实在是指:不以人的意志为转移。 4. 在实际工作中,要注意掌握…...

spring boot 使用AOP+自定义注解+反射实现操作日志记录修改前数据和修改后对比数据,并保存至日志表

一、添加aop starter依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>二&#xff1a;自定义字段翻译注解。&#xff08;修改功能时&#xff0c;需要显示如…...

【深度学习】Pytorch 系列教程(二):PyTorch数据结构:1、Tensor(张量): GPU加速(GPU Acceleration)

目录 一、前言 二、实验环境 三、PyTorch数据结构 0、分类 1、张量&#xff08;Tensor&#xff09; 1. 维度&#xff08;Dimensions&#xff09; 2. 数据类型&#xff08;Data Types&#xff09; 3. GPU加速&#xff08;GPU Acceleration&#xff09; 一、前言 ChatGP…...

多线程|多进程|高并发网络编程

一.多进程并发服务器 多进程并发服务器是一种经典的服务器架构&#xff0c;它通过创建多个子进程来处理客户端连接&#xff0c;从而实现并发处理多个客户端请求的能力。 概念&#xff1a; 服务器启动时&#xff0c;创建主进程&#xff0c;并绑定监听端口。当有客户端连接请求…...

云计算——ACA学习 云计算分类

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 目录 写在前面 前期回顾 本期介绍 一.云计算分类 1.公有云…...

3 分钟,带你了解低代码开发

一、低代码平台存在的意义 传统软件开发交付链中&#xff0c;需求经过3次传递&#xff0c;用户→业务→架构师→开发&#xff0c;每一层传递都可能使需求失真&#xff0c;导致最终交付的功能返工。 业务的变化促使软件开发过程不断更新、迭代和演进&#xff0c;而低代码开发即是…...

小白学Unity03-太空漫游游戏脚本,控制飞船移动旋转

首先搭建好太阳系以及飞机的场景 需要用到3个脚本 1.控制飞机移动旋转 2.控制摄像机LookAt朝向飞机和差值平滑跟踪飞机 3.控制各个星球自转以及围绕太阳旋转&#xff08;rotate()和RotateAround()&#xff09; 1.控制飞机移动旋转的脚本 using System.Collections; using…...

接口自动化测试推荐用什么框架?

在推荐接口自动化测试框架时&#xff0c;需要考虑多个因素&#xff0c;包括项目需求、技术栈、团队经验和个人偏好。 以下是几个常用的接口自动化测试框架供你参考&#xff1a; Postman&#xff1a; Postman是一个功能强大且易于上手的接口测试工具&#xff0c;它提供了许多…...

防火墙 FireWall

这里写自定义目录标题 一、概述二、防火墙分类三、防火墙性能四、硬件防火墙定义五、硬件防火墙作用&#xff08;拓扑图 ups&#xff09;六、硬件防火墙品牌七、软件防火墙八、iptables一、iptables是什么&#xff1f;二、netfilter/iptables功能三、iptables概念四、iptables中…...

【Linix-Day12-线程同步和线程安全】

线程同步 和 线程安全 线程同步 除了信号量和互斥锁&#xff08;互斥锁和条件变量上次介绍过&#xff09;&#xff0c;还有两种方式同步 1.读写锁 当同时对一块内存读写时&#xff0c;会出现下列问题&#xff0c;故而引入读写锁 接口介绍&#xff1a; 1.int pthread_rwloc…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

ffmpeg(四):滤镜命令

FFmpeg 的滤镜命令是用于音视频处理中的强大工具&#xff0c;可以完成剪裁、缩放、加水印、调色、合成、旋转、模糊、叠加字幕等复杂的操作。其核心语法格式一般如下&#xff1a; ffmpeg -i input.mp4 -vf "滤镜参数" output.mp4或者带音频滤镜&#xff1a; ffmpeg…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验

系列回顾&#xff1a; 在上一篇中&#xff0c;我们成功地为应用集成了数据库&#xff0c;并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了&#xff01;但是&#xff0c;如果你仔细审视那些 API&#xff0c;会发现它们还很“粗糙”&#xff1a;有…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

CVPR2025重磅突破:AnomalyAny框架实现单样本生成逼真异常数据,破解视觉检测瓶颈!

本文介绍了一种名为AnomalyAny的创新框架&#xff0c;该方法利用Stable Diffusion的强大生成能力&#xff0c;仅需单个正常样本和文本描述&#xff0c;即可生成逼真且多样化的异常样本&#xff0c;有效解决了视觉异常检测中异常样本稀缺的难题&#xff0c;为工业质检、医疗影像…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...