【正点原子I.MX6U-MINI移植篇】rootfs移植过程详解(三)

news2024/12/25 1:07:14

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

一、BusyBox构建根文件系统

1.1 BusyBox简介

BusyBox 就是一个大的工具箱,这个工具箱里面集成了 Linux 的许多工具和命令。一般下载 BusyBox 的源码,然后配置 BusyBox,选择自己想要的功能,最后编译即可。BusyBox 可以在其官网下载到,官网地址为:https://busybox.net/,官网比较简陋,如图


在官网左侧的“Get BusyBox”栏有一行“Download Source”,点击“Download Source”即可打开 BusyBox 的下载页,如图所示:


从图可以看出,目前最新的 BusyBox 版本是 1.31.0,不过我建议大家使用我们开发板光盘里面提供的 1.29.0 版本的 BusyBox。因为笔者测试 1.29.0 版本目前还没有出现任何问题,路径为:1、例程源码->6、BusyBox 源码->busybox-1.29.0.tar.bz2,BusyBox 准备好以后就可以构建根文件系统了。

1.2 编译BusyBox构建根文件系统

一般我们在 Linux 驱动开发的时候都是通过 nfs 挂载根文件系统的,当产品最终上市开卖的时候才会将根文件系统烧写到 EMMC 或者 NAND 中。所以要在nfs 服务器目录中创建一个名为 rootfs 的子目录(名字大家可以随意起,为了方便就用了 rootfs),比如我的电脑中/home/zhiguoxin/linux/nfs就是我设置的 NFS 服务器目录,使用如下命令创建名为 rootfs 的子目录:

mkdir rootfs

创建好的 rootfs 子目录就用来存放我们的根文件系统了。

将busybox-1.29.0.tar.bz2 发送到 Ubuntu 中,存放位置大家随便选择。我这里放在/home/zhiguoxin/linux/IMX6ULL/roofts,然后使用如下命令将其解压:

tar -vxjf busybox-1.29.0.tar.bz2

解压完成以后进入到 busybox-1.29.0目录中,此目录中的文件和文件夹如图所示:

1.2.1 修改 Makefile,添加编译器

同 Uboot 和 Linux 移植一样,打开 busybox 的顶层 Makefile,添加 ARCH 和 CROSS_COMPILE的值,如下所示:

CROSS_COMPILE ?= /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
ARCH ?= arm

1.2.2 busybox中文字符支持

如果默认直接编译 busybox 的话,在使用 SecureCRT 的时候中文字符是显示不正常的,中文字符会显示为“?”,比如你的中文目录,中文文件都显示为“?”。不知道从哪个版本开始 busybox中的 shell 命令对中文输入即显示做了限制,即使内核支持中文但在 shell 下也依然无法正确显示。

所以我们需要修改 busybox 源码,取消 busybox 对中文显示的限制,打开文件busybox-1.29.0/libbb/printable_string.c,找到函数printable_string,缩减后的函数内容如下:

vi libbb/printable_string.c


主要就是禁止字符大于0X7F以后break和输出‘?’。

接着打开文件busybox-1.29.0/libbb/unicode.c,找到如下内容:

vi libbb/unicode.c


红色部分的代码就是被修改以后的,同样主要是禁止字符大于 0X7F 的时候设置为‘?’。busybox 中文字符支持跟代码修改有关的就改好了,最后还需要配置 busybox来使能 unicode 码,这个稍后我们配置 busybox 的时候在设置。

1.2.3 配置 busybox

根我们编译 Uboot、Linux kernel 一样,我们要先对 busybox 进行默认的配置,有以下几种配置选项:

  • ①、defconfig,缺省配置,也就是默认配置选项。
  • ②、allyesconfig,全选配置,也就是选中 busybox 的所有功能。
  • ③、allnoconfig,最小配置。

我们一般使用默认配置即可,因此使用如下命令先使用默认配置来配置一下 busybox:

make defconfig

busybox 也支持图形化配置,通过图形化配置我们可以进一步选择自己想要的功能,输入如下命令打开图形化配置界面:

