8 Buildroot 根文件系统构建

一、根文件系统简介

  根文件系统一般也叫做 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地址即可。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

十六 动手学深度学习v2计算机视觉 ——样式迁移

文章目录 基于CNN的样式迁移 基于CNN的样式迁移 我们通过前向传播&#xff08;实线箭头方向&#xff09;计算风格迁移的损失函数&#xff0c;并通过反向传播&#xff08;虚线箭头方向&#xff09;迭代模型参数&#xff0c;即不断更新合成图像。 风格迁移常用的损失函数由3部分组…

源码角度简单介绍LinkedList

LinkedList是一种常见的数据结构&#xff0c;但是大多数开发者并不了解其底层实现原理&#xff0c;以至于存在很多误解&#xff0c;在这篇文章中&#xff0c;将带大家一块深入剖析LinkedList的源码&#xff0c;并为你揭露它们背后的真相。首先想几个问题&#xff0c;例如&#…

科技提升安全,基于YOLOv7【tiny/yolov7/yolov7x】开发构建商超扶梯场景下行人安全行为姿态检测识别系统

在商超等人流量较为密集的场景下经常会报道出现一些行人在扶梯上摔倒、受伤等问题&#xff0c;随着AI技术的快速发展与不断普及&#xff0c;越来越多的商超、地铁等场景开始加装专用的安全检测预警系统&#xff0c;核心工作原理即使AI模型与摄像头图像视频流的实时计算&#xf…

头歌——HBase 开发:使用Java操作HBase

第1关&#xff1a;创建表 题目 任务描述 本关任务&#xff1a;使用Java代码在HBase中创建表。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.如何使用Java连接HBase数据库&#xff0c;2.如何使用Java代码在HBase中创建表。 如何使用Java连接HBase数据库…

网神 SecGate3600 authManageSet.cgi信息泄露漏洞复现

漏洞概述 网神SecGate 3600 authManageSet.cgi 接口存在敏感信息泄露漏洞&#xff0c;未授权得攻击者可以通过此漏洞获取控制台管理员用户名密码等凭据&#xff0c;可登录控制整个后台&#xff0c;使系统处于极不安全的状态 复现环境 FOFA&#xff1a;body"sec_gate_im…

python冒泡排序

冒泡排序思想 大家可以把我们所有的需要排列的数字想象成一个水中的气泡&#xff0c;大的数字想象成大气泡&#xff0c;小的数字想象成小气泡。 其实冒泡排序就是比较相邻的两个数字的大小&#xff0c;然后大的数字排在小的数字的后面&#xff0c;我们依次比较&#xff0c;第一…

“百里挑一”AI原生应用亮相,百度智能云千帆AI加速器首个Demo Day来了!

作者简介&#xff1a; 辭七七&#xff0c;目前大二&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

Android : BottomNavigation底部导航_简单应用

示例图&#xff1a; 1.先创建底部导航需要的图片 res → New → Vector Asset 创建三个矢量图 图片1 baseline_home.xml <vector android:height"24dp" android:tint"#000000"android:viewportHeight"24" android:viewportWidth"24…

MySQL BinLog 数据还原恢复

博文目录 文章目录 查看状态查看 binlog 开关及存储路径查看 binlog 配置 如 存储格式 binlog_format查看当前还存在的日志查看当前正在使用的日志 切换日志确定日志确定日志文件日志格式改写日志简要说明确定日志位置以事件为单位查看日志分析日志 还原数据 查看状态 查看 b…

循环神经网络-1

目录 1 数据集构建 1.1 数据集的构建函数 1.2 加载数据并进行数据划分 1.3 构造Dataset类 2 模型构建 2.1 嵌入层 2.2 SRN层 2.3 线性层 2.4 模型汇总 3 模型训练 3.1 训练指定长度的数字预测模型 3.2 多组训练 3.3 损失曲线展示 4 模型评价 总结 参考文献 循环神经网络&…

记录一下如何使用python生成二维码 并简单练习命令行参数供初学者参考

