【正点原子FPGA连载】第二十一章根文件系统构建 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Linux开发指南

news2024/11/15 13:38:28

1)实验平台:正点原子MPSoC开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html

第二十一章根文件系统构建

Linux“三巨头”已经完成了2个了,就剩最后一个rootfs(根文件系统)了,本章我们就来学习一下根文件系统的组成以及如何构建根文件系统。这是Linux移植的最后一步,根文件系统构建好以后就意味着我们已经拥有了一个完整的、可以运行的最小系统。以后我们就在这个最小系统上编写、测试Linux驱动,移植一些第三方组件,逐步的完善这个最小系统。最终得到一个功能完善、驱动齐全、相对完善的操作系统。

15.1根文件系统简介

根文件系统一般也叫做rootfs,那么什么叫根文件系统?看到“文件系统”这四个字,很多人,包括我第一反应就是FATFS、FAT、EXT4、YAFFS和NTFS等这样的文件系统。在这里,根文件系统并不是FATFS、EXT4这样的文件系统,这些文件系统属于Linux内核的一部分。Linux中的根文件系统更像是一个文件夹或者叫做目录(在我看来就是一个文件夹,只不过是特殊的文件夹),在这个目录里面会有很多的子目录。根目录下和子目录中会有很多的文件,这些文件是Linux运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等。以后我们说到文件系统,如果不特别指明,统一表示根文件系统。对于根文件系统专业的解释,百度百科上是这么说的(原谅我把百度百科引用为专业解释,因为我实在找不到根文件系统的最初定义,也不要建议我到哪些404网站去查找,毕竟我胖,我怕翻到一般梯子不稳把我摔丑了):
根文件系统首先是内核启动时所mount(挂载)的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。
百度百科上说内核代码镜像文件保存在根文件系统中,但是我们嵌入式Linux并没有将内核代码镜像保存在根文件系统中,而是保存到了其他地方。比如NAND Flash的指定存储地址、eMMC专用分区中。根文件系统是Linux内核启动以后挂载(mount)的第一个文件系统,然后从根文件系统中读取初始化脚本,比如rcS,inittab等。根文件系统和Linux内核是分开的,单独的Linux内核是没法正常工作的,必须要搭配根文件系统。如果不提供根文件系统,Linux内核在启动的时候就会提示内核崩溃(Kernel panic)的提示,这个在13.7小节已经说过了。
根文件系统的这个“根”字就说明了这个文件系统的重要性,它是其他文件系统的根,没有这个“根”,其他的文件系统或者软件就别想工作。比如我们常用的ls、mv、ifconfig等命令其实就是一个个小软件,只是这些软件没有图形界面,而且需要输入命令来运行。这些小软件就保存在根文件系统中,这些小软件是怎么来的呢?这个就是我们本章教程的目的,教大家来构建自己的根文件系统,这个根文件系统是满足Linux运行的最小根文件系统,后续我们可以根据自己的实际工作需求不断的去填充这个最小根文件系统,最终使其成为一个相对完善的根文件系统。
在构建根文件系统之前,我们先来看一下根文件系统里面大概都有些什么内容,以Ubuntu为例,根文件系统的目录名字为‘/’,没看错,就是一个斜杠,所以输入如下命令就可以进入根目录中:
cd / //进入根目录
进入根目录以后输入“ls”命令查看根目录下的内容都有哪些,结果如下图所示:
在这里插入图片描述

