ARM busybox 的移植实战2

news2024/9/21 10:55:26

一、busybox 源码分析1

1、源码目录梳理

在这里插入图片描述


2、整个程序入口的确认

(1) 分析一个程序,不管多庞大还是小,最好的路线都是 按照程序运行时的逻辑顺序来。所以找到一个程序的入口至关重要。


(2) 学 C 语言的时候都知道,程序的主函数 main 函数就是整个程序的入口。这种情况适应于操作系统下工作的应用程序 的情况。


(3) 在 uboot 和 linux kernel 这两个大的 C 语言的项目中,main 函数都没有,都不是入口。在我们这种裸机程序中,入口不是 main 函数,而是由链接脚本来指定的。


(4) busybox 是 linux 启动起来后工作的一个应用程序,因此其中必然有 main 函数,而且 main 就是入口。


3、busybox 中 main 函数全解析

(1) busybox 入口就是 main 函数,其中有很多个 main,但是只有一个起作用了,其他的是没起作用的。真正的 busybox 工作时的入口是 libbb/appletlib.c 中的 main 函数。

在这里插入图片描述


(2) busubox 中有很多 xxx_main 的函数,这些 main 函数每一个都是 busybox 支持的一个命令的真正入口。

譬如 ls_main 函数,就是 busybox 当作 ls 函数使用时的入口程序。

在这里插入图片描述


(3) ls 或者 cd 等命令,其实都是 busybox 一个程序,但是实际执行时的效果却是各自的效果。busybox 是如何实现一个程序化身万千还能各自工作的?答案就是 main 转 xxx_main。

在这里插入图片描述

也就是说,busybox 每次执行时,都是先执行其 main,在 main 函数中识别(靠 main 函数的传参 argv[0] 来识别)我们真正要执行的函数(譬如 ls),然后去调用相应的 xxx_main(譬如 ls_main)来具体实现这个命令。

在这里插入图片描述


二、busybox源码分析2

1、inittab 解析与执行

(1) inittab 的解析是在 busybox/init/init.c/init_main 函数中。

在这里插入图片描述


(2) 执行逻辑是:先通过 parse_inittab 函数解析 /etc/inittab(解析的重点是,将 inittab 中的各个 action 和 process 解析出来),然后后面先直接执行 sysinit 和 wait 和 once(注意这里只执行一遍),然后在 while(1) 死循环中去执行 respwan 和 askfirst。

在这里插入图片描述

在这里插入图片描述


2、pwd 命令执行路径分析

(1) 根据上节讲的,我们在 busybox 命令行下执行 pwd 命令时,实际执行的是 pwd_main 这个函数。

在这里插入图片描述


3、busybox 的体积优势原理

(1) busybox 实际上就是把 ls、cd、mkdir 等很多个 linux 中常用的 shell 命令集成在一起了。集成在一起后有一个体积优势:就是 busybox 程序的大小,比 busybox 中实现的那些命令的大小加起来 要小很多。


(2) busybox 体积变小的原因主要有 2 个:

第一个是 busybox 本身提供的 shell 命令是阉割版的(busybox 中的命令支持的参数选项比发行版中要少,譬如 ls 在发行版中可以有几十个 -x 选项,但是在 busybox 中只保留了几个常用的选项,不常用的都删除掉了);

第二个是 busybox 中因为所有的命令的实现代码都在一个程序中实现,而各个命令中有很多代码函数都是通用的(譬如 ls 和 cd、 mkdir 等命令都会需要去操作目录,因此在 busybox 中实现目录操作的函数,就可以被这些命令共用),共用会降低重复代码出现的次数,从而减少总的代码量和体积。


(3) 经过分析,busybox 的体积优势 是嵌入式系统本身的要求和特点造成的。


三、rcS 文件介绍1

0、/etc/init.d/rcS

/etc/init.d/rcS 文件,是 linux 的运行时配置文件中最重要的一个,其他的一些配置都是由这个文件引出来的。这个文件可以很复杂,也可以很简单,里面可以有很多的配置项。

这是 ubuntu 发行版的 rcS 文件:

root@ubuntu:# cat /etc/init.d/rcS
#! /bin/sh
#
# rcS
#
# Call all S??* scripts in /etc/rcS.d/ in numerical/alphabetical order
#