make menuconfig

打开以后如图所示:


配置路径如下:

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

选项“Build static binary (no shared libs)”用来决定是静态编译 busybox 还是动态编译,静态编译的话就不需要库文件,但是编译出来的库会很大。动态编译的话要求根文件系统中有库文件,但是编译出来的 busybox 会小很多。这里我们不能采用静态编译!因为采用静态编译的话 DNS 会出问题!无法进行域名解析,配置如图所示:

不选择“Build static binary (no shared libs)”
继续配置如下路径配置项:

Location:
	-> Settings
		-> vi-style line editing commands

结果如图所示:

选择“vi-style line editing commands ”

继续配置如下路径配置项:

Location:
	-> Linux Module Utilities
		-> Simplified modutils

默认会选中“Simplified modutils”,这里我们要取消勾选!!结果如图所示:

取消选中“Simplified modutils”

继续配置如下路径配置项:

Location:
	-> Linux System Utilities
		-> mdev (16 kb) //确保下面的全部选中,默认都是选中的

结果如图所示:

“mdev”配置项
最后就是使能 busybox 的 unicode 编码以支持中文,配置路径如下:

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

结果如图所示:

 中文支持

busybox 的配置就到此结束了,大家也可以根据自己的实际需求选择配置其他的选项,不过对于初学者笔者不建议再做其他的修改,可能会出现编译出错的情况发生。

1.2.4 编译 busybox

配置好 busybox 以后就可以编译了,我们可以指定编译结果的存放目录,我们肯定要将编译结果存放到前面创建的 rootfs 目录中,输入如下命令:

make
make install CONFIG_PREFIX=/home/zhiguoxin/linux/nfs/rootfs

COFIG_PREFIX 指 定 编 译 结 果 的 存 放 目 录 , 比 如 我 存 放 到/home/zhiguoxin/linux/nfs/rootfs目录中,等待编译完成。编译完成以后如图所示:

busybox 编译完成

编译完成以后会在 busybox 的所有工具和文件就会被安装到 rootfs 目录中,rootfs 目录内容如图 所示:

rootfs 目录

从图可以看出,rootfs 目录下有 bin、sbin 和 usr 这三个目录,以及 linuxrc 这个文件。前面说过Linux 内核 init 进程最后会查找用户空间的 init 程序,找到以后就会运行这个用户空间的 init 程序,从而切换到用户态。如果 bootargs 设置 init=/linuxrc,那么 linuxrc 就是可以作为用户空间的 init 程序,所以用户态空间的 init 程序是 busybox 来生成的。

busybox 的工作就完成了,但是此时的根文件系统还不能使用,还需要一些其他的文件,我们继续来完善 rootfs。

1.3 向根文件系统添加lib库

1.3.1 向rootfs的/lib目录添加库文件

Linux 中的应用程序一般都是需要动态库的,当然你也可以编译成静态的,但是静态的可执行文件会很大。如果编译为动态的话就需要动态库,所以我们需要先根文件系统中添加动态库。在 rootfs 中创建一个名为“lib”的文件夹,命令如下:

mkdir lib

lib文件夹创建好了,库文件从哪里来呢?lib 库文件从交叉编译器中获取,前面我们搭建交叉编译环境的时候将交叉编译器存放到了/usr/local/arm/目录中。交叉编译器里面有很多的库文件,这些库文件具体是做什么的我们作为初学者肯定不知道,既然我不知道那就简单粗暴的把所有的库文件都放到我们的根文件系统中。这样做出来的根文件系统肯定很大,但是我们现在是学习阶段,还做不了裁剪。

进入如下路径对应的目录:

cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib

此目录下有很多的so(是通配符)和.a 文件,这些就是库文件,将此目录下所有的so*和.a文件都拷贝到 rootfs/lib目录中,拷贝命令如下:

cp *so* *.a /home/zhiguoxin/linux/nfs/rootfs/lib/ -d