图 15.1.1 Ubuntu根目录
上图中根目录下子目录和文件不少,但是这些都是Ubuntu所需要的,其中有很多子目录和文件我们嵌入式Linux是用不到的,所以这里就讲解一些常用的子目录:
1、/bin目录
看到“bin”大家应该能想到bin文件,bin文件是可执行文件,所以此目录下存放着系统需要的可执行文件,一般都是一些命令,比如ls、mv等命令。此目录下的命令所有的用户都可以使用。
2、/dev目录
dev是device的缩写,所以此目录下的文件都是和设备有关的,是设备文件。在Linux下一切皆文件,即使是硬件设备,也是以文件的形式存在的,比如/dev/ttyPS0(ZYNQ根目录会有此文件)就表示ZYNQ的串口0,我们要想通过串口0发送或者接收数据就要操作文件/dev/ttyPS0,通过对文件/dev/ttyPS0的读写操作来实现串口0的数据收发。
3、/etc目录
此目录下存放着各种服务程序的配置文件,里面的配置文件非常多。但是在嵌入式Linux下此目录会很简洁。
4、/lib目录
lib是library的简称,也就是库的意思,因此此目录下存放着Linux所必须的库文件。这些库文件是共享库,命令和用户编写的应用程序要使用这些库文件。
5、/mnt目录
临时挂载目录,一般用于安装移动介质,可以在此目录下创建空的子目录,比如/mnt/sd、/mnt/usb,这样就可以将SD卡或者U盘挂载到/mnt/sd或者/mnt/usb目录中。
6、/proc目录
此目录一般是空的,当Linux系统启动以后会将此目录作为proc文件系统的挂载点,proc是个虚拟文件系统,没有实际的存储设备。proc里面的文件都是临时存在的,一般用来存储系统运行信息文件。
7、/usr目录
要注意,usr不是user的缩写,而是Unix Software Resource的缩写,也就是Unix操作系统软件资源目录,用于存放用户级的数据和程序。这里有个小知识点,那就是Linux一般被称为类Unix操作系统,苹果的MacOS也是类Unix操作系统。关于Linux和Unix操作系统的渊源可以直接在网上找Linux的发展历史。
8、/var目录
此目录用于存放一些动态的程序数据,如系统日志等。
9、/sbin目录
此目录用于存放系统管理员常用的管理程序。具有管理员权限才可以使用,主要用户系统管理。
10、/sys目录
系统启动以后此目录作为sysfs文件系统的挂载点,sysfs是一个类似于proc文件系统的特殊文件系统,sysfs也是基于ram的文件系统,也就是说它也没有实际的存储设备。此目录是系统设备管理的重要目录,此目录通过一定的组织结构向用户提供详细的内核数据结构信息。
11、/opt
可选的文件、软件存放区,由用户选择将哪些文件或软件放到此目录中。
12、/home
普通用户的工作目录。
13、/root
超级用户的工作目录
关于Linux的根目录就介绍到这里,接下来的构建根文件系统就是研究如何创建上面这些子目录以及子目录中的文件。
15.2Petalinux构建根文件系统
构建根文件系统有两种方式,一种是手工创建根目录并编译配置相关文件,另一种是通过相应的工具来构建。手工构建方式耗时耗力并无多大意义,这里我们采用相应的工具来构建。构建根文件系统的工具有很多,如BusyBox、buildroot、Yocto等。由于Petalinux工具已经包含了Yocto,所以我们可以直接使用Petalinux工具来构建根文件系统。
实际上我们在6.3.6节配置Linux根文件系统就是在构建根文件系统,当时我们使用的是默认配置,在后面的使用中可以看到默认配置是可以满足一般的需求的。现在我们进入到第六章创建的Petalinux工程目录下,具体看下Petalinux的根文件系统构建。
进入Petalinux工程目录后,在终端输入下面的命令配置根文件系统:
petalinux-config -c rootfs
下图就是根文件系统的配置界面:
在这里插入图片描述

图 15.2.1 根文件系统的配置界面
可以看到有6个子菜单,其中“Filesystem Packages”菜单主要是配置根文件常用的工具软件,包括内核调试软件、流媒体软件、Python软件以及图形界面软件等,具体的我们就不细看了。
“Petalinux Package Groups”菜单可以使能Petalinux提供的软件包组,所谓的软件包组即将与该软件相关的组件和模块放入一组,譬如“packagegroup-petalinux-opencv”包含opencv需要的包:opencv、libopencv-core、libopencv-highgui、libopencv-imgproc、libopencv-objdetect、libopencv-ml、libopencv-calib3d、libopencv-ccalib,当使能“packagegroup-petalinux-opencv”时,这些包也会自动使能,这样做的好处是解决了软件依赖的问题。
“Image Features”菜单可以配置根文件系统的某些功能,如是否支持ssh,使用dropbear的ssh还是openssh等。如果不希望每次启动linux后都得输入密码验证,可以使能该菜单下的“debug-tweaks”选项。如下图所示:
在这里插入图片描述