exec /etc/init.d/rc S
root@ubuntu:# vim /etc/init.d/rc

在这里插入图片描述


这是 busybox 最简单的 rcS 文件:

在这里插入图片描述


1、PATH=xxx

在这里插入图片描述

(1) 首先从 shell 脚本的语法角度分析,这一行定义了一个变量PATH,值等于后面的字符串。


(2) 后面用 export 导出了这个 PATH,那么 PATH 就变成了一个环境变量。


(3) PATH 这个环境变量,是 linux 系统内部定义的一个环境变量,含义是操作系统去执行程序时,会默认到 PATH 指定的各个目录下去寻找。

如果找不到,就认定这个程序不存在,如果找到了就去执行它。将一个可执行程序的目录导出到 PATH,可以让我们不带路径 来执行这个程序。


(4) rcS 中为什么要先导出 PATH?就是因为我们希望一旦进入命令行时,PATH 环境变量中就有默认的 /bin /sbin /usr/bin /usr/sbin 这几个常见的可执行程序的路径,这样我们进入命令行后就可以 ls、 cd 等直接使用了。


(5) 为什么我们的 rcS 文件还没添加,系统启动就有了 PATH 中的值?原因在于 busybox 自己用代码硬编码,为我们导出了一些环境变量,其中就有 PATH。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


2、runlevel=

在这里插入图片描述

(1) runlevel 也是一个 shell 变量,并且被导出为环境变量。


(2) runlevel 这个环境变量到底有什么用?

在这里插入图片描述


(3) runlevel=S 表示将系统设置为单用户模式。


3、umask=

在这里插入图片描述

(1) umask 是 linux 的一个命令,作用是设置 linux 系统的 umask 值。

(2) umask 值决定当前用户在创建文件时的默认权限。


4、mount -a

在这里插入图片描述

(1) mount 命令是用来挂载文件系统的。


(2) mount -a 是挂载所有的应该被挂载的文件系统,在 busybox 中 mount -a 时,busybox 会去查找一个文件 /etc/fstab 文件,这个文件按照一定的格式列出来所有应该被挂载的文件系统(包括了虚拟文件系统)

ubuntu 发行版的 /etc/fstab:

在这里插入图片描述


busybox 的 fstab:

在这里插入图片描述


四、 rcS文件实战1

1、PATH&runlevel

在 rootfs 根文件系统创建 init.d 目录,然后拷贝 rcS 到 init.d 目录下:

在这里插入图片描述

root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# cd init.d/
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc/init.d# vim rcS 
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc/init.d# 
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc/init.d# cat rcS 
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin

runlevel=S
prevlevel=N

umask 022

export PATH runlevel prevlevel

mount -a

root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc/init.d#  

拷贝 fstab 文件到 etc 目录下:

在这里插入图片描述

root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# ls
fstab  init.d  inittab
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# vim fstab 
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# cat fstab 
# /etc/fstab: static file system information.
#
# Use 'vol_id --uuid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# 	<file system> 	<mount point> 	<type> 	<options> 	<dump> 	<pass>
	proc 			/proc 			proc 	defaults 	0 		0
	sysfs 			/sys 			sysfs 	defaults 	0 		0
	tmpfs 			/var 			tmpfs 	defaults 	0 		0
	tmpfs 			/tmp 			tmpfs 	defaults 	0 		0
	tmpfs 			/dev 			tmpfs 	defaults 	0 		0

root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# 

(1) 我们实战发现,rcS 文件明明存在,但是却提示不存在。问题原因就是,rcS 文件在 windows 下创建的,行尾换行符为 ‘\r\n’,多了点东西。但是因为 ubuntu 中的 vi 对行尾做了优化,所以在 ubuntu 中是看不出来多了东西的。但是在 securecrt 下一看就发现,每一行末尾多出来了一个^M。

在这里插入图片描述

在这里插入图片描述


手动修改删除多余的 ^M。

重新启动,不再报错 rcS 找不到。

在这里插入图片描述


(2) 这个故事告诉我们:shell 脚本文件如果格式不对,运行时可能会被提示文件不存在。


(3) 扩展讲一个:有时候一个应用程序执行时,也会提示文件不存在,问题可能是这个程序所调用的一个动态链接库找不到。


