【NUJ PA2】Read a Makefile

这里是NJU的PA2.2里面要求读懂的Makefile,是abstract-machine的。这里会放一些与读懂这个Makefile有关的知识。
下面是用ChatGPT解释的代码。只做大致的了解,写Makefile的时候还是要具体去看官方手册。
官方手册:make.pdf
(gnu.org)

# Makefile for AbstractMachine Kernels and Libraries### *Get a more readable version of this Makefile* by `make html` (requires python-markdown)
html:cat Makefile | sed 's/^\([^#]\)/    \1/g' | markdown_py > Makefile.html
.PHONY: html## 1. Basic Setup and Checks## 创建一个裸机内核镜像### Default to create a bare-metal kernel imageifeq ($(MAKECMDGOALS),)MAKECMDGOALS  = image.DEFAULT_GOAL = imageendif### Override checks when `make clean/clean-all/html`ifeq ($(findstring $(MAKECMDGOALS),clean|clean-all|html),)### Print build info message$(info # Building $(NAME)-$(MAKECMDGOALS) [$(ARCH)])### Check: environment variable `$AM_HOME` looks saneifeq ($(wildcard $(AM_HOME)/am/include/am.h),)$(error $$AM_HOME must be an AbstractMachine repo)endif### Check: environment variable `$ARCH` must be in the supported listARCHS = $(basename $(notdir $(shell ls $(AM_HOME)/scripts/*.mk)))ifeq ($(filter $(ARCHS), $(ARCH)), )$(error Expected $$ARCH in {$(ARCHS)}, Got "$(ARCH)")endif### Extract instruction set architecture (`ISA`) and platform from `$ARCH`. Example: `ARCH=x86_64-qemu -> ISA=x86_64; PLATFORM=qemu`ARCH_SPLIT = $(subst -, ,$(ARCH))ISA        = $(word 1,$(ARCH_SPLIT))PLATFORM   = $(word 2,$(ARCH_SPLIT))### Check if there is something to buildifeq ($(flavor SRCS), undefined)$(error Nothing to build)endif### Checks end hereendif## 2. General Compilation Targets### Create the destination directory (`build/$ARCH`)WORK_DIR  = $(shell pwd)DST_DIR   = $(WORK_DIR)/build/$(ARCH)$(shell mkdir -p $(DST_DIR))### Compilation targets (a binary image or archive)IMAGE_REL = build/$(NAME)-$(ARCH)IMAGE     = $(abspath $(IMAGE_REL))ARCHIVE   = $(WORK_DIR)/build/$(NAME)-$(ARCH).a### Collect the files to be linked: object files (`.o`) and libraries (`.a`)OBJS      = $(addprefix $(DST_DIR)/, $(addsuffix .o, $(basename $(SRCS))))LIBS     := $(sort $(LIBS) am klib) # lazy evaluation ("=") causes infinite recursionsLINKAGE   = $(OBJS) \$(addsuffix -$(ARCH).a, $(join \$(addsuffix /build/, $(addprefix $(AM_HOME)/, $(LIBS))), \$(LIBS) ))## 3. General Compilation Flags### (Cross) compilers, e.g., mips-linux-gnu-g++AS        = $(CROSS_COMPILE)gccCC        = $(CROSS_COMPILE)gccCXX       = $(CROSS_COMPILE)g++LD        = $(CROSS_COMPILE)ldAR        = $(CROSS_COMPILE)arOBJDUMP   = $(CROSS_COMPILE)objdumpOBJCOPY   = $(CROSS_COMPILE)objcopyREADELF   = $(CROSS_COMPILE)readelf### Compilation flagsINC_PATH += $(WORK_DIR)/include $(addsuffix /include/, $(addprefix $(AM_HOME)/, $(LIBS)))INCFLAGS += $(addprefix -I, $(INC_PATH))ARCH_H := arch/$(ARCH).hCFLAGS   += -O2 -MMD -Wall -Werror $(INCFLAGS) \-D__ISA__=\"$(ISA)\" -D__ISA_$(shell echo $(ISA) | tr a-z A-Z)__ \-D__ARCH__=$(ARCH) -D__ARCH_$(shell echo $(ARCH) | tr a-z A-Z | tr - _) \-D__PLATFORM__=$(PLATFORM) -D__PLATFORM_$(shell echo $(PLATFORM) | tr a-z A-Z | tr - _) \-DARCH_H=\"$(ARCH_H)\" \-fno-asynchronous-unwind-tables -fno-builtin -fno-stack-protector \-Wno-main -U_FORTIFY_SOURCECXXFLAGS +=  $(CFLAGS) -ffreestanding -fno-rtti -fno-exceptionsASFLAGS  += -MMD $(INCFLAGS)LDFLAGS  += -z noexecstack## 4. Arch-Specific Configurations### Paste in arch-specific configurations (e.g., from `scripts/x86_64-qemu.mk`)-include $(AM_HOME)/scripts/$(ARCH).mk### Fall back to native gcc/binutils if there is no cross compilerifeq ($(wildcard $(shell which $(CC))),)$(info #  $(CC) not found; fall back to default gcc and binutils)CROSS_COMPILE :=endif## 5. Compilation Rules### Rule (compile): a single `.c` -> `.o` (gcc)$(DST_DIR)/%.o: %.c@mkdir -p $(dir $@) && echo + CC $<@$(CC) -std=gnu11 $(CFLAGS) -c -o $@ $(realpath $<)### Rule (compile): a single `.cc` -> `.o` (g++)$(DST_DIR)/%.o: %.cc@mkdir -p $(dir $@) && echo + CXX $<@$(CXX) -std=c++17 $(CXXFLAGS) -c -o $@ $(realpath $<)### Rule (compile): a single `.cpp` -> `.o` (g++)$(DST_DIR)/%.o: %.cpp@mkdir -p $(dir $@) && echo + CXX $<@$(CXX) -std=c++17 $(CXXFLAGS) -c -o $@ $(realpath $<)### Rule (compile): a single `.S` -> `.o` (gcc, which preprocesses and calls as)$(DST_DIR)/%.o: %.S@mkdir -p $(dir $@) && echo + AS $<@$(AS) $(ASFLAGS) -c -o $@ $(realpath $<)### Rule (recursive make): build a dependent library (am, klib, ...)$(LIBS): %:@$(MAKE) -s -C $(AM_HOME)/$* archive### Rule (link): objects (`*.o`) and libraries (`*.a`) -> `IMAGE.elf`, the final ELF binary to be packed into image (ld)$(IMAGE).elf: $(OBJS) am $(LIBS)@echo + LD "->" $(IMAGE_REL).elf@$(LD) $(LDFLAGS) -o $(IMAGE).elf --start-group $(LINKAGE) --end-group### Rule (archive): objects (`*.o`) -> `ARCHIVE.a` (ar)$(ARCHIVE): $(OBJS)@echo + AR "->" $(shell realpath $@ --relative-to .)@$(AR) rcs $(ARCHIVE) $(OBJS)### Rule (`#include` dependencies): paste in `.d` files generated by gcc on `-MMD`-include $(addprefix $(DST_DIR)/, $(addsuffix .d, $(basename $(SRCS))))## 6. Miscellaneous### Build order controlimage: image-deparchive: $(ARCHIVE)image-dep: $(OBJS) am $(LIBS)@echo \# Creating image [$(ARCH)].PHONY: image image-dep archive run $(LIBS)### Clean a single project (remove `build/`)clean:rm -rf Makefile.html $(WORK_DIR)/build/.PHONY: clean### Clean all sub-projects within depth 2 (and ignore errors)CLEAN_ALL = $(dir $(shell find . -mindepth 2 -name Makefile))clean-all: $(CLEAN_ALL) clean$(CLEAN_ALL):-@$(MAKE) -s -C $@ clean.PHONY: clean-all $(CLEAN_ALL)