图 15.2.2 配置自动登录
这样配置后,会自动登录,不用再手动输入用户名和密码,方便调试。
“apps”菜单可用来构建根文件系统的用户应用。
“user packages”菜单可用来配置用户自定义的软件包,因为我们没有自定义软件包,所以该菜单为空。
“PetaLinux RootFS Settings”主要是用来设置root用户的密码,默认为“root”。
介绍完这6个菜单后,我们退出配置界面。如果没有做修改,就不需要重新编译根文件系统,如果做了修改可以使用如下命令编译根文件系统:
petalinux-build -c rootfs
Petalinux工程生成的根文件系统在images/linux/目录下,如下图所示:

图 15.2.3 Petalinux工程生成的根文件系统
图中带有“rootfs”的文件名都是Petalinux生成的根文件系统。一般我们使用rootfs.tar.gz文件。我们可以将rootfs.tar.gz文件解压到SD卡的第二个分区——ext4文件系统分区来测试根文件系统,可参考第九章Linux图形界面的搭建。不过我们在Linux驱动开发的时候一般都是通过nfs挂载根文件系统的,当产品最终上市的时候才会将根文件系统烧写到eMMC或者SD中,这样做的好处是方便调试,免得多次插拔SD卡。
我们在4.4节设置的nfs服务器目录下创建一个名为rootfs的子目录(名字随意,此处为了方便使用了rootfs),比如笔者的电脑中“/home/shang/workspace/nfs”就是笔者设置的NFS服务器目录,使用如下命令创建名为rootfs的子目录:
mkdir rootfs
创建好rootfs子目录就可以用来存放我们的根文件系统了。我们将rootfs.tar.gz文件解压到rootfs目录。命令如下:
tar -xzvf images/linux/rootfs.tar.gz -C ~/workspace/nfs/rootfs/
解压完成的rootfs目录内容如下图所示:
在这里插入图片描述