开发板的 runlevel 无效:

在这里插入图片描述

正常的 ubuntu 发行版的 runlevel 命令能正常工作:

在这里插入图片描述


在这里插入图片描述


(4) 测试结果:PATH 本来在 busybox 中就已经用代码导出过了,所以 rcS 中再次导出没有任何明显的现象,因此看不出什么差别;runlevel 实际执行结果一直是 unknown,问题在于 busybox 并不支持 runlevel 这个特性


2、umask 测试

在这里插入图片描述

(1) umask是022的时候,默认touch创建一个文件的权限是644。

(2) umask是044的时候,默认touch创建一个文件的权限是622。

(3) umask是444的时候,默认touch创建一个文件的权限是222。

总结:umask 的规律就是:umask 值和默认创建文件的权限值加起来,是666.


3、mount 测试

在这里插入图片描述

(1) 挂载时全部出错:

mount: mounting proc on /proc failed: No such file or directory
mount: mounting sysfs on /sys failed: No such file or directory
mount: mounting tmpfs on /var failed: No such file or directory
mount: mounting tmpfs on /tmp failed: No such file or directory
mount: mounting tmpfs on /dev failed: No such file or directory

(2) 原因是因为,根文件系统中找不到挂载点。

所谓挂载点, 就是我们要将目标文件系统(当然这里都是虚拟文件系统)挂载到当前文件系统中的某一个目录中,这个目录就是挂载点。


(3) 解决方案就是,自己在制作的 rootfs 根目录下 创建这些挂载点目录即可。

root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs# mkdir proc sys tmp var dev
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs# ls
bin  dev  etc  linuxrc  proc  sbin  sys  tmp  usr  var
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs# 

在这里插入图片描述


(4) 验证是否挂载成功,可以看挂载时输出信息;还可以启动后去看 proc 和 sys 文件夹,如果有文件出现则证明挂载成功了,如果没东西就证明失败了。

在这里插入图片描述

在这里插入图片描述


五、rcS文件介绍2

1、mdev

(1) mdev 是 udev 的嵌入式简化版本,udev/mdev 是用来配合 linux 驱动工作的一个应用层的软件,udev/mdev 的工作就是配合 linux 驱动生成相应的 /dev 目录下的设备文件。


(2) 因为这个问题涉及到驱动,因此详细讲解要等到驱动部分。这里我们只是通过一些直观的现象来初步理解 udev/mdev 的工作效果。


(3) 在 rcS 文件中没有启动 mdev 的时候,/dev 目录下启动后是空的;在 rcS 文件中添加上 mdev 有关的 2 行配置项后,再次启动系统后发现,/dev 目录下生成了很多的设备驱动文件。

在这里插入图片描述


(4) /dev 目录下的设备驱动文件就是 mdev 生成的,这就是 mdev 的效果和意义。

在这里插入图片描述

在这里插入图片描述


2、hostname

(1) hostname 是 linux 中的一个 shell 命令。命令(hostname xxx)执行后,可以用来设置当前系统的主机名为 xxx,直接 hostname 不加参数,可以显示当前系统的主机名。


(2)

/bin/hostname -F /etc/sysconfig/HOSTNAME

-F 来指定一个主机名配置文件(这个文件一般文件名叫 hostname 或者 HOSTNAME)

在这里插入图片描述


在这里插入图片描述


3、ifconfig

(1) 有时候我们希望开机后进入命令行时,ip 地址就是一个指定的 ip 地址(譬如192.168.1.30),这时候就可以在 rcS 文件中:

ifconfig eth0 192.168.1.30

在这里插入图片描述

在这里插入图片描述


六、profile 文件和用户登录理论

1、profile 文件添加

(1) 之前添加了 /bin/hostname/etc/sysconfig/HOSTNAME 文件中定义了一个 hostname(aston210),实际效果是:命令行下 hostname 命令查到的 host 名字确实是 aston210。但是问题就是,命令行的提示符是没有显示的。


(2) 这个问题的解决就要靠 profile 文件。将提供的 profile 文件放入 /etc/ 目录下即可。

root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs# cd etc/
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# 
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# cp /mnt/hgfs/linux_win_shared/etc/profile .
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# ls
fstab  init.d  inittab  profile  sysconfig
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# cat profile 
# Ash profile
# vim: syntax=sh

