8 Buildroot 根文件系统构建

news2024/11/24 2:13:19

一、根文件系统简介

  根文件系统一般也叫做 rootfs,这个是属于 Linux 内核的一部分。

  根文件系统首先是一种文件系统,该文件系统不仅具有普通文件系统的存储数据文件的功能,但是相对于普通的文件系统,它的特殊之处在于,它是内核启动时所挂载(mount)的第一个文件系统,内核代码的映像文件保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些初始化脚本(如rcS,inittab)和服务加载到内存中去运行。我们要明白文件系统和内核是完全独立的两个部分。在嵌入式中移植的内核下载到开发板上,是没有办法真正的启动Linux操作系统的,会出现无法加载文件系统的错误。

二、buildroot

  Buildroot 是 Linux 平台上一个开源的嵌入式 Linux 系统自动构建框架,用交叉编译生成 Linux 系统。整个Buildroot 是由 Makefile 脚本和 Kconfig 配置文件构成的。

1. buildroot 源码下载

  官方网站:Buildroot - 让嵌入式 Linux 变得简单

  由于我的 Ubuntu 版本较低,所以用正点推荐的 2020.02.6 版本。

2. buildroot 构建根文件系统

① 配置 buildboot

  先把 buildroot-2020.02.6.tar.bz2 拷贝到 Ubuntu 的 linux/tool 路径下。解压命令如下:

tar -vxjf buildroot-2020.02.6.tar.bz2

  buildroot 也支持图形化配置:

make menuconfig

1、配置 Target options

  需要配置的项目和其对应的内容如下(“=”号后面是配置项要选择的内容! ): 

-> Target Architecture = ARM (little endian)
-> Target Binary Format = ELF
-> Target Architecture Variant = cortex-A7
-> Target ABI = EABIhf
-> Floating point strategy = NEON/VFPv4
-> ARM instruction set = ARM

# 目标架构:ARM
# 目标二进制格式:ELF
# 目标架构变体:cortex-A7
# 目标ABI:EABIhf
# 浮点策略:NEON/VFPv4
# ARM指令集:ARM

 2、配置 Toolchain

  此配置项用于配置交叉编译工具链,也就是交叉编译器,这里设置为我们自己所使用的交叉编译器即可。 需要配置的项目和其对应的内容如下: 

Toolchain
    -> Toolchain type = External toolchain
    -> Toolchain = Custom toolchain // 用户自己的交叉编译器
    -> Toolchain origin = Pre-installed toolchain // 预装的编译器
    -> Toolchain path = /usr/local/arm/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf
    -> Toolchain prefix = $(ARCH) -none-linux-gnueabihf 
    -> External toolchain gcc version = 9.x
    -> External toolchain kernel headers series = 4.20.x // 交叉编译器的 linux 版本号
    -> External toolchain C library = glibc/eglibc
    -> [*] Toolchain has SSP support? (NEW)
    -> [*] Toolchain has RPC support? (NEW) 
    > [*] Toolchain has C++ support? 
    -> [*] Enable MMU support (NEW)
    
# 工具链类型:外部工具链
# 工具链:自定义工具链
# 工具链来源:预安装的工具链
# 工具链路径:/usr/local/arm/gcc-arm-9.2-2019.12-x86_64-arm-none-linuxgnueabihf
# 工具链前缀:$(ARCH)-none-linux-gnueabihf
# 外部工具链gcc版本:9.x
# 外部工具链内核头文件系列:4.20.x
# 外部工具链C库:glibc/eglibc
# 工具链是否支持SSP(堆栈保护):选中
# 工具链是否支持RPC:选中
# 工具链是否支持C++:选中
# 是否启用MMU支持:选中

3、配置 System configuration 

  此选项用于设置一些系统配置,比如开发板名字、欢迎语、用户名、密码等。需要配置的项目和其对应的内容如下: 

System configuration
    -> System hostname = ATK-stm32mp1 // 平台名字
    -> System banner = Welcome Lxs // 欢迎语
    -> Init system = BusyBox // 使用 busybox
    -> /dev management = Dynamic using devtmpfs + mdev // 使用 mdev
    -> [*] Enable root login with password (NEW) // 使能登录密码
        -> Root password = 147258 // 登录密码