图 15.2.4 rootfs目录
可以看到该有的目录都有了。接下来我们测试该根文件系统。
15.3根文件系统测试
测试根文件系统rootfs的方法就是使用NFS挂载,uboot里面的bootargs环境变量会设置“root”的值,所以我们将root的值改为NFS挂载即可。在Linux内核源码里面有相应的文档讲解如何设置,文档为Documentation/filesystems/nfs/nfsroot.txt,格式如下:
root=/dev/nfs nfsroot=[:][,] ip=:::::::::
root=/dev/nfs这是启用nfs挂载所必需的。注意,它不是真正的设备,只是告诉内核使用NFS加载根文件系统。
nfsroot:
:nfs服务器IP地址,也就是存放根文件系统主机的IP地址,比如笔者的存放根文件系统主机Ubuntu的IP地址为192.168.2.21。
:nfs服务器上根文件系统的存放路径,比如笔者的是/home/shang/workspace/nfs/rootfs。
:NFS的其他可选选项,一般不设置。
ip:
可以自动配置(开发板连接路由器,自动获取IP地址),也可以手动配置(开发板直连电脑,手动设置静态IP地址),由下面的选项决定。使用自动配置时,可直接变成“ip=dhcp”。
:客户端IP地址,也就是我们开发板的IP地址,Linux内核启动以后就会使用此IP地址来配置开发板。此地址一定要和Ubuntu主机在同一个网段内,并且没有被其他的设备使用,在Ubuntu中使用ping命令ping一下就知道要设置的IP地址有没有被使用,如果不能ping通就说明没有被使用,那么就可以设置为开发板的IP地址,比如笔者设置为192.168.2.22。
:服务器IP地址,前面已经说了。
:网关地址,笔者的网关地址是192.168.2.1。
:子网掩码,一般是255.255.255.0。
:客户机的名字,一般不设置,此值可以空着。
:设备名,也就是网卡名,一般是eth0,eth1….,正点原子的MPSoC开发板的PL_ETH为eth0,PS_ETH为eth1,如果开发板上的两个网口都配置的情况下。这里我们使用PL_ETH,因为linux启动后默认使用eth0,也就是所以PL_ETH。
:自动配置,一般不使用,所以设置为off。
:DNS0服务器IP地址,不使用。
:DNS1服务器IP地址,不使用。
根据上面的格式设置bootargs环境变量的root值如下:
root=/dev/nfs nfsroot=192.168.2.21:/home/shang/workspace/nfs/rootfs ip=192.168.2.22:192.168. 2.21:192.168.2.1:255.255.255.0::eth1:off’
启动开发板,进入uboot命令行模式,然后重新设置bootargs环境变量,命令如下:
setenv bootargs ‘console=ttyPS0,115200 root=/dev/nfs rw nfsroot=192.168.2.21:/home/ shang/workspace/nfs/rootfs,nfsvers=3 ip=192.168.2.22:192.168.2.21:192.168.2.1:255.255.255.0::eth1:off’ //设置bootargs
saveenv //保存环境变量
如果开发板是通过网线与路由器相连接,可以使用下面的bootargs环境变量:
setenv bootargs ‘console=ttyPS0,115200 root=/dev/nfs nfsroot=192.168.2.21:/home/shang/workspace/nfs/rootfs,tcp ip=dhcp rw’
saveenv //保存环境变量
设置好以后使用“boot”命令启动Linux内核,结果如下图所示:
在这里插入图片描述

图 15.3.1进入根文件系统
从上图可以看出,系统已经进入了根文件系统,说明我们的根文件系统工作了。如果没有启动进入根文件系统的话可以重启一次开发板试试。我们可以输入“ls /”命令测试一下,结果如下图所示:
在这里插入图片描述

图 15.3.2 ls命令测试
可以看出ls命令工作正常,说明根文件系统基本没问题。接下来我们进行其他功能测试。

15.4根文件系统其他功能测试

15.4.1软件运行测试
我们使用Linux的目的就是运行我们自己的软件,我们编译的应用软件一般都使用动态库,使用动态库的话应用软件体积就很小,但是得提供库文件,库文件我们已经添加到了根文件系统中。我们编写一个小小的测试软件来测试一下库文件是否工作正常,在Ubuntu虚拟机的~/workspace/nfs/rootfs目录下创建一个名为“drivers”的文件夹,以后我们学习Linux驱动的时候就把所有的实验文件放到这个文件夹里面。
在前面创建的“drivers”文件夹下使用vim编辑器新建一个hello.c文件,在hello.c里面输入如下内容:

1  #include <stdio.h>
2  
3  int main(void)
4  {
5      int i=0;
6      while(i < 4){
7          printf("Hello World!\r\n");
8          i++;
9          sleep(2);
10     }
11     return 0;
12 }

hello.c内容很简单,就是循环输出“hello world”4次。sleep相当于Linux的延时函数,单位为秒,所以sleep(2)就是延时2秒。编写完代码后执行编译,因为我们是要在ARM64位芯片上运行的,所以要用交叉编译器去编译,也就是使用$CC(带参数的aarch64-xilinx-linux-gcc)编译(需要先执行10.5节的设置SDK的工作环境),然后执行如下命令:
C C h e l l o . c − o h e l l o 使用 CC hello.c -o hello 使用 CChello.cohello使用CC将hello.c编译为hello可执行文件。这个hello可执行文件究竟是不是ARM使用的呢?使用“file”命令查看文件类型以及编码格式:
file hello //查看hello的文件类型以及编码格式
结果如下图所示:
在这里插入图片描述