# No core files by default
ulimit -S -c 0 > /dev/null 2>&1

USER="`id -un`"
LOGNAME=$USER
PS1='[\u@\h \W]\# '
PATH=$PATH

HOSTNAME=`/bin/hostname`

export USER LOGNAME PS1 PATH


root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# 

在这里插入图片描述


(3) 添加了 profile 之后的实验现象:命令行提示符前面显示:[@aston210 ]#

在这里插入图片描述

结论是:

第一,profile 文件起了作用,hostname 显示出来了。

第二,还有个问题,登录用户名没显示出来。

原因就是我们直接进入了命令行,而没有做登录。等我们添加了用户登录功能,并且成功登陆后这个问题就能解决。


(4) profile 文件工作原理是:profile 文件也是被 busybox(init 进程)自动调用的,所以是认名字的。


2、如何看到用户登录界面

(1) linux 中有一个原则就是:用一个小程序来完成一个功能。如果我们产品确实需要很复杂的综合型的功能,我们倾向于先使用很多个小程序完成其中的一个功能,然后再将这些小程序集成起来完成整个大功能的产品。


(2) 这种集成很多个小程序来完成一个大的功能,有很多种技术实现。譬如 shell 脚本,还有一些别的技术,譬如 linux 启动中的 inittab。


(3) 因为我们之前 intttab 中有一个配置项 ::askfirst:-/bin/sh,这个配置项作用就是:当系统启动后,就去执行 /bin/sh,执行这个就会出现命令行。
因此我们这样的安排就会直接进入命令行,而不会出现登录界面。


(4) 我们要出现登录界面, 就不能直接执行 /bin/sh,而应该执行一个负责出现登录界面,并且负责管理用户名和密码的一个程序,busybox 中也集成了这个程序(就是 /bin/login 和 /sbin/gettty),因此我们要在 inittab 中用 /bin/login 或者 /sbin/getty ,去替代 /bin/sh。


3、用户名和密码的设置

(1) 用户名和密码的设置,是和登录程序有关联的,但是 /bin/login和 /sbin/getty 在用户名和密码的管理上是一样的。 其实常见的所有的 linux 系统的用户名和密码的管理几乎都是一样的。


(2) 密码一般都是用加密文字的,而不是用明文。意思就是系统中的密码肯定是在系统中的一个专门用来存密码的文件中存储的,用明文存密码有风险,因此 linux 系统都是用密文来存储密码的。关于密文密码的使用下节课实践时会详细讲。


七、用户登录实战

1、添加 /bin/login 到 sysinit

(1) 在 inittab 中修改,去掉 /bin/sh,换上 /bin/login,则系统启动后出现登录界面。可以输入用户名和密码。

root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# vim inittab 
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# cat inittab 
#first:run the system script file
::sysinit:/etc/init.d/rcS
#::askfirst:-/bin/sh
::sysinit:/bin/login
::ctrlaltdel:-/sbin/reboot
#umount all filesystem
::shutdown:/bin/umount -a -r
#restart init process
::restart:/sbin/init

root@ubuntu:/home/aston/workspace/porting_x210/rootfs/rootfs/etc# 

在这里插入图片描述


(2) 实验现象:成功出现用户登录界面,但是死活密码不对。

成功出现登陆界面:

在这里插入图片描述


2、添加 passwd 和 shadow 文件

(1) 为什么用户名和密码不对?因为我们根本没有为 root 用户设置密码。


(2) linux 系统中用来描述用户名和密码的文件是 passwd 和 shadow 文件,这两个文件都在 etc 目录下。passwd 文件中存储的是用户的密码设置,shadow 文件中存储的是加密后的密码。


(3) 我们直接复制 ubuntu 系统中的 /etc/passwd 和 /etc/shadow 文件到当前制作的 rootfs 目录下,然后再做修改即可。

在这里插入图片描述


同理,删除 shadow 文件除了 root 之外的 其他用户密码:

在这里插入图片描述


(4) /etc/passwd 和 /etc/shadow 修改好后,shadow 中默认有一个加密的密码口令,这个口令和你拷贝的shadow本身有关,像我的 ubuntu 中, root 用户的密码就是 root,因此复制过来后登陆时的密码还是 root。