后面的-d表示拷贝符号链接,这里有个比较特殊的库文件:ld-linux-armhf.so.3,此库文件也是个符号链接,相当于 Windows 下的快捷方式。会链接到库 ld-2.19-2014.08-1-git.so 上,输入命令ls ld-linux-armhf.so.3 -l查看此文件详细信息,如图所示:

ls ld-linux-armhf.so.3 -l

文件 ld-linux-armhf.so.3

从图 38.2.3.1 可以看出,ld-linux-armhf.so.3 后面有个“->”,表示其是个软连接文件,链接到文件 ld-2.19-2014.08-1-git.so,因为其是一个“快捷方式”,因此大小只有 24B。但是,ld-linux-armhf.so.3 不能作为符号链接,否则的话在根文件系统中执行程序无法执行!所以我们需要 ld-linux-armhf.so.3 完成逆袭,由“快捷方式”变为“本尊”,方法很简单,那就是重新复制 ld-linux-armhf.so.3,只是不复制软链接即可,先将 rootfs/lib 中的 ld-linux-armhf.so.3 文件删除掉,命令如下:

rm ld-linux-armhf.so.3

然后重新进入到/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib 目录中,重新拷贝ld-linux-armhf.so.3,命令如下:

cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
cp ld-linux-armhf.so.3 /home/zhiguoxin/linux/nfs/rootfs/lib/

拷贝完成以后再到 rootfs/lib 目录下查看 ld-linux-armhf.so.3 文件详细信息,如图所示:

文件 ld-linux-armhf.so.3
从图 38.2.3.2 可以看出,此时 ld-linux-armhf.so.3 已经不是软连接了,而是实实在在的一个库文件,而且文件大小为 724392B。

继续进入如下目录中:

cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib

此目录下也有很多的的so和.a 库文件,我们将其也拷贝到rootfs/lib 目录中,命令如下:

cp *so* *.a /home/zhiguoxin/linux/nfs/rootfs/lib/ -d

rootfs/lib 目录的库文件就这些了,完成以后的 rootfs/lib 目录如图所示:

1.3.2 向rootfs的usr/lib目录添加库文件

在rootfs的usr目录下创建一个名为 lib 的目录,将如下目录中的库文件拷贝到rootfs/usr/lib目录下:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib

cd usr
mkdir lib

将此目录下的 so 和.a 库文件都拷贝到 rootfs/usr/lib 目录中,命令如下:

cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib
cp *so* *.a /home/zhiguoxin/linux/nfs/rootfs/usr/lib/ -d

完成以后的 rootfs/usr/lib 目录如图所示:

 rootfs/usr/lib 目录

至此,根文件系统的库文件就全部添加好了,可以使用“du”命令来查看一下 rootfs/lib 和rootfs/usr/lib 这两个目录的大小,命令如下:

cd rootfs //进入根文件系统目录
du ./lib ./usr/lib/ -sh //查看 lib 和 usr/lib 这两个目录的大小

结果如图所示:

lib 和 usr/lib 目录大小
可以看出lib和usr/lib这两个文件的大小分别为57MB和68MB,加起来就是57+68=125MB。非常大!

1.3.3 创建其他文件夹

在根文件系统中创建其他文件夹,如dev、proc、mnt、sys、tmp 和root等,创建完成以后,如图所示:

 创建好其他文件夹以后的 rootfs
目前来看,这个根文件系统好像已经准备好了,究竟有没有准备好,直接测一下就知道了!

二、根文件系统初步测试

接下来我们使用测试一下前面创建好的根文件系统 rootfs,测试方法就是使用 NFS 挂载,uboot 里面的 bootargs 环境变量会设置“root”的值,所以我们将 root 的值改为 NFS 挂载即可。

在 Linux 内核源码里面有相应的文档讲解如何设置,文档为 Documentation/filesystems/nfs/
nfsroot.txt,格式如下:

root=/dev/nfs nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>] ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>