# 可以设置密码,但是每次重启都要输入密码很麻烦,所以我这里是失能的。

 4、配置 Filesystem images

  此选项配置我们最终制作的根文件系统为什么格式的,配置如下: 

-> Filesystem images
    -> [*] ext2/3/4 root filesystem // 如果是 EMMC 或 SD 卡的话就用 ext3/ext4
        -> ext2/3/4 variant = ext4 // 选择 ext4 格式
        -> exact size =1G // ext4 格式根文件系统 1GB(根据实际情况修改)
    -> [*] ubi image containing an ubifs root filesystem // 如果使用 NAND 的话就用 ubifs

  buildroot 可以直接制作出 ext4 格式的根文件系统,但是一般我们会自行往根文件系统里面添加很多其他的文件,所以产品开发完成以后需要自行打包根文件系统,然后烧写到开发板里面。不管是针对 EMMC 的 ext4 格式的根文件系统还是针对 NAND 的 ubi 格式的根文件系统,都要设置相应的大小,比如这里我们设置的 ex4 格式根文件系统大小为 1GB。 

5、禁止编译 Linux 内核和 uboot

  buildroot 不仅仅能构建根文件系统,也可以编译 linux 内核和 uboot。我们一般都不会使用 buildroot 下载的 linux 内核和 uboot,因为 buildroot 下载的 linux 和 uboot官方源码,里面会缺少很多驱动文件,而且最新的 linux 内核和 uboot 会对编译器版本号有要求,可能导致编译失败。因此我们需要配置 buildroot,关闭 linux 内核和 uboot 的编译,只使用buildroot 来构建根文件系统,首先是禁止 Linux 内核的编译,配置如下:

-> Kernel
    -> [ ] Linux Kernel // 不要选择编译 Linux Kernel 选项!
    
    
-> Bootloaders
    -> [ ] U-Boot // 不要选择编译 U-Boot 选项!

6、编译 Target packages 

  此选项用于配置要选择的第三方库或软件、比如 alsa-utils、 ffmpeg、 iperf 等工具,这里我们先只选择内核的模块加载相关软件,配置如下: 

-> Target packages
    -> System tools
        -> [*] kmod     // 使能内核模块相关命令

  先编译最基础的根文件系统,一步一步来。

7、保存配置项

  和 uboot、 kernel 一样,通过图形化界面配置好 buildroot 以后最好保存一下配置项,防止清除工程以后将配置项给删除掉。 buildroot 的默认配置项都保存在 configs 目录下,配置完成以后选择<Save>,然后输入要设置的配置项名字:

  如果以后重新配置 builroot 可以直接输入:

make stm32mp1_atk_defconfig

  保存完成后就可以看到  stm32mp1_atk_defconfig 这个文件。

② 编译 buildboot

  输入以下命令:

make -j8 //多线程编译

# "-j"参数可以指定同时执行的并发任务数。"-j8"表示同时进行8个并发编译任务。

  编译的时间是真的久,我直接翻墙然后再编译快一点。

  将 rootfs.tar 拷贝到在 nfs 目录下的 rootfs文件夹中并解压,命令如下: 

cp rootfs.tar /home/alientek/linux/nfs/rootfs/ -f
cd ~
cd linux/nfs/rootfs/
tar -vxf rootfs.tar
rm rootfs.tar

  这就是使用 buildroot 编译出来的根文件系统,我们可以通过 nfs 挂载到开发板上,然后对其进行测试。

③ buildboot 测试根文件系统 

  测试方法是通过 nfs 挂载的方式,启动 uboot,修改 bootargs 环境变量,设置 nfsroot 目录为 Ubuntu 中的rootfs 目录,命令如下: 

setenv bootargs console=ttySTM0,115200 root=/dev/nfs nfsroot=192.168.1.105:/home/alientek/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.106:192.168.1.105:192.168.1.1:255.255.255.0::eth0:off''
saveenv

  这里有密码登录,需要取消,输入以下命令:

cd ~
vim linux/nfs/rootfs/etc/inittab

  修改成功后开发板 RESET 重复以下操作:

setenv bootargs console=ttySTM0,115200 root=/dev/nfs nfsroot=192.168.1.105:/home/alientek/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.106:192.168.1.105:192.168.1.1:255.255.255.0::eth0:off''
boot

3. buildroot 下的 busybox 配置