图 15.4.1查看hello编码格式
从上图可以看出,输入“file hello”后输出了如下信息:
hello: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked……
意思是hello文件是64位的LSB可执行文件,基于ARM aarch64架构,并且是动态链接的,所以我们编译出来的hello可以在MPSoC开发板上运行。
同时,我们在开发板终端中也能看到生成的的可执行文件,如下图所示:
在这里插入图片描述

图 15.4.2 查看可执行文件
在开发板中输入如下命令来执行这个可执行文件:
cd /drivers //进入drivers目录
./hello //执行hello
结果如下图所示:
在这里插入图片描述

图 15.4.3 hello运行结果
可以看出,程序hello运行正常,说明我们的根文件系统中的共享库是没问题的。在程序运行的时候应该能感觉到,hello程序执行的时候终端是没法用的,除非使用“ctrl+c”组合键来关闭hello程序,那么有没有办法既能让hello正常运行,而且终端能够正常使用?答案是有的,让hello程序进入后台运行就行了,让一个软件进入后台的方法很简单,运行软件的时候加上“&”即可,比如“./hello &”就是让hello程序在后台运行。在后台运行的软件可以使用“kill -9 pid(进程ID)”命令来关闭掉,首先使用“ps”命令查看要关闭的软件PID是多少,ps命令用于查看所有当前正在运行的进程,并且会给出进程的PID。输入“ps”命令,结果如下图所示:
在这里插入图片描述

图 15.4.4 ps命令结果
从上图可以看出hello程序对应的PID为1184,因此我们使用如下命令关闭在后台运行的hello软件:
kill -9 1184
因为hello在不断的输出“hello world”所以我们的输入看起来会被打断,其实是没有的,因为我们是输入,而hello是输出。在数据流上是没有打断的,只是显示在SecureCRT上就好像被打断了,所以只管输入“kill -9 1184”即可。hello被kill以后会有提示,如下图所示:
在这里插入图片描述

图 15.4.5提示hello被kill掉
再去用ps命令查看一下当前的进程,发现没有hello了。这个就是Linux下的软件后台运行以及如何关闭软件的方法,重点就是3个操作:程序后面加“&”、使用ps查看要关闭的软件PID、使用“kill -9 pid”来关闭指定的软件。

15.4.2开机自启动测试

在上一小节测试hello软件的时候都是等Linux启动进入根文件系统以后手动输入命令“./hello”来完成的。我们一般做好产品以后都是需要开机自动启动相应的软件,本节我们就以hello这个软件为例,讲解一下如何实现开机自启动。开机启动后进入根文件系统的时候会运行/etc/init.d/rcS这个shell脚本,Linux内核启动以后需要启动一些服务,而rcS就是规定启动哪些文件的脚本文件。因此我们可以在这个脚本里面添加自启动相关内容。添加完成以后的/etc/init.d/rcS文件内容如下:

1  #!/bin/sh
2  #
3  # rcS        Call all S??* scripts in /etc/rcS.d in
4  #        numerical/alphabetical order.
5  #
6  # Version:   @(#)/etc/init.d/rcS  2.76  19-Apr-1999  miquels@cistron.nl
7  #
8  
9  PATH=/sbin:/bin:/usr/sbin:/usr/bin
10 runlevel=S
11 prevlevel=N
12 umask 022
13 export PATH runlevel prevlevel
14 
15 #    Make sure proc is mounted
16 #
17 [ -d "/proc/1" ] || mount /proc
18 
19 #
20 #    Source defaults.
21 #
22 . /etc/default/rcS
23 
24 #开机自启动
25 cd /drivers
26 ./hello &
27 cd 
28 
29 #
30 #    Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
31 #
32 trap ":" INT QUIT TSTP
33 
34 #
35 #    Call all parts in order.
36 #
37 exec /etc/init.d/rc S