< server-ip>:服务器 IP 地址,也就是存放根文件系统主机的 IP 地址,那就是 Ubuntu 的 IP
地址,比如我的 Ubuntu 主机 IP 地址为 192.168.10.100。
< root-dir> :根文件系统的存放路径,比如我的就是/home/zhiguoxin/linux/nfs/rootfs。
< nfs-options>:NFS 的其他可选选项,一般不设置。
< client-ip> :客户端 IP 地址,也就是我们开发板的 IP 地址,Linux 内核启动以后就会使用
此 IP 地址来配置开发板。此地址一定要和 Ubuntu 主机在同一个网段内,并且没有被其他的设
备使用,在 Ubuntu 中使用 ping 命令 ping 一下就知道要设置的 IP 地址有没有被使用,如果不能
ping 通就说明没有被使用,那么就可以设置为开发板的 IP 地址,比如我就可以设置为
192.168.10.50。
< server-ip> :服务器 IP 地址,前面已经说了。
< gw-ip> :网关地址,我的就是 192.168.10.1。
< netmask>:子网掩码,我的就是 255.255.255.0。
< hostname>:客户机的名字,一般不设置,此值可以空着。
< device> :设备名,也就是网卡名,一般是 eth0,eth1….,正点原子的 I.MX6U-ALPHA 开
发板的 ENET2 为 eth0,ENET1 为 eth1。如果你的电脑只有一个网卡,那么基本只能是 eth0。
这里我们使用 ENET2,所以网卡名就是 eth0。
< autoconf> :自动配置,一般不使用,所以设置为 off。
< dns0-ip> :DNS0 服务器 IP 地址,不使用。
< dns1-ip> :DNS1 服务器 IP 地址,不使用。
根据上面的格式 bootargs 环境变量的 root 值如下:

root=/dev/nfs nfsroot=192.168.10.100:/home/zhiguoxin/linux/nfs/rootfs,proto=tcp rw ip=192.168.10.50:192.168.10.100:192.168.10.1:255.255.255.0::eth0:off

“proto=tcp”表示使用 TCP 协议,“rw”表示 nfs 挂载的根文件系统为可读可写。启动开发板,进入 uboot 命令行模式,然后重新设置 bootargs 环境变量,命令如下:

setenv bootargs 'console=tty0 console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.10.100:/home/zhiguoxin/linux/nfs/rootfs,proto=tcp rw ip=192.168.10.50:192.168.10.100:192.168.10.1:255.255.255.0::eth0:off'
saveenv

设置好以后使用boot命令启动Linux内核,结果如图所示:


在进入根文件系统的时候会有下面这一行错误提示:

can't run '/etc/init.d/rcS': No such file or directory

提示很简单,说是无法运行/etc/init.d/rcS这个文件,因为这个文件不存在。看来我们的 rootfs 还是缺文件,还需要一步一步的完善。

三、完善根文件系统

3.1 创建/etc/init.d/rcS 文件

rcS 是个 shell 脚本,Linux内核启动以后需要启动一些服务,而rcS就是规定启动哪些文件的脚本文件。在 rootfs 中创建/etc/init.d/rcS 文件,然后在rcS中输入如下所示内容:

ls 
mkdir etc
cd etc
mkdir init.d
cd init.d
vi rcS
#!/bin/sh

PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH

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

echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
  • 第 1 行,表示这是一个 shell 脚本。
  • 第 3 行,PATH 环境变量保存着可执行文件可能存在的目录,这样我们在执行一些命令或者可执行文件的时候就不会提示找不到文件这样的错误。
  • 第 4 行,LD_LIBRARY_PATH 环境变量保存着库文件所在的目录。
  • 第 5 行,使用 export 来导出上面这些环境变量,相当于声明一些“全局变量”。
  • 第 7 行,使用 mount 命令来挂载所有的文件系统,这些文件系统由文件/etc/fstab 来指定,所以我们一会还要创建/etc/fstab 文件。
  • 第 8 和 9 行,创建目录/dev/pts,然后将 devpts 挂载到/dev/pts 目录中。
  • 第 11 和 12 行,使用 mdev 来管理热插拔设备,通过这两行,Linux 内核就可以在/dev 目录下自动创建设备节点。关于 mdev 的详细内容可以参考 busybox 中的 docs/mdev.txt 文档。