1. Basic Setup and Checks

Default to create a bare-metal kernel image

MAKECMDGOALS

Make会将特殊变量MAKECMDGOALS设置为您在命令行上指定的目标列表。如果在命令行上没有指定目标,则此变量为空。请注意,这个变量只应在特殊情况下使用。
适当使用的一个例子是在清理规则中避免包含.d文件(参见第4.13节[自动先决条件],第42页),这样make就不会创建这些文件,只是立即删除它们。
换句话说,MAKECMDGOALS变量可以用于根据命令行上指定的目标来执行特定的操作或规则。在清理规则中,您可以检查MAKECMDGOALS变量,以决定是否需要清理.d文件。这样可以避免不必要的创建和删除.d文件的开销。
在这里插入图片描述

这段代码片段展示了一个示例的
Makefile 开头部分。 首先,定义了一个变量sources,其中包含了要编译的源文件列表,例如 foo.cbar.c。接下来,使用条件语句 ifeq 来检查 MAKECMDGOALS 变量中是否包含了clean 目标。MAKECMDGOALS 变量存储了在命令行上指定的目标列表。 如果MAKECMDGOALS 中不包含 clean 目标,那么会执行 include语句。这里使用了变量替换和模式替换,将 sources 中的 .c 后缀替换为.d 后缀,然后包含这些 .d 文件。.d文件通常是由编译器生成的依赖关系文件,用于跟踪源文件之间的依赖关系。通过这段代码,可以在编译程序之前自动包含并处理依赖关系文件,以确保在源文件或头文件发生更改时,相关的文件会被重新编译。这有助于提高构建的效率和准确性。