第25行,进入drivers目录,因为要启动的软件存放在drivers目录下。
第26行,以后台方式执行hello程序。
第27行,退出drivers目录,进入到当前用户目录下。
自启动代码添加完成以后就可以重启开发板,看看hello这个软件会不会自动运行。结果如下图所示:
在这里插入图片描述

图 15.4.6 hello开机自启动
从上图可以看出,hello程序开机自动运行了,说明开机自启动成功。
15.4.3网络连接测试
本小节的网络连接测试是指测试MPSoC开发板能否连接到互联网。需要提醒的是,测试的MPSoC开发板需要和能连接到互联网的路由器用网线连接,如果MPSoC开发板是和我们的主机电脑连接的话,本小节可跳过,因为这种情况下MPSoC开发板是不能连接到互联网的,除非电脑主机有路由器的功能。
测试方法很简单,就是通过ping命令来ping百度的官网:www.baidu.com。输入如下命令:
ping www.baidu.com
结果如下图所示:
在这里插入图片描述

图 15.4.7 ping测试结果
可以看出,测试失败,提示www.baidu.com是个“bad address”,也就是地址不对,显然我们的地址是正确的。之所以出现这个错误提示是因为www.baidu.com的地址解析失败,并没有解析出其对应的IP地址。我们需要配置域名解析服务器的IP地址,一般域名解析地址可以设置为所处网络的网关地址,比如192.168.2.1,也可以设置为公共DNS服务器地址如114.114.114.114。
设置很简单,可以直接在串口终端中输入“udhcpc”命令,该命令可自动获取IP地址,并且修改nameserver的值,一般是将其设置为对应的网关地址。输入“udhcpc”命令后,执行结果如下图所示:
在这里插入图片描述

图 15.4.8 “udhcpc”命令
从上图可以看到,执行“udhcpc”命令后,我们的MPSoC开发板获得了IP地址“192.168.2.124”,添加了DNS地址为网关地址“192.168.2.1”。现在我们重新ping一下百度官网,结果如下图所示:
在这里插入图片描述

图 15.4.9 ping百度官网结果
参数“-c 4”代表ping 4次就停止,否则无限次的ping。从上图可以看出ping百度官网成功了。域名也成功的解析了,至此,我们的根文件系统就彻底的制作完成。需要说明的是本章制作的根文件系统是能满足基本需求的,如果想运行图形界面的其他功能,可以自行移植,推荐使用我们在第九章Linux图形界面的搭建中使用的根文件系统。
uboot、Linux kernel、rootfs这三个共同构成了一个完整的Linux系统,现在的系统至少是一个可以正常运行的系统,后面我们就可以在这个系统上完成Linux驱动开发的学习。
随着本章的结束,也宣告着本书第三篇的内容也正式结束了,第三篇是系统移植篇,重点就是uboot、Linux kernel和rootfs的移植,看似简简单单的“移植”两个字,引出的却是一篇300多页的“爱恨情仇”。授人以鱼不如授人以渔,本可以简简单单的教大家修改哪些文件、添加哪些内容,怎么去编译,然后得到哪些文件。但是这样只能看到表象,并不能深入的了解其原理,为了让大家能够详细的了解整个流程,笔者义无反顾的选择了这条最难走的路,不管是uboot还是Linux kernel,从Makefile到启动流程,都尽自己最大的努力去阐述清楚。奈何,笔者水平有限,还是有很多的细节没有处理好,大家有疑问的地方可以到正点原子论坛www.openedv.com上发帖留言,大家一起讨论学习。

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

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

相关文章

ch3_1系统总线的概念

1. 总线的基本概念 总线概念&#xff1a; 是连接各个部件的信息传输线&#xff0c;是各个部件共享的传输介质&#xff1b; 1.1 为何需要总线 总线结构便于增减 外设&#xff0c; 同时 减少了信息传输线的条数。 总线是信号的公共传输线&#xff0c; 1.2 总线上信息的传送 …

深入理解堆与优先队列