示例代码中的 rcS 文件内容是最精简的,大家如果去看 Ubuntu 或者其他大型 Linux操作系统中的rcS 文件,就会发现其非常复杂。因为我们是初次学习,所以不用搞这么复杂的,而且这么复杂的 rcS 文件也是借助其他工具创建的,比如 buildroot 等。

创建好文件/etc/init.d/rcS以后一定要给其可执行权限!使用如下命令给予/ec/init.d/rcS 可执行权限:

chmod 777 rcS

设置好以后就重新启动 Linux 内核,启动以后如图所示:

从图可以看到,提示找不到/etc/fstab 文件,还有一些其他的错误,我们先把/etc/fstab这个错误解决了。说不定把这个问题解决以后其他的错误也就解决了。前面我们说了“mount -a”挂载所有根文件系统的时候需要读取/etc/fstab,因为/etc、fstab 里面定义了该挂载哪些文件,好了,接下来就是创建/etc/fstab 文件。

3.2 创建/etc/fstab文件

在 rootfs中创建/etc/fstab 文件,fstab在Linux开机以后自动配置哪些需要自动挂载的分区,格式如下:

< file system> < mount point> < type> < options> < dump> < pass>

< file system>:要挂载的特殊的设备,也可以是块设备,比如/dev/sda 等等。
< mount point>:挂载点。
< type>:文件系统类型,比如 ext2、ext3、proc、romfs、tmpfs 等等。
< options>:挂载选项,在 Ubuntu 中输入“man mount”命令可以查看具体的选项。一般使用 defaults,也就是默认选项,defaults 包含了 rw、suid、 dev、 exec、 auto、 nouser 和 async。
< dump>:为 1 的话表示允许备份,为 0 不备份,一般不备份,因此设置为 0。
< pass>:磁盘检查设置,为 0 表示不检查。根目录‘/’设置为 1,其他的都不能设置为 1,其他的分区从 2 开始。一般不在 fstab 中挂载根目录,因此这里一般设置为 0。

按照上述格式,在 fstab 文件中输入如下内容:

#<file system> <mount point> <type> <options> <dump> <pass>
 proc            /proc        proc   defaults   0      0
 tmpfs           /tmp         tmpfs  defaults   0      0
 sysfs           /sys         sysfs  defaults   0      0

 fstab 文件创建完成以后重新启动 Linux,结果如图所示:

 Linux 启动过程

可以看出,启动成功,而且没有任何错误提示。但是我们要还需要创建一个文件/etc/inittab。

3.3 创建/etc/inittab文件

inittab的详细内容可以参考 busybox 下的文件examples/inittab。init 程序会读取/etc/inittab这个文件,inittab 由若干条指令组成。每条指令的结构都是一样的,由以:分隔的 4 个段组成,格式如下:

<id>:<runlevels>:<action>:<process>

< id >:每个指令的标识符,不能重复。但是对于 busybox 的 init 来说,有着特殊意义。对于busybox 而言< id>用来指定启动进程的控制 tty,一般我们将串口或者 LCD 屏幕设置为控制 tty。
< runlevels > :对 busybox 来说此项完全没用,所以空着。
< action >:动作,用于指定< process>可能用到的动作。busybox 支持的动作如表所示:


< process> :具体的动作,比如程序、脚本或命令等。

参考 busybox 的examples/inittab 文件,我们也创建一个/etc/inittab,在里面输入如下内容:

# etc/inittab
::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
  • 第 2 行,系统启动以后运行/etc/init.d/rcS 这个脚本文件。
  • 第 3 行,将 console 作为控制台终端,也就是 ttymxc0。
  • 第 4 行,重启的话运行/sbin/init。
  • 第 5 行,按下 ctrl+alt+del 组合键的话就运行/sbin/reboot,看来 ctrl+alt+del 组合键用于重启系统。
  • 第 6 行,关机的时候执行/bin/umount,也就是卸载各个文件系统。
  • 第 7 行,关机的时候执行/sbin/swapoff,也就是关闭交换分区。