ifeq ($(MAKECMDGOALS),)MAKECMDGOALS  = image.DEFAULT_GOAL = image
endif

如果MAKECMDGOALS 变量为空,即没有在命令行上指定目标,则会执行里面的代码,将MAKECMDGOALS、.DEFAULT_GOAL都指向image这个镜像。
### Override checks when make clean/clean-all/html

ifeq ($(findstring $(MAKECMDGOALS),clean|clean-all|html),)

也是说我们输入make clean/make clean-all/makehtml,可以避免在执行清理或生成 HTML等特定操作时,执行不必要的检查(也就是下面的Check)或设置。

Printbuild info message

pass,没啥好说的。

Check: environment variable$AM_HOME looks sane

ifeq ($(wildcard $(AM_HOME)/am/include/am.h),)$(error $$AM_HOME must be an AbstractMachine repo)
endif

用于检查环境变量 $AM_HOME 是否指向 Abstract-Machine 仓库

Check:environment variable $ARCH must be in the supported list

检查是否是支持的ISA

Extract instruction set architecture (ISA)and platform from $ARCH. Example:

ARCH=x86_64-qemu -> ISA=x86_64; PLATFORM=qemu没啥好说的,也就是做了一点类似字符串的截取的工作。

Check if there

is something to build 检查是否需要build。

2. General Compilation Targets

Create the destination directory (build/$ARCH)

生成目标的文件路径,创建文件。 ### Compilation targets (a binary image
or archive)

IMAGE_REL = build/$(NAME)-$(ARCH)
IMAGE     = $(abspath $(IMAGE_REL))
ARCHIVE   = $(WORK_DIR)/build/$(NAME)-$(ARCH).a

这段代码片段定义了编译目标的变量。 首先,定义了一个变量IMAGE_REL,它表示编译生成的二进制镜像的相对路径。路径由build/$(NAME)(名称变量)和 $(ARCH)(架构变量)组成。接下来,定义了一个变量 IMAGE,它使用 abspath 函数将 IMAGE_REL的相对路径转换为绝对路径。这样可以确保在不同的工作目录中也能正确地引用生成的二进制镜像。最后,定义了一个变量 ARCHIVE,它表示编译生成的静态库的路径。路径由$(WORK_DIR)(工作目录变量)、build/$(NAME)$(ARCH) 组成。通过这些变量,可以方便地引用编译生成的二进制镜像和静态库的路径,以便后续的操作和使用。
生成了一个库文件。
在这里插入图片描述

Collect the files to be linked: object files (.o) and libraries (.a)

这段代码片段用于收集需要链接的文件,包括目标文件(.o)和库文件(.a)。首先,定义了一个变量 OBJS,它使用 addprefixaddsuffixbasename 函数来生成目标文件的路径。addprefix函数用于在每个文件名前添加目标目录的路径 $(DST_DIR)addsuffix函数用于在每个文件名后添加 .o 后缀,basename函数用于去除源文件的扩展名。通过这些函数的组合,可以生成目标文件的完整路径。接下来,使用 sort 函数对变量 LIBS 进行排序,并将 amklib添加到 LIBS 变量中。这里使用了 := 运算符,表示对 LIBS变量进行延迟求值,避免无限递归的问题。 最后,定义了一个变量LINKAGE,它包含了需要链接的文件列表。这个列表由目标文件 $(OBJS)和库文件组成。库文件的路径由 $(AM_HOME)$(LIBS)-$(ARCH).a组合而成。通过 join 函数和字符串操作,可以生成每个库文件的完整路径。通过这些变量,可以方便地收集需要链接的目标文件和库文件,并在链接过程中使用它们。

3. General Compilation Flags