在这里插入图片描述


3、重置密码实践

(1) ubuntu 刚装好的时候,默认登录是用普通用户登录的,默认 root 用户是关闭的。普通用户的密码是在装系统的时候设置的,普通用户登陆后可以使用 su passwd root 给 root 用户设置密码,设置了密码后,root 用户才可以登录。


(2) 其实这个原因就是,root 用户在 /etc/shadow 文件中加密口令是空白的。所以是不能登录的。


(3) busybox 中因为没有普通用户,所以做法是:默认 root 用户如果加密口令是空的,则默认无密码直接登录。

等我们登陆了之后,还是可以用 passwd root 给 root 用户设置密码。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


解决报错:-sh:can’t access tty; job control turned off

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


(4) 平时有时候我们忘记了自己的操作系统的密码,怎么办?

有一种解决方法就是,用其他系统(WindowsPE 系统或者 ubuntu 的单用户模式等···)来引导启动,启动后挂载到我们的硬盘上,然后找到 /etc/shadow 文件,去掉密文密码后保存。然后再重启系统后密码就没了。


4、getty 实战

(1) 大家后面做项目会发现,inittab 中最常见的用于登录的程序不是 /bin/login,反而是 /sbin/getty。


(2) 这两个的差别不详,但是在 busybox 中这两个是一样的。这两个其实都是 busybox 的符号链接而已。因此不用严格区分这两个。


(3) 我们可以在 inittab 中,用 getty 替换 login 程序来实现同样的效果。

在这里插入图片描述

重启登录效果没有差别:

在这里插入图片描述


八、动态链接库的拷贝

1、静态编译链接 helloworld 程序并执行

(1) 任务:自己写一个 helloworld 程序,然后交叉编译连接,然后丢到开发板根文件系统中,开机后去运行。


(2) C 程序如果使用 gcc 来编译,则可以在主机 ubuntu 中运行,但是不能在开发板运行;

要在开发板运行,需要用 arm-linux-gcc 来交叉编译,但是这时候就不能在主机 ubuntu 中运行了。

我们可以用 file xx 命令来查看一个 elf 可执行程序是哪个架构的。

在这里插入图片描述


(3) 静态链接:

arm-linux-gcc hello.c -o hello_satic -static

在这里插入图片描述

制作 Makefile 进行程序编译:

在这里插入图片描述


(4) 实验结果:静态编译连接后生成的 hello_satic 已经可以成功运行。

在这里插入图片描述


2、动态编译连接helloworld程序并执行

(1) 动态链接:

arm-linux-gcc hello.c -o hello_dynamic

(2) 实验结果:-sh: ./hello_dynamic: not found 。运行时提示找不到程序。

在这里插入图片描述


(3) 错误分析:动态链接的 hello 程序中调用到了 printf 函数,而 printf 函数在动态连接时,要在运行时环境(开发板的 rootfs)中,去寻找对应的库文件(开发板 rootfs 中部署的动态链接库中,包含了 printf 函数的那个库文件)。如果找到了,则 printf 函数就会被成功解析,然 后hello_dynamic 程序就会被执行;如果找不到,则程序就不能被执行,命令行会提示错误信息 -sh: ./hello_dynamic: not found。


(4) 解决方案:将 arm-linux-gcc 的动态链接库文件,复制到开发板 rootfs 的 /lib 目录下即可解决。


3、找到并复制动态链接库文件到rootfs中

(1) 我们用的 arm-2009q3 这个交叉编译工具链的动态链接库,在 /usr/local/arm/arm-2009q3/arm-none-linux-gnueabi/libc/lib 目录下。

其他的一些交叉编译工具链中动态链接库的目录不一定在这里,要去找一下。找的方法就是 find。

在这里插入图片描述


(2) 复制动态链接库,到 roots/lib 目录下。复制时要注意参数用 -rdf,主要目的就是符号链接复制过来还是符号链接。
复制命令:

cp ../lib/ /home/aston/workspace/porting_x210/rootfs/rootfs/. -rfd

在这里插入图片描述

在这里插入图片描述

动态库的大小总共 3.8M:

在这里插入图片描述


(3) 现在再去测试 ./hello_dynamic 看看是否可以运行,实验结果是可以运行。