目录一、什么是堆&#xff1f;二、堆的实现2.1 上滤与下滤2.2 堆的常用操作2.3 建堆三、堆排序四、优先队列References一、什么是堆&#xff1f; 堆&#xff08;Heap&#xff09;是一种特殊的完全二叉树&#xff0c;满足性质&#xff1a;除叶节点外每个节点的值都大于等于&…

【Window 入侵排查】

Window 入侵排查1、文件的排查1.1 开机启动有无异常文件启动1.2 对系统敏感文件路径的查看1.3 查看Recent1.4 查看文件时间1.5 webshell 文件排查2、进程、端口排查2.1 查看进程2.2 进程排查2.3 使用powershell 进行查询2.4 使用WMIC 命令进行排查3、检查启动项、计划任务、服务…

全志V85X系列芯片PCB设计需要注意些什么?

全志V85X &#xff08;包括V853、V853S、V851S、V851SE等&#xff09;是一颗面向智能视觉领域推出的新一代高性能、低功耗的处理器SOC&#xff0c;可广泛用于智能门锁、智能考勤门禁、网络摄像头、行车记录仪、智能台灯等智能化升级相关行业。V85X 集成ARM Cortex-A7和RISC-V E…

一个跨平台执行外部命令的C#开源库

更多开源项目请查看&#xff1a;一个专注推荐.Net开源项目的榜单 对于我们程序员来说&#xff0c;在日常开发项目中&#xff0c;调用外部的命令是非常常见的&#xff0c;比如调用批处理命令、调用其他应用&#xff0c;这里面就涉及到进程的通讯、管理、启动、取消等一些操作&am…

Spring Native打包本地镜像,无需通过Graal的maven插件buildtools

简介 在文章《GraalVM和Spring Native尝鲜&#xff0c;一步步让Springboot启动飞起来&#xff0c;66ms完成启动》中&#xff0c;我们介绍了如何使用Spring Native和buildtools插件&#xff0c;打包出本地镜像&#xff0c;也打包成Docker镜像。本文探索一下&#xff0c;如果不通…

一文细说Linux Out Of Memory机制

有时候我们会发现系统中某个进程会突然挂掉&#xff0c;通过查看系统日志发现是由于 OOM机制 导致进程被杀掉。 今天我们就来介绍一下什么是 OOM机制 以及怎么防止进程因为 OOM机制 而被杀掉。 什么是OOM机制 OOM 是 Out Of Memory 的缩写&#xff0c;中文意思是内存不足。而…

【CLYZ集训】人人人数【数学】

思路&#xff1a; 先转转转&#xff0c;把答案变成求每种数的出现次数都小于i的方案书除以Cnm−1mC_{n m - 1}^{m}Cnm−1m​ 对于每个1到m中的数&#xff0c;设每个数的出现次数为xi&#xff0c;则所有x加起来要等于m&#xff0c;且都小于i。 容斥&#xff0c;设其中k个不小于…

目标检测算法——YOLOV8——算法详解

一、主要贡献 主要的创新点&#xff1a;其实到了YOLOV5 基本创新点就不太多了&#xff0c;主要就是大家互相排列组合复用不同的网络模块、损失函数和样本匹配策略。 Yolo v8 主要涉及到&#xff1a;backbone 使用C2f模块&#xff0c;检测头使用了anchor-free Decoupled-head&a…

HTB_Unified_log4j_jndi注入mongodb修改用户hash

文章目录信息收集漏洞复现漏洞验证漏洞利用提权信息收集 nmap -sV -v 这次扫描时间很长&#xff0c;因为默认只扫 1000 个常用端口&#xff0c;如果扫到大端口就会自动扫描全端口&#xff0c;可以自行加速 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.3 (…

Markdown语法-从基础到进阶

时代在进步&#xff0c;越来越多的人和软件开始使用Markdown进行文字编辑&#xff0c;其编辑方便性让很多人爱不释手。但是&#xff0c;不可避免的问题是&#xff0c;在编辑的时候&#xff0c;经常会需要去google,毕竟&#xff0c;习惯了office的可视化操作符号&#xff0c;很多…