(Cross) compilers, e.g.,mips-linux-gnu-g++

进行交叉编译。通过这些变量,可以方便地配置和切换不同的编译器和工具链,以适应特定的编译环境和目标平台。

Compilation flags

定义了一些编译标志(Compilation flags)。

4. Arch-Specific Configurations

Paste in arch-specific configurations(e.g., from scripts/x86_64-qemu.mk)

这段代码片段用于包含特定架构的配置文件。使用 -include 指令,将$(AM_HOME)/scripts/$(ARCH).mk 文件包含到当前的 Makefile
中。这个文件路径由 $(AM_HOME)(AbstractMachine 仓库路径)和$(ARCH)(架构变量)组成。通过包含特定架构的配置文件,可以在构建过程中应用特定的架构相关配置。这样可以根据不同的架构定制编译和链接的行为,以适应特定的目标平台和需求。这方式可以使Makefile 更加灵活和可配置,以适应不同的架构和配置需求。 ### Fall backto native gcc/binutils if there is no cross compiler这段代码片段用于在没有交叉编译器的情况下,回退到本地的 gcc 和 binutils。

5. Compilation Rules - 定义编译规则,将源文件编译为目标文件。 -

  • 定义编译规则,将源文件编译为目标文件。
  • 定义递归规则,构建依赖库(am、klib 等)的静态库。
  • 定义链接规则,将目标文件和库文件链接为最终的 ELF 二进制文件。
  • 定义归档规则,将目标文件打包为静态库。
  • 定义 .d 文件的包含规则,用于处理头文件的依赖关系。

6. Miscellaneous

这段代码片段控制了构建的顺序和清理操作。 首先,定义了目标image,它依赖于目标 image-dep。这表示在构建 image 之前,需要先构建image-dep。同样地,定义了目标 archive,它依赖于变量$(ARCHIVE),表示在构建 archive 之前,需要先生成 $(ARCHIVE)。在目标 image-dep 中,定义了依赖关系,它依赖于目标 $(OBJS)am$(LIBS)。这表示在构建 image-dep 之前,需要先生成目标文件$(OBJS)、构建 am 和构建 $(LIBS)。 在目标 clean中,定义了清理操作,它会删除 Makefile.html 文件和 $(WORK_DIR)/build/目录。 在目标 clean-all 中,定义了清理所有子项目的操作。通过使用find 命令找到所有深度为 2 的 Makefile文件,并提取出对应的目录。然后,通过递归调用 $(MAKE)命令在每个子项目中执行 clean 目标。通过这些目标和规则,可以控制构建的顺序,并提供清理操作以清除构建生成的文件。

END

  1. 里面对于make clean、make html、make
    clean-all进行了处理,使得它们不需要进行检查和下面的操作,节省了很多时间;
  2. 对于交叉编译做了处理,如果没有交叉编译的环境则回退到原环境;
  3. Arch-Specific Configurations的Paste in arch-specific configurations
    (e.g., from scripts/x86_64-qemu.mk)使用 -include 指令,将$(AM_HOME)/scripts/$(ARCH).mk 文件包含到当前的 Makefile
    中。也是就是包含了特定架构的配置文件,可以在构建过程中应用特定的架构相关配置。使得一个n*m的问题变成了n + m!
    在这里插入图片描述

Answered by ChatGPT:

这个 Makefile 是用于构建 AbstractMachine 内核和库的。下面对其中的内容进行解释:1. Basic Setup and Checks(基本设置和检查):- 检查默认目标,并设置 `MAKECMDGOALS` 和 `.DEFAULT_GOAL`。- 检查环境变量 `$AM_HOME` 是否指向 AbstractMachine 仓库。- 检查环境变量 `$ARCH` 是否在支持的架构列表中。- 提取 `$ARCH` 中的指令集架构 (`ISA`) 和平台信息。2. General Compilation Targets(通用编译目标):- 创建目标目录 `build/$ARCH`。- 定义编译目标:`IMAGE_REL`(二进制镜像路径)和 `ARCHIVE`(静态库路径)。- 收集需要链接的文件:目标文件(`.o`)和库文件(`.a`)。3. General Compilation Flags(通用编译标志):- 定义编译器和工具链的变量。- 定义编译标志,包括包含路径、宏定义和其他编译选项。4. Arch-Specific Configurations(特定架构的配置):- 根据 `$ARCH` 包含特定架构的配置文件(例如 `scripts/x86_64-qemu.mk`)。- 如果没有交叉编译器,则使用本地的 gcc 和 binutils。5. Compilation Rules(编译规则):- 定义编译规则,将源文件编译为目标文件。- 定义递归规则,构建依赖库(am、klib 等)的静态库。- 定义链接规则,将目标文件和库文件链接为最终的 ELF 二进制文件。- 定义归档规则,将目标文件打包为静态库。- 定义 `.d` 文件的包含规则,用于处理头文件的依赖关系。6. Miscellaneous(其他):- 定义构建顺序控制的目标。- 定义清理目标,用于清除构建生成的文件和目录。这个 Makefile 提供了一套通用的编译规则和目标,用于构建 AbstractMachine 内核和库。根据不同的架构和目标,可以通过修改和扩展这个 Makefile 来满足具体的构建需求。

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

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