/etc/inittab文件创建好以后就可以重启开发板即可,至此!根文件系统要创建的文件就已经全部完成了。接下来就要对根文件系统进行其他的测试,比如是我们自己编写的软件运行收费正常、是否支持软件开机自启动、中文支持是否正常以及能不能链接等。

四、根文件系统其他功能测试

4.1 软件运行测试

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

在 ubuntu下使用vim编辑器新建一个hello.c文件,在hello.c里面输入如下内容:

#include <stdio.h>

int main(void)
{
    while(1) 
    {
        printf("hello world!\r\n");
        sleep(2);
    }
    return 0;
}
arm-linux-gnueabihf-gcc hello.c -o hello

将其拷贝到 rootfs/drivers 目录下,在开发板中输入如下命令来执行这个可执行文件:

cd /drivers
./hello

可以看出,hello 这个软件运行正常,说明我们的根文件系统中的共享库是没问题的,要想终止 hello 的运行,按下“ctrl+c”组合键即可。此时大家应该能感觉到,hello 执行的时候终端是没法用的,除非使用“ctrl+c”来关闭 hello,那么有没有办法既能让 hello 正常运行,而且终端能够正常使用?那肯定是有的,让 hello 进入后台运行就行了。

让一个软件进入后台的方法很简单,运行软件的时候加上&即可,比如./hello &就是让 hello 在后台运行。在后台运行的软件可以使用kill -9 pid(进程 ID)命令来关闭掉,首先使用ps命令查看要关闭的软件 PID 是多少,ps 命令用于查看所有当前正在运行的进程,并且会给出进程的 PID。输入ps命令,结果如图所示:

从图可以看出 hello 对应的 PID 为 445,因此我们使用如下命令关闭在后台运行的hello 软件:

kill -9 445

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

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

4.2 外网连接测试

这里说的外网不是外国哪些 404 网站的连接测试,而是百度、淘宝等这些网站的测试。也就是说看看我们的开发板能不能上网,能不能和我们的局域网外的这些网站进行通信。测试方法很简单,就是通过 ping 命令来 ping 一下百度的官网:www.baidu.com。输入如下命令:

ping www.baidu.com

结果如图所示:

可以看出,测试失败,提示 www.baidu.com 是个“bad address”,也就是地址不对,显然我们的地址是正确的。之所以出现这个错误提示是因为 www.baidu.com 的地址解析失败了,并没有解析出其对应的 IP 地址。我们需要配置域名解析服务器的 IP 地址,一般域名解析地址可以设置为所处网络的网关地址,比如 192.168.10.1。也可以设置为 114.114.1144.114,这个是运营商的域名解析服务器地址。

在 rootfs 中新建文件/etc/resolv.conf,然后在里面输入如下内容:

nameserver 114.114.114.114
nameserver 192.168.10.1

设置很简单,nameserver 表示这是个域名服务器,设置了两个域名服务器地址:114.114.114.114 和 192.168.10.1,大家也可以改为其他的域名服务器试试。如果使用“udhcpc”命令自动获取 IP 地址,“udhcpc”命令会修改 nameserver 的值,一般是将其设置为对应的网关地址。修改好以后保存退出,重启开发板!重启以后重新 ping 一下百度官网,可以成功。

至此!我们的根文件系统就彻底的制作完成,这个根文件系统最好打包保存一下,防止以后做实验不小心破坏了根文件系统而功亏一篑,又得从头制作根文件系统。uboot、Linux kernel、rootfs 这三个共同构成了一个完整的Linux 系统,现在的系统至少是一个可以正常运行的系统。

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

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

相关文章

智慧工地车辆未冲洗抓拍系统 opencv+yolo