① busybox 配置 

  buildroot 会自动下载 busybox 压缩包, buildroot 下载的源码压缩包都存放在/dl 目录下,在 dl 目录下就有一个叫做“busybox”的文件夹,此目录下保存着 busybox 压缩包,如下图所示:

  但是 buildroot 会将所有解压后的软件保存在 /output/build 目录中。

  进入 busybox 图形化配置界面:

cd ..            # 返回buildroot源码根目录下
make busybox-menuconfig

-> Settings
    -> Build static binary (no shared libs)

# 不要选择这个

  继续配置:

-> Settings
    -> vi-style line editing commands
# 选择这个

  继续配置:

-> Linux Module Utilities
    -> Simplified modutils
# 不要选择这个

  继续配置:

-> Linux System Utilities
    -> mdev (17 kb)     # 确保下面的全部选中,默认都是选中的

  使能 busybox 的 unicode 编码以支持中文:

-> Settings
    -> Support Unicode      # 选中
        -> Check $LC_ALL, $LC_CTYPE and $LANG environment variables     # 选中

  配置完成后还需要让busybox 支持中文:

cd /linux/tools/buildroot-2020.02.6/output/build/busybox-1.31.1
vim libbb/printable_string.c

  修改 31~32 行和 45行:

  修改  busybox-1.32.0/libbb/unicode.c  内容,修改 1022 行和 1031 行:

② 编译 busybox 

cd /linux/tools/buildroot-2020.02.6    # 进入 buildroot 源码目录下
make show-targets    # 当前 buildroot 所有 packages

  如果我们想单独编译并安装 busybox 的话执行下面命令即可:

make busybox    # 编译 busybox

  编译完成以后重新编译 buildroot,主要是对其进行打包,输入如下命令: 

make -j8

  编译完成后查看 output/images 目录下的 rootfs.tar 创建时间是否是刚刚编译的,如果不是就删掉 rootfs.tar,然后重新执行“sudo make”重新编译一下即可。 

4. buildroot 第三方软件和库的配置 

① 使能 VSFTPD 服务

   在开发板上搭建 FTP 服务器,这样可以使用 FileZilla 软件直接向开发板拷文件或把开发板文件拷贝到电脑中。

cd /linux/tools/buildroot-2020.02.6
make menuconfig
-> Target packages
    -> Networking applications
        -> [*] vsftpd

② 使能 SSH

  有时候需要远程登录开发板,这个时候就可以通过网络登录,要用到 SSH 服务。

  保存在 configs/stm32mp1_atk_defconfig。

  之后重新编译 buildroot ,用 make -j8 。将 ouput/images/rootfs.tar 拷贝到 nfs目录下的 rootfs 目录中,然后重新解压。 命令如下:

tar -vxf rootfs.tar

  解压完成以后就可以使用 FTP 和 SSH 等相关的软件了,由于 FTP 和 SSH 都是通过网络进行数据传输的,因此需要先配置网络,如果是通过 nfs 挂载的根文件系统,那么网络已经初始化完成了,因此可以直接使用。如果是烧写到 EMMC 里面的,那么就需要先配置网络相关功能。 

4. buildroot 根文件系统测试

① 软件运行测试

  编译的应用软件一般都使用动态库,使用动态库的话应用软件体积就很小,但是得提供库文件,库文件我们已经添加到了根文件系统中。我们编写一个小小的测试软件来测试一下库文件是否工作正常,在根文件系统下创建一个名为“drivers”的文件夹,以后我们学习 Linux 驱动的时候就把所有的实验文件放到这个文件夹里面。 

#include <stdio.h>
#include <unistd.h>

int main(void)
{
    while(1)
    {
        printf("hello world!\r\n");
        sleep(2);
    }
    return 0;
}

  sleep 相当于 Linux 的延时函数,单位为秒,所以 sleep(2)就是延时 2 秒。因为我们要在 ARM 芯片上运行,需要用交叉编译器编译:

arm-none-linux-gnueabihf-gcc hello.c -o hello

  可以使用 file 命令查看文件类型和编码格式:

file hello

  hello 是个 32 位的 LSB 可执行文件, ARM 架构的,并且是动态链接的。将拷贝到 rootfs/dervers 目录下。

  终止 hello 运行按下 CTRL+C,“./hello &”就是让 hello 在后台运行。在后台运行的软件可以使用“kill -9 pid(进程 ID)”命令来关闭掉,首先使用“ps”命令查看要关闭的软件 PID 是多少, ps 命令用于查看所有当前正在运行的进程,并且会给出进程的 PID。

  首先先让 hello 在后台运行,然后输入 ps 查看 PID 是多少,然后再用 kill -9 命令关闭。

./hello &
ps
kill -9 205

  因为 hello 在不断的输出“hello world”所以我们的输入看起来会被打断,其实是没有的,因为我们是输入,而 hello 是输出。在数据流上是没有打断的,只是显示在 SecureCRT 上就好像被打断了。

② 中文字符测试

  在 ubuntu 中向在 rootfs 目录新建一个名为“中文测试”的文件夹,然后在 MobaXterm 下查看中文名能不能显示正确。输入“ls”命令:

setenv bootargs console=ttySTM0,115200 root=/dev/nfs nfsroot=192.168.1.105:/home/alientek/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.106:192.168.1.105:192.168.1.1:255.255.255.0::eth0:off''

③  开机自启动测试

  进入根文件系统的时候会运行/etc/init.d/rcS 这个 shell 脚本,因此我们可以在这个脚本里面添加自启动相关内容。添加完成以后的/etc/init.d/rcS 文件内容如下: 

#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
runlevel=S
umask 022
export PATH LD_LIBRARY_PATH runlevel

mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts

echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

# 开机自启动
cd /drivers        # 进入 drivers 目录,因为要启动的软件存放在 drivers 目录下
./hello &          # 以后台方式执行 hello 这个软件
cd /               # 退出 drivers 目录,进入到根目录下

④ 外网连接测试

  测试一下看开发板能不能上网,在 rootfs 中新建文件/etc/resolv.conf,然后在里面输入如下内容: 

nameserver 114.114.114.114
nameserver 192.168.1.1

  nameserver 表示这是个域名服务器,设置了两个域名服务器地址:114.114.114.114 和 192.168.1.1。之后重启开发板。

⑤ depmod 测试

  Linux 驱动的时候需要使用此命令分析模块的依赖性,此命令需要在 busybox 中使能,路径如下: 

-> Linux Module Utilities
    -> [*] depmod

  然后再重新编译,一般将驱动模块放到 lib/modules/5.4.31 目录下,既然当前根文件系统不存在这个目录,那么就手动创建此目录,命令如下: 

mkdir /lib/modules/5.4.31 -p

  系统会自动使用这三个文件。

⑥ vsftpd 测试

  首先需要对vsftpd 进行配置,打开/etc/vsftpd.conf 文件,将下面两行前面的“#”去掉: 

  接下来把文件的所属用户改为 root,输入以下命令:

chown root:root /etc/vsftpd.conf

  我们新建一个用户完成 FTP 登录。

  打开  FileZilla,设置新站点。

  连接就可以完成与开发版的 vsftpd 连接。

⑦ sshd 测试

  SSHD 不需要进行配置,只需要创建一个登陆用户即可。我们需要修改/var/empty目录所属用户以及用户组,输入如下命令: 

chown root:root /var/empty/

  同样的,也可以在 ubuntu 下通过 ssh 命令登录开发板,输入如下命令: 

ssh luoxuesong@192.168.1.106

# 其中 luoxuesong 是登录账号名字,192.168.1.106 是我们自己给开发板设的 IP 地址。用户名和 IP 地址用 @ 连接。
# 输入 exit 退出 SSH 会话

⑧ 创建自启动文件

  默认情况下 buildroot 构建的根文件系统中 rcS 文件内容如下:

  rcS 默认会在/etc/init.d 目录下查找所有以‘S’开头的脚本,然后依次执行这些脚本。所以我们可以自己创建一个以‘S’开头的自启动脚本文件,比如我创建一个名为 Sautorun 的自启动文件,命令如下: 

cd /etc/init.d/ 
touch Sautorun 
chmod 777 Sautorun 

  设置好以后重启开发板,此时 Sautorun 脚本就会被 rcS 调用,进而运行 test 软件。 

⑨ 显示路径

  使用 buildroot 构建的根文件系统启动以后会发现,输入命令的时候命令行前面一直都是“#”,如果我们进入到某个目录的话前面并不会显示当前目录路径。