在成都Java培训班学习五个多月有用吗?

不知道“有用”的标准是什么&#xff0c;是能入行上岗工作&#xff0c;还是想只通过几个月的培训一跃成为资深开发攻城狮&#xff1f;这里不得不给大家泼瓢冷水&#xff0c;短期培训能让你对口上岗工作就很不错了&#xff1b;想要成为技术大佬&#xff1f;大学里面四年都没能让…

2023年南京Java培训机构排行榜上线,犹豫的小伙伴们看过来!

2022年&#xff0c;JRebel发布了《2022年Java发展趋势和分析》&#xff0c;它通过调研问卷的方式总结的报告&#xff0c;涉及了不同国家、不同岗位、不同公司规模、不同行业&#xff0c;相对来说&#xff0c;该调查报告是有一定参考意义的。数据显示&#xff0c;Java这一语言在…

使用Chisel搭建Systolic Array

最近听到非常多人吹Chisel&#xff0c;为了方便快速做算法实现&#xff0c;就去尝试学了下&#xff0c;发现确实很香&#xff0c;有种相见恨晚的感觉。今天是使用Chisel搭建个脉动阵列&#xff08;Systolic Array, SA&#xff09;[1]&#xff0c;脉动阵列是神经网络中最基础也是…

用递归玩转简单二叉树

前言&#xff1a; 数据结构学到二叉树&#xff0c;就进入到了有难度的部分了&#xff0c;但难度对应着重要性&#xff0c;其重要性也不言而喻了。这节我会介绍用C语言实现递归方法的二叉树的一些重要基本功能&#xff0c;在二叉树中又属于基础知识&#xff0c;有需要的各位必须…

下载CleanMyMac X有什么好处?最新版本有哪些新功能

CleanMyMac X 是一款先进的、集所有功能于一身的实用系统清理工具&#xff0c;它能帮助保持您的Mac保持清洁。只需两个简单的点击&#xff0c;就可以删除无用的文件&#xff0c;以节省您宝贵的磁盘空间。CleanMyMac X可以流畅地与系统性能相结合&#xff0c;清洁不需要的语言、…

EasyCVR新增角色分配分组功能的使用及注意事项

我们在此前的文章中分享过关于EasyCVR分组功能的更新&#xff0c;具体可以查看这篇文章&#xff1a;AI云边端EasyCVR平台新功能解析&#xff1a;支持为角色选择多级分组。今天我们来为大家介绍一下&#xff0c;新功能在配置时需要注意的事项。1、首先我们先简单回顾一下老版本的…

【Js】语法糖之数组解构和拆包表达式

文章目录数组结构拆包表达式来源数组结构 在ES5中&#xff1a;如果计划从数组中提取特定元素&#xff0c;就需使用元素的索引&#xff0c;并将其保存到变量之中。 在ES6中&#xff1a;新增数组解构功能&#xff0c;以简化获取数组中数据的过程。 数组解构采用了数组字面量的…

【SpringCloud复习巩固】Sentinel

sentinel 链接&#xff1a;https://pan.baidu.com/s/1lLJKBSDJNJgW5Lbru6NYrA 提取码&#xff1a;ut3g 目录 一.初识Sentinel 1.1雪崩问题及其解决方案 1.2认识Sentinel 1.3安装Sentinel控制台 1.4微服务整合sentinel 二.限流规则 2.1簇点链路 2.2流控规则 2.3流控效果…

从0~1实现 单体或微服务下 实现订单未支付超时取消功能 方案(2)-rocketmq 延迟队列方案 完整设计和源码

从0~1实现 单体或微服务下 订单未支付超时取消功能 方案&#xff08;1&#xff09;-java delayquene 注册中心(zookeeper/nacos)高可用方案从0~1实现 单体或微服务下 订单未支付超时取消功能 方案&#xff08;2&#xff09;-rocketmq 延迟队列方案 场景说明 我们日常接触的电…