在这里插入图片描述


4、使用strip工具去掉库中符号信息

动态链接库 so 文件中,包含了调试符号信息,这些符号信息在运行时是没用的(调试时用的),这些符号会占用一定空间。

在传统的嵌入式系统中,flash 空间是有限的,为了节省空间常常把这些符号信息去掉。这样节省空间并且不影响运行。

去掉符号命令:

arm-linux-strip *so*

实际操作后发现库文件由 3.8M 变成了 3.0M,节省了 0.8M 的空间。

在这里插入图片描述


九、开机自启动与主流rcS格式介绍

1、修改 rcS 实现开机自启动

(1) 开机自启动指的是,让一些应用程序能够开机后自动执行。


(2) 开机自启动的实现原理就是,在开机会自动执行的脚本 rcS 中,添加上执行某个程序的语句代码即可。

在这里插入图片描述


2、前台运行与后台运行

(1) 程序运行时占用了当前的控制台,因此这个程序不结束我们都无法使用控制台,这就叫前台运行。默认执行程序就是前台运行的。


(2) 后台运行就是让这个程序运行,并且同时让出控制台。这时候运行的程序还能照常运行,而且还能够不影响当前控制台的使用。


(3) 让一个程序后台运行的方法就是 ./xxx &


3、实际开发中 rootfs 的 rcS 是怎样的

(1) 我们以 X210 开发板九鼎科技做的 rootfs 中 rcS 部分来分析。


(2) 分析 inittab 发现:sysinit 时执行 rcS,shutdown 时执行 rcK。

在这里插入图片描述


(3) 分析 /etc/init.d/rcS 和 rcK 文件发现,rcS 和 rcK 都是去遍历执行 /etc/init.d/ 目录下的 S 开头的脚本文件,区别是 rcS 传参是 start,rcK 传参是 stop。


(4) 由此可以分析出来,正式产品中的 rcS 和 rcK 都是一个引入,而不是真正干活的。真正干活的配置脚本是 /etc/init.d/S??*。这些文件中肯定有一个判断参数是 start 还是 stop,然后 start 时去做一些初始化,stop 时做一些清理工作。


十、制作 ext2 格式的镜像并烧录启动

1、确定文件夹格式的rootfs可用

(1) 设置 bootargs 为 nfs 启动方式,然后从主机 ubuntu 中做好的文件夹格式的 rootfs 去启动,然后看启动效果,作为将来的参照物。


2、动手制作ext2格式的镜像

在这里插入图片描述


(1)

# bs=1024 count=10240   相乘就是 10MB.
dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240
losetup  /dev/loop1 rootfs.ext2
mke2fs -m 0 /dev/loop1 10240
mount -t ext2 /dev/loop1 ./ext2_rootfs/

在这里插入图片描述


(2) 向 ./rootfs 中复制内容

root@ubuntu:/home/aston/workspace/porting_x210/rootfs#cd ext2_rootfs/
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/ext2_rootfs# ls
lost+found
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/ext2_rootfs# 
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/ext2_rootfs# 
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/ext2_rootfs# cp ../rootfs/* . -rf
root@ubuntu:/home/aston/workspace/porting_x210/rootfs/ext2_rootfs# ls

在这里插入图片描述


(3) 回到 ext2_rootfs 的上级路径,卸载 ext2_rootfs 根文件系统:

umount /dev/loop1
losetup -d /dev/loop1

在这里插入图片描述


(4)完成后得到的rootfs.ext2就是我们做好的rootfs镜像。拿去烧录即可。

cp rootfs.ext2   /mnt/hgfs/linux_win_shared/. -rf

拷贝 rootfs.ext2 文件,到 Windows 主机:

在这里插入图片描述

将 rootfs.ext2 文件拷贝到 Windows 的 fastboot 软件目录中:

在这里插入图片描述


3、烧录镜像并设置合适的bootargs

(1) 使用 fastboot 烧录制作好的 rootfs.ext2 到开发板 inand 中

fastboot flash system rootfs.ext2

烧录完成后重启系统

  1. 开发板进入 fastboot 模式:
    在这里插入图片描述

  2. 在 Windows fastboot 这边输入命令:
    在这里插入图片描述


(2) 设置bootargs为:

set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext2