相关文章

军用FPGA软件 Verilog语言的编码准测之复位

军用FPGA软件 Verilog语言的编码准测之复位 语言 &#xff1a;Verilg HDL EDA工具&#xff1a;ISE、Vivado、Quartus II 军用FPGA软件 Verilog语言的编码准测之复位一、引言二、基本编程规范之复位强制准则1----禁止将异步的置位/复位信号连接到非置位/复位端强制准则2----禁止…

Json-server 的使用教程

目录 前言一、简介二、安装与配置1. 安装 node-js2. npm 镜像设置3. 安装 json-server 三、使用1. 创建本地数据源2. 启动 Json Server3. 操作数据&#xff08;1&#xff09;查询数据&#xff08;2&#xff09;新增数据&#xff08;3&#xff09;修改数据&#xff08;4&#xf…

RTOS笔记--资源管理

资源管理 资源管理&#xff0c;其实就是前面介绍过的通知方式中的队列信号量互斥量等是如何访问临界资源的&#xff0c;如何做到完全互斥。 在之前举过一个例子&#xff1a;当我们使用全局变量来进行互斥操作时&#xff0c;有可能在改写全局变量时被切换使得不再互斥&#xff0…

【SpringBoot】深入分析 SpringApplication 源码:彻底理解 SpringBoot 启动流程

在黄昏的余晖里&#xff0c;梦境渐浓&#xff0c;如烟如雾。心随星辰&#xff0c;徜徉远方&#xff0c;岁月静好&#xff0c;愿如此刻般绵长。 文章目录 前言一、SpringBoot 应用二、SpringApplication2.1 SpringApplication 中的属性2.2 SpringApplication 的构造器2.3 Sprin…

185. 部门工资前三高的所有员工

185. 部门工资前三高的所有员工 题目链接&#xff1a;185. 部门工资前三高的所有员工 代码如下&#xff1a; # Write your MySQL query statement below select d.Name as Department,e1.Name as Employee,e1.Salary from Employee as e1 join Department as d on e1.Depart…

【Linux】基础IO——文件描述符,重定向,FILE

话接上篇&#xff1a; 1.文件描述符fd 磁盘文件 VS 内存文件&#xff1f; 当文件存储在磁盘当中时&#xff0c;我们将其称之为磁盘文件&#xff0c;而当磁盘文件被加载到内存当中后&#xff0c;我们将加载到内存当中的文件称之为内存文件。磁盘文件和内存文件之间的关系就像程…

JVM 三色标记算法

三色标记算法核心原理 三色标记算法是一种JVM的垃圾标记算法&#xff0c;CMS/G1垃圾回收器就是使用的这种算法&#xff0c;它可以让JVM在不发生或者尽可能短的发生STW&#xff08;Stop The World&#xff09;的情况下进行垃圾的标记和清除。 顾名思义&#xff0c;三色标记算法…

【名词解释】Unity中的3D物理系统:刚体

Unity中的3D物理系统是用于模拟现实世界中物体的运动和相互作用的一套工具和组件。刚体&#xff08;Rigidbody&#xff09;是Unity 3D物理系统中的一个核心组件&#xff0c;它允许游戏对象&#xff08;GameObject&#xff09;受到重力和外力的影响&#xff0c;并参与碰撞检测。…

实现JWT认证与授权的Spring Boot项目详解

我们将详细介绍如何使用JWT&#xff08;JSON Web Tokens&#xff09;结合Spring Boot框架实现用户认证和授权系统。此方案将包括用户注册、登录以及通过JWT令牌进行后续请求的身份验证过程。我们将从引入必要的依赖开始&#xff0c;然后逐步构建项目的各个部分&#xff0c;包括…