智慧工地车辆未冲洗抓拍系统利用opencvyolo网络深度学习架构模型对现场画面中车辆的冲洗情况实现智能识别。OpenCV基于C实现&#xff0c;同时提供python, Ruby, Matlab等语言的接口。OpenCV-Python是OpenCV的Python API&#xff0c;结合了OpenCV CAPI和Python语言的最佳特性。O…

微信防撤回功能修改

今天无意之中看到了一个帖子&#xff0c;谈到了有关微信消息撤回的。突发奇想实现一下&#xff0c;以后就不怕错过朋友的消息了。 首先介绍一下基本思路&#xff0c;由于微信采用的是CS端原理&#xff0c;所有的数据请求均通过服务器&#xff0c;客户端只是响应指令而已。 A向…

实验三:自主存取控制实验

【实验目的】 掌握自主存取控制权限的定义和维护方法。掌握在ORACLE数据库中定义用户、角色&#xff0c;分配权限给用户、角色&#xff0c;回收权限&#xff0c;以相应用户登录数据库验证权限分配是否正确的方法。 【实验内容】 设有一个企业&#xff0c;由总裁负责管理采购、…

【Pandas指南】Series

Pandas数据结构简介 - Series 来源&#xff1a;Pandas官网&#xff1a;https://pandas.pydata.org/docs/getting_started/intro_tutorials/index.html 笔记托管&#xff1a;https://gitee.com/DingJiaxiong/machine-learning-study 下面将从对 pandas 中的基本数据结构进行快速…

Git Bash Here和RStudio软件的问题解决

Git Bash Here和RStudio软件的问题解决 文章目录Git Bash Here和RStudio软件的问题解决0、 写在前面1、Git软件在任务栏图标空白2、RStudio软件2.1 警告信息InormalizePath(path.expand(path),winslash,mustWork)2.2 incomplete final line found by readTableHeader on报错3、…

推荐两个go语言的websocket库

最近在写一个需要前后端保持通信的服务。前端要能及时感知后端数据的变化&#xff0c;后端要及时处理前端发过来的指令。这种服务就需要用到websocket了。 以前在写websocket相关的程序时&#xff0c;一直在用gorilla/websocket这个库&#xff0c;这个库事实上已经成为了go语言…

后端面试之系统设计 - 用户密码如何储存在DB里

原文地址&#xff1a;码农在新加坡的个人博客 背景 现在很多网站都因为爆库导致密码泄漏&#xff0c;要设计怎么样的密码储存机制&#xff0c;才能保证最大限度的不被盗取&#xff0c;即使数据泄漏&#xff0c;黑客也无法在短时间内获取对应的密码来登录用户的账号&#xff0c…

LeanCloud: 数据存储实现小程序云开发

1. LeanCloud 官网传送 2. LeanCloud选择原因 微信小程序的开发包括上线需要一个备案过的域名&#xff0c;而域名备案又需要一个服务器&#xff08;仅腾讯云而言&#xff09;。而微信云开发作为个人开发者受限于费用也不做考虑。 此时不考虑复杂的业务逻辑数据库读取是后端服…

A股、港股上市公司碳排放、碳强度和碳披露数据(2018-2021年)

随着中国碳强度减排任务的不断加重&#xff0c;当前政策的就业红利将不复存在&#xff0c;同时政策机制蕴含的资源错配、各行业边际减排成本不相等的问题则愈加严重&#xff0c;实施碳交易减排政策的时机逐渐成熟&#xff0c;政府应如何根据二氧化碳排放量、碳强度和碳披露等数…

带你走进Java字符串的小世界

目录 一. String 1. 什么是String 2. String常用构造器 3. 字符串的判断 4. 字符串的获取 5. 字符串的转换 6. 字符串比较和替换 7. 字符串的切割 二. StringBuffer与StringBuilder 2.1 关于StringBuffer 2.1.1 定义 2.1.2 构造方法 2.2 关于StringBuffer 三. StringJoiner的使…

分布式缓存的四大痛点