在这里插入图片描述


(3) 启动后发现,现象和之前 nfs 方式启动挂载 rootfs 后一样的,至此 rootfs 制作实验圆满完成。

在这里插入图片描述


源自朱有鹏老师.

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

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

相关文章

机器学习算法 随机森林

文章目录 一、概述1.1 集成学习1.2 决策树1.3 随机森林 二、Sklearn中的随机森林2.1 分类树API2.2 参数 2.2 回归树API2.2.1 重要参数 2.3 随机森林调参 三、总结 一、概述 1.1 集成学习 多个模型集成成为的模型叫做集成评估器&#xff08;ensemble estimator&#xff09;&am…

车载软件架构——闲聊几句AUTOSAR BSW(二)

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 我特别喜欢一个老话,来都来了。我觉得这就是松弛感,既然来了,就开心起来吧!松弛感来自于专注,焦虑不是靠克服的,是靠忘记的,当你很专注做一件事的时候…

HNCTF-re部分复现

目录 [HNCTF 2022 WEEK3]Help_Me! [HNCTF 2022 WEEK3]Whats 1n DLL? [HNCTF 2022 WEEK4]ez_maze 这几天在做HNCTF的week3&#xff0c;week4部分&#xff0c;学到了一些不知道的没接触过的东西&#xff0c;所以记录一下 [HNCTF 2022 WEEK3]Help_Me! 题目下载&#xff1a;下…

onnx笔记2:onnx操作实例

1. 介绍 本文以yolov5s模型,演示对yolov5s.onnx模型文件的读取,修改等操作 2. onnx操作 2.1 获取数据 (1) 案例1 :读取weights数据 比如获取yolov5s.onnx第一个Conv的weights数据。 点击左侧第一个Conv, 右侧INPUTS下面的W点开+号,可以看到该Conv的weight的name为m…

MySQL --- 主从复制、读写分离

一、MySQL主从复制 MySQL数据库默认是支持主从复制的&#xff0c;不需要借助于其他的技术&#xff0c;我们只需要在数据库中简单的配置即可。接下来&#xff0c;我们就从以下的几个方面&#xff0c;来介绍一下主从复制 1.1、介绍 MySQL主从复制是一个异步的复制过程&#xff0c…

linux 安装 oracle 11g

linux 安装 oracle 11g 1、下载oracle 11g (11.2.0.1.0)1.1、Oracle Database 11.2.0.1.01.2、Oracle Database Grid Infrastructure 11.2.0.1.01.3、客户端 2、安装文档3、安装前准备3.1、建立用户和用户组3.2、sysctl3.3、security limits3.4、其他设置3.5、创建安装目录3.6、…

SpringBootWeb请求响应

目录 前言 1. 请求 1.1 Postman 1.1.1 介绍 1.1.2 安装 1.2 简单参数 1.2.1 原始方式 1.2.2 SpringBoot方式 1.2.3 参数名不一致 小结 1.3 实体参数 1.3.1 简单实体对象 1.3.2 复杂实体对象 1.4 数组集合参数 1.4.1 数组 1.4.2 集合 1.5 日期参数 1.6 JSON参…

液压轴位置闭环控制(比例伺服阀应用)

液压阀的基础知识请参看下面的博客文章: PLC液压控制系列之比例流量阀结构分析_RXXW_Dor的博客-CSDN博客比例流量阀液压同步控制的PID闭环调节可以参看下面这篇博文三菱FX3U-PLC 前馈+PID闭环调节实现液压同步控制(比例换向阀)_RXXW_Dor的博客-CSDN博客液压控制系统在工业现…

plt got

小白垃圾笔记而已&#xff0c;不建议阅读。 本来是仅仅写的文字&#xff0c;因为我并没有调试出来&#xff0c;在群里问了师傅后才知道是因为我开起了 full Pelro保护。 按理说应该关闭的&#xff0c;或者开启部分也可以。gcc -z lazy -o test test.c // 部分开启, 即…

跨平台跨端的登录流程及其安全设计

跨平台跨端的登录流程及其安全设计 目录 跨平台跨端的登录流程及其安全设计 一、登录流程 1.1、登录流程时序图 1.2、三方App 登录 1.3、请求的路由守卫 二、注册流程 2.1、注册流程时序图 2.2、多因素认证 2.3、自动跳转登录页面 三、涉及的技术与安全 3.1、用户…