精品丨PowerBI迁移到SSAS

业务场景&#xff1a; 企业初期在进行 BI 可视化路线的时候&#xff0c;往往不会选择方案较为完整的SSAS&#xff0c;而是会选择轻量的 PowerBI 方案&#xff0c;究其根本还是软件成本的问题。 但是随着模型越来越臃肿&#xff0c;维护成本越来越高&#xff0c;有很多模型需要进…

【名词解释】Unity中的3D坐标系

Unity中的3D坐标系是一个基于右手定则的笛卡尔坐标系&#xff0c;它定义了Unity场景中所有3D对象的位置、旋转和缩放。以下是一些基本的名词解释和使用方法&#xff1a; 名词解释&#xff1a; X轴&#xff1a;水平方向&#xff0c;从屏幕左侧向右延伸。Y轴&#xff1a;垂直方…

SQL Auto Increment

SQL Auto Increment 在关系型数据库中&#xff0c;自动增量&#xff08;Auto Increment&#xff09;是一个常见且实用的特性。它允许数据库自动为表中插入的新行分配唯一的标识符&#xff0c;通常用于主键字段。本文将深入探讨SQL中的自动增量功能&#xff0c;包括其工作原理、…

Java面向对象-抽象类和抽象方法

Java面向对象-抽象类和抽象方法 1、代码案例展示2、抽象类和抽象方法的关系&#xff1a; 1、代码案例展示 1、在一个类中会有一类方法&#xff0c;无需重写&#xff0c;直接使用 2、在一个类中会有一类方法&#xff0c;会对这个方法进行重写 3、一个方法的方法体去掉&#xff…

【文心智能体分享】日记周报助手

引言 在繁忙的实习生活中&#xff0c;你是否曾为如何整理日常的工作日志、周报、月报而烦恼&#xff1f;现在&#xff0c;我们为你带来了一个全新的智能体——“日记周报助手”&#xff0c;它将成为你实习过程中的得力助手&#xff0c;帮你轻松整理实习日志&#xff0c;让你的…

mysql 中的锁

一.锁的介绍 锁是计算机协调多个进程或线程并发访问某一资源的机制&#xff0c;在数据库中&#xff0c;除了传统的计算资源&#xff08;cpu&#xff0c;ram&#xff0c;i/o&#xff09;的争用以外&#xff0c;数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性…

【C#】IndexOf的使用

1. 在ObservableCollection<T> 类中使用&#xff1a; ObservableCollection<T> 类是 C# 中的一个集合类&#xff0c;它继承自 Collection<T> 并实现了 INotifyCollectionChanged 接口&#xff0c;使得集合的更改可以自动通知给任何监听它的界面元素。这使得…

初见 Rollup 的十大常见问题

文章目录 初见 Rollup 的十大常见问题1. 超神奇的 Rollup 英文解释&#xff01;2. 为什么 ESM 要比 CommonJS 要好呢&#xff1f;3. 什么是 tree-shaking ?4. 如何使用 Rollup 处理 CommonJS&#xff1f;5. 为什么 node-resolve 不是一个内置功能&#xff1f;6. 为什么在进行代…

如何警用root用户登录ssh

使用tail指令&#xff0c;可以动态查看日志信息。 &#xff08;tail -f /var/log/secure或messages&#xff09; 使用>符号&#xff0c;可以清空日志内容&#xff0c;不删除文件本身。 禁用root用户为以下步骤&#xff1a; 首先使用useradd创建用户&#xff08;可以修改为其…

STM32HAL-最简单的时间片论法

目录 概述 一、开发环境 二、STM32CubeMx配置 三、编码 四、运行结果 五、总结 概述 本文章使用最简单的写法时间片论法框架,非常适合移植各类型单片机,特别是资源少的芯片上。接下来将在stm32单片机上实现,只需占用1个定时器作为tick即可。(按键框架+时间片论法)…

20240613每日前端--------聊聊根据面试简历面试的一位高级前端开发工程师

项目经验 封装了通用的表单组件&#xff0c;支持多表单结构&#xff0c;如&#xff1a;富文本编辑器、文件上传等封装了 Echarts 图表组件&#xff0c;可以展示各种报表数据封装了通用的表格组件&#xff0c;支持多条件搜索及分页功能封装了 svg 图标上传组件&#xff0c;将下…