目前开发中经常用到的缓存&#xff0c;是我们必不可缺的&#xff0c;他大大的提高了我们整个项目的响应速度和并发量。但是带来好处的同时&#xff0c;也给我们带了了新的问题&#xff1a;缓存穿透、缓存击穿、缓存雪崩以及缓存一致性这么四个问题&#xff0c;也是分布式缓存的…

LeetCode算法之----动态规划

点赞收藏&#xff0c;以防遗忘 本文【程序大视界】已收录&#xff0c;关注免费领取互联网大厂学习资料&#xff0c;添加博主好友进群学习交流&#xff0c;欢迎留言和评论&#xff0c;一起交流共同进步。 目录 【一】前言 【二】打家劫舍 【三】不同路径 【四】最小路径和 …

【数据预处理】基于Kettle的字符串数据清洗、Kettle的字段清洗、Kettle的使用参照表集成数据

文章目录一.前言1.1 实验内容二.实验过程2.1 实验内容一&#xff1a;掌握基于Kettle的字符串数据清洗2.2 实验内容二&#xff1a;掌握基于Kettle的字段清洗2.3 实验内容三&#xff1a;掌握基于Kettle的使用参照表集成数据2.4 实验心得&#xff1a;一.前言 需要本文章的源文件下…

用零知识证明连接多链宇宙

目录 一、前言 二、Bridges和Zero Knowledge Proofs 三、Succinct Verification of Proof of Consensus (Succinct Labs)

【自然语言处理】【ChatGPT系列】ChatGPT的智能来自哪里?

相关博客 【自然语言处理】【ChatGPT系列】ChatGPT的智能来自哪里&#xff1f; 【自然语言处理】【ChatGPT系列】Chain of Thought&#xff1a;从大模型中引导出推理能力 【自然语言处理】【ChatGPT系列】InstructGPT&#xff1a;遵循人类反馈指令来训练语言模型 【自然语言处理…

二叉搜索树与Mysql索引的亲密关系

欢迎关注公众号&#xff1a;【离心计划】&#xff0c;一起逃离技术舒适圈 二叉搜索树 二叉搜索树大家应该多多少少听过&#xff0c;它有一个很重要的特征&#xff0c;就是父节点左子树所有结点的值小于父节点的值&#xff0c;右子树所有结点的值大于父节点的值&#xff0c;这个…

详解vue中vuex的用法

前言 说到 vuex 相信大家都不陌生&#xff0c;vuex 是一个专为 vue.js 应用程序开发的状态管理模式。vuex 背后的基本思想&#xff0c;就是单向数据流。今天我们就来好好聊聊 vuex。 vuex&#xff1f; 用官方的话来说&#xff0c;vuex 是一个专为 vue.js 应用程序开发的状态管…

【Linux】进程间通信之共享内存与信号量初识

目录&#x1f308;前言&#x1f338;1、System V共享内存&#x1f361;1.1、概念&#x1f362;1.2、原理&#x1f33a;2、共享内存相关函数和指令&#x1f361;2.1、shmget函数&#xff08;创建&#xff09;&#x1f362;2.2、shmctl函数&#xff08;控制&#xff09;&#x1f…

使用 DataAnnotations(数据注解)实现模型的通用数据校验

DataAnnotations 实现数据模型的通用校验参数校验的意义常用参数的校验.NET 中内置 DataAnnotations 提供的特性校验关于 DataAnnotations 中的特性介绍基于 DataAnnotations 的通用模型校验封装基于 DataAnnotations 的特性校验助手实现步骤如何使用 DataAnnotations 封装的特…

某农业学校 算法设计与分析-第五次实验-回溯算法

1. 罗密欧与朱丽叶的迷宫问题 问题描述 罗密欧与朱丽叶的迷宫。罗密欧与朱丽叶身处一个mn的迷宫中&#xff0c;如图所示。每一个方格表示迷宫中的一个房间。这mn个房间中有一些房间是封闭的&#xff0c;不允许任何人进入。在迷宫中任何位置均可沿8 个方向进入未封闭的房间。罗…