设置环境变量,没有加载文件系统
bootargs=console=ttymxc0,115200
Linux 中的根文件系统更像是一个文件夹或者叫做目录(在我看来就是一个文件夹,只不过是特殊的文件夹),在这个目录里面会有很多的子目录。根目录下和子目录中会有很多的文 件,这些文件是 Linux 运行所必须的,比如库、常用的软件和命令、设备文件、配置文件等等。
根文件系统首先是内核启动时所 mount(挂载)的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。
korofileheader可用于头文件注释署名格式,第二个还有代码补全工具。
win:ctrl+alt+t
//注释:ctrl+/
/**/注释:alt+shift+a
笔者测试 1.29.0 版本
当字符大于 0X7F 以后就跳出去了。
如果支持 UNICODE 码的话,当字符大于 0X7F 就直接输出‘?’。
配置文件:
make defconfig
make menuconfig
路径
-> Settings
-> Linux Module Utilities
-> Linux System Utilities
-> Settings
make
make install CONFIG_PREFIX=/home/samba/linux/nfs/rootfs
前面说过 Linux 内核 init 进程最后会查找用户空间的 init 程序,找到以后就会运行这个用户空间的 init 程序,从而切换到用户态。
如果 bootargs 设置 init=/linuxrc,那么 linuxrc 就是可以作为用户空间的 init 程序,所以用户态空间的 init 程序是 busybox 来生成的。
busybox 的工作就完成了,但是此时的根文件系统还不能使用,还需要一些其他的文件,还需要一些库文件。
当然也可以压缩然后解压。
root@ubuntu:/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib#
cp *so* *.a /home/samba/linux/nfs/rootfs/lib/ -d
so(是通配符)和.a 文件,这些就是库文件,将此目录下所有的so*和.a 文件都拷贝到 rootfs/lib 目录中。
后面的“-d”表示拷贝符号链接,这里有个比较特殊的库文件:ld-linux-armhf.so.3,此库文件也是个符号链接,相当于Windows 下的快捷方式。
“->”,表示其是个软连接文件,链接 到文件 ld-2.19-2014.08-1-git.so,因为其是一个“快捷方式”,因此大小只有 24B。但是,ld-linux-armhf.so.3 不能作为符号链接,否则的话在根文件系统中执行程序无法执行!所以我们需要 ld-linux-armhf.so.3 完成逆袭。
删除/home/samba/linux/nfs/rootfs/lib/目录下的文件
rm ld-linux-armhf.so.3
进入/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/armlinux-gnueabihf/libc/lib 目录中,重新拷贝 ld-linux-armhf.so.3
cp ld-linux-armhf.so.3 /home/samba/linux/nfs/rootfs/lib/
root@ubuntu:/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/samba/linux/nfs/rootfs/usr/lib/ -d
mkdir dev proc mnt sys tmp root
格式
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 地址。
<root-dir>:根文件系统。
<nfs-options>:NFS 的其他可选选项,一般不设置。
<client-ip>:客户端 IP 地址。
<gw-ip>:网关地址。
<netmask>:子网掩码。
<hostname>:客户机的名字,一般不设置,此值可以空着。
<device>:设备名,也就是网卡名,一般是 eth0,eth1….,正点原子的 I.MX6U-ALPHA 开发板的 ENET2 为 eth0,ENET1 为 eth1。如果你的电脑只有一个网卡,那么基本只能是 eth0。这里我们使用 ENET2,所以网卡名就是 eth0。
<autoconf>:自动配置,一般不使用,所以设置为 off。
<dns0-ip>:DNS0 服务器 IP 地址,不使用。
<dns1-ip>:DNS1 服务器 IP 地址,不使用。
“proto=tcp”表示使用 TCP 协议,“rw”表示 nfs 挂载的根文件系统为可读可写。
设置 bootargs
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.108.154:/home/samba/linux/nfs/rootfs,proto=tcp rw ip=192.168.108.66:192.168.108.154:192.168.108.113:
255.255.255.0::eth0:off'
VFS: Unable to mount root fs via NFS, trying floppy.
VFS: Cannot open root device "nfs" or unknown-block(2,0): error -6
Please append a correct "root=" boot option; here are the available partitions:
0100 65536 ram0 (driver?)
0101 65536 ram1 (driver?)
0102 65536 ram2 (driver?)
0103 65536 ram3 (driver?)
0104 65536 ram4 (driver?)
0105 65536 ram5 (driver?)
0106 65536 ram6 (driver?)
0107 65536 ram7 (driver?)
0108 65536 ram8 (driver?)
0109 65536 ram9 (driver?)
010a 65536 ram10 (driver?)
010b 65536 ram11 (driver?)
010c 65536 ram12 (driver?)
010d 65536 ram13 (driver?)
010e 65536 ram14 (driver?)
010f 65536 ram15 (driver?)
b300 7634944 mmcblk1 driver: mmcblk
b301 131072 mmcblk1p1 452c2dfe-01
b302 7493632 mmcblk1p2 452c2dfe-02
b330 512 mmcblk1rpmb (driver?)
b320 4096 mmcblk1boot1 (driver?)
b310 4096 mmcblk1boot0 (driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
random: nonblocking pool is initialized
这里是通过该博主方法解决的
以前使用的16.04版本的ubuntu没问题,现在更换了18.04.4版本,开始报错。
从Ubuntu17.04开始,nfs默认只支持协议3和协议4,而kernel中默认支持协议2。
sudo gedit /etc/default/nfs-kernel-server
RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog"
无法运行“/etc/init.d/rcS”这个文件,因为这个文件不存在。
rcS 是个 shell 脚本,Linux 内核启动以后需要启动一些服务,而 rcS 就是规定启动哪些文件的脚本文件
Ubuntu 或者其他大型 Linux操作系统中的 rcS 文件,就会发现其非常复杂。而且这么复杂的 rcS 文件也是借助其他工具创建的,比如 buildroot 等
#!/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
给予/ec/init.d/rcS 可执行权限:
chmod 777 rcS
启动测试
这里的报错是因为rcS写错了,写成这样了。
mount -a 8 mkdir /dev/pts
mount -t devpts devpts /dev/pts
There are filesystem-specific -o flags.
mount: mounting devpts on /dev/pts failed: No such file or directory
/etc/init.d/rcS: line 8: can't create /proc/sys/kernel/hotplug: nonexistent directory
mdev: /sys/dev: No such file or directory
在 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。
#
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
inittab 的详细内容可以参考 busybox 下的文件 examples/inittab。init 程序会读取/etc/inittab这个文件
格式如下:
<id>:<runlevels>:<action>:<process>
<id>:每个指令的标识符,不能重复。但是对于 busybox 的 init 来说,<id>有着特殊意义。
对于 busybox 而言<id>用来指定启动进程的控制 tty,一般我们将串口或者 LCD 屏幕设置为控
制 tty。
<runlevels>:对 busybox 来说此项完全没用,所以空着。
<action>:动作,用于指定<process>可能用到的动作。
<process>:具体的动作,比如程序、脚本或命令等
#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,也就是关闭交换分区。
至此!根文件系统要创建的文件就已经
全部完成了
root@ubuntu:/home/samba/linux/nfs/rootfs/test# ls
hello hello.c
root@ubuntu:/home/samba/linux/nfs/rootfs/test# file hello
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.31, BuildID[sha1]=7dd1bde89e09327b11ad95e22e72f9bfafd8aecb, with debug_info, not stripped
hello 这个软件为例,实现开机自启动。进入根文件系统的时候会运行/etc/init.d/rcS 这个 shell 脚本。
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
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
./hello &
cd /
个“bad address”,也就是地址不对,之所以出现这个错误提示是因为 www.baidu.com的地址解析失败了,并没有解析出其对应的 IP 地址。我们需要配置域名解析服务器的 IP地址,一般域名解析地址可以设置为所处网络的网关地址,比如 192.168.1.1。也可以设置为 114.114.114.114,这个是运营商的域名解析服务器地址。
新建文件/etc/resolv.conf
nameserver 114.114.114.114
nameserver 192.168.1.1
OK,大功告成,我们可以把uboot,kernel,rootfs保存起来,然后烧写到开发板进行驱动的学习。
先把整个files文件移植到虚拟机,注意这里得用正点原子官方出厂的文件。
格式化卡,和给脚本权限。
root@ubuntu:/home/samba/files# ls -l
总用量 40
drwxr-xr-x 2 root root 4096 4月 1 18:35 boot
drwxr-xr-x 2 root root 4096 4月 1 18:37 filesystem
-rwxrwxrwx 1 root root 6781 8月 5 2021 imx6mkemmcboot.sh
-rwxrwxrwx 1 root root 5360 8月 5 2021 imx6mknandboot.sh
-rwxrwxrwx 1 root root 7697 11月 24 16:20 imx6mksdboot.sh
drwxr-xr-x 2 root root 4096 4月 1 18:35 modules
-rwxr--r-- 1 root root 2639 8月 5 2021 README.txt
开始烧写sd卡
./imx6mksdboot.sh -device /dev/sdc -flash emmc -ddrsize 512
三个分区,还有uboot没有出现,如果文件系统分区没有出现请拔插sd卡。
./imx6mkemmcboot.sh -device /dev/mmcblk1 -ddrsize 512
这个是6ull自己烧所以比较慢。
切换emmc启动。
设置一下环境变量