主代码main.py 后面是演示效果图&#xff1a; import argparse import sysimport qrcode import os qr qrcode.QRCode(version1,error_correctionqrcode.constants.ERROR_CORRECT_L,box_size10,border4, ) fileList[] fileName[]parserargparse.ArgumentParser(description生…

Uncaught ReferenceError: jQuery is not defined解决方法

当我在写java的Maven项目时&#xff0c;出现了这样的一个报错信息&#xff1a; 我一直找代码&#xff0c;抓包&#xff0c;调试&#xff0c;比对代码 jQuery未定义就是指JS的导包没有导进来&#xff01;&#xff01;&#xff01;&#xff01; 导进来就运行正常啦

Docker部署Nacos集群并用nginx反向代理负载均衡

首先找到Nacos官网给的Github仓库&#xff0c;里面有docker compose可以快速启动Nacos集群。 文章目录 一. 脚本概况二. 自定义修改1. example/cluster-hostname.yaml2. example/.env3. env/mysql.env4. env/nacos-hostname.env 三、运行四、nginx反向代理&#xff0c;负载均衡…

二、SpringFramework 介绍

2.1 Spring 和 SpringFramework概念 https://spring.io/projects 广义的 Spring&#xff1a;Spring 技术栈&#xff08;全家桶&#xff09; 广义上的 Spring 泛指以 Spring Framework 为基础的 Spring 技术栈。 经过十多年的发展&#xff0c;Spring 已经不再是一个单纯的应…

OpenHarmony 如何去除系统锁屏应用

前言 OpenHarmony源码版本&#xff1a;4.0release / 3.2 release 开发板&#xff1a;DAYU / rk3568 一、3.2版本去除锁屏应用 在源码根目录下&#xff1a;productdefine/common/inherit/rich.json 中删除screenlock_mgr组件的编译配置&#xff0c;在rich.json文件中搜索th…

保姆级:Windows Server 2012上安装.NET Framework 3.5

目录 一.问题所在无法在安装SQL server2008&#xff08;2012&#xff09; 1.无法安装一下功能 .NET Framework 3.5 二.解决措施 1、打开服务器管理器 2、添加角色和功能 3、选择安装功能 4、指定备用源路径 5、配置本地文件路径 一.问题所在无法在安装SQL server2008&…

西南交通大学【数据结构实验8】

实验内容及要求&#xff1a; 编写控制台应用程序&#xff0c;提供以下菜单项&#xff1a; 插入元素 从键盘输入若干两两互不相同的非0整数&#xff0c;直到输入0时停止。将输入的所有非0整数按输入次序插入二叉排序树(初始时是空树)。 插入某个非0整数时&#xff0c;若该整…

算法Day30 餐厅的套餐

餐厅的套餐 Description 假设有一家餐厅&#xff0c;菜单上有n道菜可供选择&#xff0c;现在需要从中选择k道菜组成一份套餐。请设计一个算法&#xff0c;返回所有可能但互不相同的菜品组合。 Input 不同菜品的id各不相同&#xff0c;分别为1,2,3…n,输入内容依次为n和k的值&a…

skynet 中 mongo 模块运作的底层原理解析

文章目录 前言总览全流程图涉及模块关系连接数据库函数调用流程图数据库操作函数调用流程图涉及到的代码文件 建立连接SCRAMSASL 操作数据库结语参考链接 前言 这篇文章总结 skynet 中 mongo 的接入流程&#xff0c;代码解析&#xff0c;读完它相信你对 skynet 中的 mongo 调用…

Python:核心知识点整理大全16-笔记

目录 8.2.3 默认值 8.2.4 等效的函数调用 8.2.5 避免实参错误 8.3 返回值 8.3.1 返回简单值 formatted_name.py 8.3.2 让实参变成可选的 8.3.3 返回字典 往期快速传送门&#x1f446;&#xff08;在文章最后&#xff09;&#xff1a; 8.2.3 默认值 编写函数时&#xff…