这个是跟 PS1 环境变量有关,它是用于设置命令提示符格式,格式如下: 

PS1 = ‘命令列表’

命令列表中可选的参数如下:
\!:显示该命令的历史记录编号。
\#:显示当前命令的命令编号。
\$:显示$符作为提示符,如果用户是 root 的话,则显示#号。
\\:显示反斜杠。
\d:显示当前日期。
\h:显示主机名。
\n:打印新行。
\nnn:显示 nnn 的八进制值。
\s:显示当前运行的 shell 的名字。
\t:显示当前时间。
\u:显示当前用户的用户名。
\W:显示当前工作目录的名字。
\w:显示当前工作目录的路径

  我们打开 /etc/profile 文件,文件内容如下所示: 

export PATH="/bin:/sbin:/usr/bin:/usr/sbin"

if [ "$PS1" ]; then
	if [ "`id -u`" -eq 0 ]; then
		export PS1='# '
	else
		export PS1='$ '
	fi
fi

export EDITOR='/bin/vi'

# Source configuration files from /etc/profile.d
for i in /etc/profile.d/*.sh ; do
	if [ -r "$i" ]; then
		. $i
	fi
done
unset i

# 3~9 行是设置 P1 环境变量,但是不建议修改,因为当我们重新编译了 buildroot 并解压后这个文件内容就会被替换。
# 14~17 行是 etc/profile 文件会遍历 etc/profile.d 目录下的 .sh 脚本文件,然后执行。所以我们可以自定义 .sh 脚本文件。

  在/etc/profile.d 目录下新建一个名为“myprofile.sh”的 shell 脚本文件,并且给予此文件可执行权限,命令如下: 

cd /etc/profile.d/ 
touch myprofile.sh 
chmod 777 myprofile.sh 

  最后在 myprofile.sh 里面添加如下代码:

#!/bin/sh

PS1='[\u@\h]:\w$ '
export PS1

  之后重启开发板,之后我们就可以看见当前路径和用户。

⑩ 使能 sysfs debug 目录

  后续调试驱动的时候我们可能要用到/sys/kernel/debug 目录,默认我们没有挂载 debugfs 文件系统,所以/sys/kernel/debug 目录下没有任何文件,挂载方法很简单。 输入以下代码:

mount -t debugfs none /sys/kernel/debug

# 修改完重启

5. 烧写根文件系统到 EMMC 中 

① 根文件系统打包

1、新建 ext4 格式磁盘

  输入如下命令创建 ext4 磁盘: 

cd ~
mkdir /home/alientek/linux/rootfs
cd /home/alientek/linux/rootfs   
dd if=/dev/zero of=rootfs.ext4 bs=1M count=1024 # dd 命令创建一个名为 rootfs.ext4 的磁盘,由于根文件系统比较大,因此 count设置为 1024,也就是根文件系统总空间为 1GB
mkfs.ext4 -L rootfs rootfs.ext4 

# "mkfs.ext4":这是用于创建Ext4文件系统的命令。
# "-L rootfs":这个选项用于设置文件系统的标签,将文件系统的标签设置为"rootfs"。
# "rootfs.ext4":指定要格式化的文件系统所在的设备或文件。在这个例子中,我们使用"rootfs.ext4"作为文件系统。

2、将系统镜像拷贝到 ext4 磁盘

  首先创建一个目录用来挂载前面制作制作出来的 rootfs.ext4:

sudo mkdir /mnt/rootfs

  然后使用 mount 命令将 rootfs.ext4 挂载到 /mnt/rootfs 目录下:

cd /home/alientek/linux/rootfs
mount rootfs.ext4 /mnt/rootfs/

  挂载成功以后就将/home/alientek/linux/nfs/rootfs 目录下的所有根文件系统文件拷贝到/mnt/bootfs 目录下,命令如下: 

cd /home/alientek/linux/nfs/rootfs/
sudo cp * /mnt/rootfs/ -drf

  umount 卸载 /mnt/rootfs:

sudo umount /mnt/rootfs

② 烧写到 EMMC

  根文件系统 rootfs.ext4 烧写到开发板的 EMMC里面,使用 STM32CubeProgrammer 软件完成此操作,并修改 Flashlayout。

③ EMMC 启动测试

  烧写完成后,用 uboot 命令行,设置 bootcmd 和 bootargs 两个环境变量:

setenv bootcmd 'ext4load mmc 1:2 c2000000 uImage;ext4load mmc 1:2 c4000000 stm32mp157datk.dtb;bootm c2000000 - c4000000'
setenv bootargs 'console=ttySTM0,115200 root=/dev/mmcblk1p3 rootwait rw'
saveenv
boot

  完成后系统之启动了lo网卡,eh0并没有启动,输入以下命令:

ifconfig eth0 up     # 打开 eth0 网卡

  但是此时开发板网络还不能使用,因为我们还没有配置 eth0 网卡地址信息输入以下命令,如果开发板连接交换机或电脑需要输入以下命令:w

ifconfig eth0 up                                      # 打开 eth0
ifconfig eth0 192.168.1.250 netmask 255.255.255.0     # 设置 IP 地址

  如果开发版直连路由器,直接输入 " udhcpc "命令直接从路由器获得动态IP地址即可。

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

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

相关文章

flutter的ListView和SingleChildScrollView有什么区别?他们的使用场景有什么不一样?

文章目录 简介ListViewSingleChildScrollView使用场景的不同 简介 ListView和SingleChildScrollView都是在Flutter中用于处理滚动内容的组件&#xff0c;但它们有一些关键的区别。 ListView 多个子元素&#xff1a; ListView是一个滚动的可滚动组件&#xff0c;通常用于包含多…

看图识药,python开发实现基于VisionTransformer的119种中草药图像识别系统

中药药材图像识别相关的实践在前面的系列博文中已经有了相应的实践了&#xff0c;感兴趣的话可以自行移步阅读即可&#xff0c;每篇文章的侧重点不同&#xff1a; 《python基于轻量级GhostNet模型开发构建23种常见中草药图像识别系统》 《基于轻量级MnasNet模型开发构建40种常…

HTML中常用表单元素使用(详解!)

Hi i,m JinXiang ⭐ 前言 ⭐ 本篇文章主要介绍HTML中常用表单元素使用以及部分理论知识 &#x1f349;欢迎点赞 &#x1f44d; 收藏 ⭐留言评论 &#x1f4dd;私信必回哟&#x1f601; &#x1f349;博主收将持续更新学习记录获&#xff0c;友友们有任何问题可以在评论区留言 …

云基础软件深化合作,云轴科技ZStack与麒麟软件战略签约

12月8日&#xff0c;云轴科技ZStack与麒麟软件战略合作签约仪式在北京举行&#xff0c;双方对过往紧密合作表达了充分肯定&#xff0c;并就进一步联合技术创新、打造重点行业标杆和持续赋能客户达成高度共识。云轴科技创始人&CEO张鑫和麒麟软件高级副总经理谢文征共同见证双…

112. 路径总和(Java)

目录 解法&#xff1a; 官方解法&#xff1a; 方法一&#xff1a;广度优先搜索 思路及算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 方法二&#xff1a;递归 思路及算法 复杂度分析 时间复杂度&#xff1a; 空间复杂度&#xff1a; 给你二叉树的…

【毕业设计】基于STM32的解魔方机器人

1、方案设计 1.采用舵机作为魔方机器人的驱动电机&#xff0c;从舵机的驱动原理可知&#xff1a;舵机运行的速度和控制器的主频没有关系&#xff0c;所以采用单片机和采用更高主频的嵌入式处理器相比在控制效果上没有什么差别。单片机编程过程简单&#xff0c;非常容易上手&am…

c#_sqlserver_三层架构winform学生信息管理及选课系统

基本功能包括管理员登录、注册学生账号、删除学生信息、查找学生信息、发布课程、修改课程、删除课程等。 教师端 登录&#xff1a;管理员登陆&#xff0c;拥有相应账号即可登录&#xff08;后台注册&#xff09;。注册学生账号&#xff1a;管理员可给学生分配学号&#xff0…

Linux Mint编译安装Qemu

文章目录 前言1. 准备Qemu源码包2. 编译安装2.1 首次尝试编译2.2 安装python3-venv2.3 安装sphinx2.4 安装sphinx-rtd-theme2.4 安装ninja2.6 安装编译器 3. 重新编译并安装4. 进行固件仿真4.1 准备固件4.2 Binwalk解析文件4.3 看一下文件结构4.4 安装sasquatch4.5 重新解析文件…

OkHttp: 拦截器和事件监听器

文章目录 1. 拦截器1. 拦截器链2. 实际案例1. 注册为应用拦截器2. 注册为网络拦截器 3. 如何选择用哪种拦截器1. 应用拦截器2. 网络层拦截器3. 重写请求4. 重写响应 4. 可用性 2. 事件监听器1. 请求的生命周期2. EventListener使用案例3. EventListener.Factory4. 调用失败的请…

一、Oracle学习笔记

1.1.1实例的概念实例是一组内存结构和后台进程的集合。oracle适用于大型的应用系统1.1.2实例的构成1.实例中的这部分内存结构叫做系统全局区&#xff08;SGA&#xff09;:存储数据库中的数据、存储数据字典的信息、重做日志、经过解析的SQL代码等一个实例只有一个SGA&#xff1…

QT作业4

实现一个闹钟&#xff0c;当输入时间后&#xff0c;点击启动到达时间后循环播报三遍&#xff0c;便签内容 头文件&#xff1a; #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTextToSpeech> //文本转语言类 #include <QTimerEvent> //定…

EasyV易知微助力智慧城市未来趋势发展——数字孪生城市

“智慧城市的未来趋势就是数字孪生”——《基于数字孪生的智慧城市》 城市数字化管理、智慧城市和数字孪生城市的发展是相互促进、逐步深化的过程。 城市数字化管理作为起点&#xff0c;奠定了信息化、数据化的基础&#xff1b;而智慧城市则将数字城市管理进一步升级&#xff…

什么是防抖与节流?应用场景举例

防抖节流如何处理防抖与节流 防抖节流防抖例子节流例子Vue Axios全局接口防抖、节流封装实现 小结 防抖 防抖&#xff1a;触发高频事件后n秒内函数只会执行一次&#xff0c;如果n秒内高频事件再次被触发&#xff0c;则重新计算时间 应用场景&#xff1a; 提交按钮、用户注册…

时间序列预测 — CNN-LSTM实现多变量多步光伏预测(Tensorflow)

目录 1 数据处理 1.1 导入库文件 1.2 导入数据集 1.3 缺失值分析 2 构造训练数据 ​3 模型训练 3.1 CNN-LSTM网络 3.2 模型训练 4 模型预测 专栏链接&#xff1a;https://blog.csdn.net/qq_41921826/category_12495091.html 1 数据处理 1.1 导入库文件 import scip…

数据库系统相关概念

数据&#xff1a;描述事务的符号记录。 数据库(DB)&#xff1a;按一定的数据模型组织&#xff0c;描述和存储在计算机内的&#xff0c;有组织的&#xff0c;可共享的数据集合。 数据库管理系统(DBMS)&#xff1a;位于用户和操作系统之间的一层数据管理软件。主要功能包括&#…

(C++)最大连续1的个数--滑动窗口

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://le…

【LeetCode题目拓展】第207题 课程表 拓展(拓扑排序、Tarjan算法、Kosaraju算法)

文章目录 一、拓扑排序题目二、题目拓展1. 思路分析2. tarjan算法3. kosaraju算法 一、拓扑排序题目 最近在看一个算法课程的时候看到了一个比较好玩的题目的扩展&#xff0c;它的原题如下&#xff1a; 对应的LeetCode题目为 207. 课程表 这个题目本身来说比较简单&#xff…

C# WPF上位机开发(增强版绘图软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 前面我们写过一个绘图软件&#xff0c;不过那个比较简单&#xff0c;主要就是用鼠标模拟pen进行绘图。实际应用中&#xff0c;另外一种使用比较多的…

【flutter对抗】blutter使用+ACTF习题

最新的能很好反编译flutter程序的项目 1、安装 git clone https://github.com/worawit/blutter --depth1​ 然后我直接将对应的两个压缩包下载下来&#xff08;通过浏览器手动下载&#xff09; 不再通过python的代码来下载&#xff0c;之前一直卡在这个地方。 如果读者可以…

C++11 【初识】

C11简介 1.在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。 2.不过由于C03(TC1)主要是对C98标准中的漏洞进行修复&#xff0c;语言的核心部分则没有改动&#xff0c;因此人们习惯性的把两个标准合…