基于深度学习的图片上色(Opencv,Pytorch,CNN)

文章目录 1. 前言2.图像格式&#xff08;RGB&#xff0c;HSV&#xff0c;Lab&#xff09;2.1 RGB2.2 hsv2.3 Lab 3. 生成对抗网络&#xff08;GAN&#xff09;3.1 生成网络&#xff08;Unet&#xff09;3.2 判别网络&#xff08;resnet18&#xff09; 4. 数据集5. 模型训练与预…

OSCP-Medjed(重置用户密码、mysql写webshell、可写文件替换提权)

目录 扫描 FTP WEB 提权 扫描 FTP 尝试登录到FTP服务器,该服务器位于端口30021 使用Filezilla,并能够浏览文件。那里有一些配置文件,但找不到任何值得注意的东西,不能写入目录。

成长之路---C语言笔记(构造类型之字符数组及字符串函数)

决不要停止自学&#xff0c;也不要忘记&#xff0c;不管你已经学到了多少东西&#xff0c;已经知道了多少东西&#xff0c;知识和学问是没有止境的一鲁巴金 字符数组 字符数组就是用于存放字符型数据的数组。在C语言中&#xff0c;字符串是作为字符数组来处理的&#xff0c;没有…

redis设计与实现读书笔记(2)

今天看的是关于单机数据库&#xff0c;RDB持久化以及AOF持久化的内容。 关于单机数据库 1.默认数据库数量 redis的服务器默认是会创建16个数据库&#xff0c;每个客户端访问的时候都要指定自己的目标数据库。 select可以切换目标数据库。 注意事项 到目前为止&#xff0c…

部署YUM仓库

文章目录 1. YUM仓库服务1.1 YUM概述1.1 准备安装源 2.制作YUM源2.1制作ftp源2.2 国内在线yum源2.3 本地源与在线源同时使用 3.yum软件包的下载方式4.yum的常用操作命令 1. YUM仓库服务 1.1 YUM概述 yum是一个基于RPM包&#xff08;是Red-Hat Package Manager红帽软件包管理器…

【Android入门到项目实战-- 6.1】—— 如何申请用户权限

目录 一、申请权限 1、布局文件 2、MainActivity类 3、AndroidManifest文件 你在使用安卓APP时可能经历过以下场景&#xff1a;使用APP的拍照功能时需要你授权使用相机。那么APP是如何完成申请权限功能的&#xff1f; 访问&#xff1a;https://developer.android.google.cn/…

ERTEC200P-2 PROFINET设备完全开发手册(9-2)

9.2 运行AC1/AC4参考代码 修改源代码usrapp_cfg.h的宏为 #define EXAMPL_DEV_CONFIG_VERSION 44 编译后下载到评估板运行AC4示例程序 在TIA中导入GSDML-V2.35-Siemens-ERTEC200pApp44-20210623.xml。新建项目&#xff0c;添加PLC和Devkit设备。 按照如下图所示配置模块&am…

2023零基础学软考网络工程师能过吗?

网络工程师是在计算机及其相关领域中拥有一定专业技能和知识的人员&#xff0c;可以为企业或个人设计、建设和维护计算机网络系统。网络工程师的职业前景非常广阔&#xff0c;尤其是随着信息化和互联网的迅速发展&#xff0c;网络工程师的需求也越来越大。软考是国家计算机技术…

Java多线程- synchronized关键字总结

目录 多线程锁的概要 Synchronized关键字 synchronized加锁过程 synchronized锁优化 锁消除 锁粗化 多线程锁的概要 首先对于锁的条件和要点进行一个总结: 锁使用来保护代码片段的, 以保证多线程的安全性, 一次只允许一个线程执行被保护的代码.锁可以管理视图进入被保护代…

malloc的一些知识

这是一个叫malloc的家伙&#xff0c;一直勤勤恳恳帮你为所欲为的玩转系统内存。可是长路漫漫&#xff0c;唯malloc作伴&#xff0c;我却不懂它。走近malloc&#xff0c;多了解一下总没错。 可能对我们来讲&#xff0c;malloc就是void* malloc (size_t len)&#xff0c;调用就是…