浅谈ARM嵌入式中的根文件系统rootfs

根文件系统和 Linux 内核是分开的,单独的 Linux 内核是没法正常工作的,必须要搭配根文件系统。根文件系统的这个“根”字就说明了这个文件系统的重要性,它是其他文件系统的根,没有这个“根”,其他的文件系统或者软件就别想工作。嵌入式会把rootfs保存在NAND flash或EMMC中。内核可以直接挂载Emmc中的rootfs;也可以使用uboot把rootfs加载到ramdisk中,挂载内存中的rootfs。

1.根文件系统和 Linux 内核是分开的,单独的 Linux 内核是没法正常工作的

根文件系统是 Linux 内核启动以后挂载(mount)的第一个文件系统,然后从根文件系统中读取初始化脚本,比如 rcS,inittab 等。根文件系统和 Linux 内核是分开的,单独的 Linux 内核是没法正常工作的,必须要搭配根文件系统。如果不提供根文件系统,Linux 内核在启动的时候就会提示内核崩溃(Kernel panic)的提示。
在这里插入图片描述
图1: 根文件系统缺失错误
最后一行:

Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) 

也就是提示内核崩溃,因为 VFS(虚拟文件系统)不能挂载根文件系统,因为根文件系统目录不存在,所以内核会提示在UBOOT中设置一个正确的环境变量“root=” ( Please append a correct “root=” boot option)。即使根文件系统目录存在,如果根文件系统目录里面是空的依旧会提示内核崩溃。
这个就是根文件系统缺失导致的内核崩溃,但是内核是启动了的,只是根文件系统不存在而已。

2.如何构建根文件系统rootfs

根文件系统的这个“根”字就说明了这个文件系统的重要性,它是其他文件系统的根,没有这个“根”,其他的文件系统或者软件就别想工作。比如我们常用的 ls、mv、ifconfig 等命令其实就是一个个小软件,只是这些软件没有图形界面,而且需要输入命令来运行。这些小软件就保存在根文件系统中。

可以使用BusyBox,Buildroot ,Yocto,构建根文件系统rootfs
在这里插入图片描述
图2:创建好的 rootfs

Linux 内核 init 进程最后会查找用户空间的 init 程序,找到以后就会运行这个用户空间的 init 程序,从而切换到用户态。如果 bootargs 设置 init=/linuxrc,那么 linuxrc 就是可以作为用户空间的 init 程序,所以用户态空间的 init 程序是 busybox 来生成的。

在ARM嵌入式中,UBOOT会把上面创建好的rootfs会被保存到nand flash中。

在UBOOT代码中默认的 NAND 分区为:

 #define CONFIG_MFG_NAND_PARTITION "mtdparts=gpmi-nand:64m(boot),16m(kernel),16m(dtb),1m(misc),-(rootfs) "

分区结果如表
在这里插入图片描述
表1:NAND 分区设置
从表中可以看到,rootfs被放到了96M的位置。当然NAND 的分区是可以调整的,比如 boot 分区我们用不了 64M 这么大,因此可以将其改小,其他的分区一样的。

3.内核启动时是如何知道rootfs在哪里呢?

当然是通过Uboot传递来的环境变量 bootargs 。如下:

mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw 

可以看出环境变量 mmcargs 就是设置 bootargs 的值为“console= ttymxc0, 115200 root=/dev/mmcblk1p2 rootwait rw”,bootargs 就是设置了很多的参数的值,这些参数 Linux 内核会使用到,常用的参数有:
1、console
console 用来设置 linux 终端(或者叫控制台),也就是通过什么设备来和 Linux 进行交互,是
串口还是 LCD 屏幕?如果是串口的话应该是串口几等等。一般设置串口作为 Linux 终端,这样我们就可以在电脑上通过 SecureCRT 来和 linux 交互了。这里设置 console 为 ttymxc0,因为 linux启动以后 I.MX6ULL 的串口 1 在 linux 下的设备文件就是/dev/ttymxc0,在 Linux 下,一切皆文件。
ttymxc0 后面有个“,115200”,这是设置串口的波特率,console=ttymxc0,115200 综合起来就是设
2、root
root 用来设置根文件系统的位置,root=/dev/mmcblk1p2 用于指明根文件系统存放在
mmcblk1 设备的分区 2 中。EMMC 版本的核心板启动 linux 以后会存在/dev/mmcblk0、
/dev/mmcblk1、/dev/mmcblk0p1、/dev/mmcblk0p2、/dev/mmcblk1p1 和/dev/mmcblk1p2 这样的文件,其中/dev/mmcblkx(x=0~n)表示 mmc 设备,而/dev/mmcblkxpy(x=0n,y=1n)表示 mmc 设备x 的分区 y。在 I.MX6U-ALPHA 开发板中/dev/mmcblk1 表示 EMMC,而/dev/mmcblk1p2 表示EMMC 的分区 2。
root 后面有“rootwait rw”,rootwait 表示等待 mmc 设备初始化完成以后再挂载,否则的话
mmc 设备还没初始化完成就挂载根文件系统会出错的。rw 表示根文件系统是可以读写的,不加rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。
3、rootfstype
此选项一般配置 root 一起使用,rootfstype 用于指定根文件系统类型,如果根文件系统为ext 格式的话此选项无所谓。如果根文件系统是 yaffs、jffs 或 ubifs 的话就需要设置此选项,指定根文件系统的类型。
bootargs 常设置的选项就这三个,后面遇到其他选项的话再讲解。


上面的例子中我们把根文件系统放在了EMMC中,加载rootfs时直接从EMMC中加载rootfs,并没有使用ramdisk。想使用ramdisk可以参考下面的文章:https://blog.csdn.net/weixin_30608131/article/details/98945515

NAND FLASH加载ramdisk文件系统

虚拟机下制作ramdisk的命令

dd if=/dev/zero of=ramdisk bs=2M count=14

/sbin/losetup /dev/loop2 ramdisk

mkfs.ext2 /dev/loop2

mount -t ext2 /dev/loop2 /mnt

cp -r /tmp/myroot/* /mnt/

umount /dev/loop2

/sbin/losetup -d /dev/loop2

cp /tmp/ramdisk /tftpboot

其中bs,和count的大小可以改变。据观察,发现生成的ramdisk大小,大约为bs*count用命令查看ramdisk的大小

du -h ramdisk

在超级终端uboot下做相应配制

tftp 0x80700000 uImage-ti-davinci_evm-2.6.10_mvl401-1.1.1.0600990
nand erase 0x2250000 0x200000
nand write 0x80700000 0x2250000 0x200000

tftp 0x82000000 ramdisk
nand erase 0x60000 0x2000000
nand write 0x82000000 0x60000 0x2000000

setenv bootcmd 'nand read 0x82000000 0x60000 0x2000000; nboot 0x80700000 0 0x2250000; bootm'
setenv bootargs mem=120M console=ttyS0,115200n8 root=/dev/ram0 rw initrd=0x82000000,29M ip=192.168.1.14:192.168.1.13:192.168.1.1:255.255.255.0

其中,内核uImage-ti-davinci_evm-2.6.10_mvl401-1.1.1.0600990通过tftp传到ddr中(0x80700000),然后烧写进nand flash(相对于0x02000000的偏移地址0x2250000,大小0x200000)。制作好的ramdisk文件系统ramdisk,通过tftp下载到ddr中(0x82000000),然后烧写进nand flash(相对于0x02000000的偏移地址0x60000,大小0x2000000)。
注意(0x82000000+0x2000000)不要和(0x80700000+0x2250000)重叠了。

bootcmd参数,‘nand read 0x82000000 0x60000 0x2000000’ ,是把0x60000处的文件系统数据拷贝到0x82000000处,共32M字节(要比文件系统大)。nboot 0x80700000 0 0x2250000,是打开device 0,把0x2000000字节搬移到0x80700000中。

root=/dev/ram0指明根文件系统存放在内存ram0中。

bootargs参数 initrd=0x82000000是文件系统的位置,29M是文件系统的大小。

NOTE:当NAND FLASH报错Skipping bad block ……时,不会有影响的。

后记,我对根文件系统的一些体会:

我们提到的根文件系统根据使用的时机,其实分为三种:第一种是在内核启动时由内核在内存中创造出来的一个虚拟的rootfs,这个rootfs只有超级块和根目录。第二种是用户生成的内存根文件系统,早期是initrd,后来是initramfs和tmpfs,这三种根文件系统相对来说会完整一些包含了各种库函数和命令,供内核启动时调用。第三种是保存在磁盘或者是flash中的能够提供完整功能的根文件系统,可以供内核和用户调用。

下面简单讲下三种根文件系统是在何时被使用到的:
**1.**bootloader在加载内核时会把initramfs(或者是initrd,tmpfs)和kernel一起加载到内存中。对于嵌入式这个initramfs就是最终的根文件系统(这是一个完整的,包含各种lib,各种命令和文件)。(这个initramfs里面的目录和文件,会被kernel copy到内核创造出的内存rootfs空间中)。

**2.**由于我们不想把kernel变得很大,并没有把保存根文件系统的硬件驱动包含在kernel中,这时内核是没有办法挂载在外部设备中的根文件系统。为了解决这个问题,内核最开始会生成一个内存rootfs。这个rootfs只有根目录,里面没有任何文件。然后内核会把这个内存rootfs挂载到vfs系统中。然后这个内存rootfs会把initramfs中的内容copy到他自己的空间中,形成了一个比较完整根文件系统。

**3.**对于有些嵌入式来说,完成上面两个步骤根文件系统就已经构建完成了。也有些嵌入式系统的内核可以直接挂载Emmc中的rootfs(可以参考《浅谈ARM嵌入式中的根文件系统rootfs 》这篇博文:https://blog.csdn.net/katerdaisy/article/details/135747568)。但是对于大部分设备来说,内核还会把内存rootfs替换成磁盘中的根文件系统。

内核可以直接挂载Emmc中的rootfs,uboot传递参数如下:
mmcargs=setenv bootargs console= ttymxc0, 115200 root= /dev/mmcblk1p2 rootwait rw
其中root=/dev/mmcblk1p2 用于指明根文件系统存放在

内核要使用内存rootfs和initrd时,uboot传递参数如下:
setenv bootargs mem=120M console=ttyS0,115200n8 root=/dev/ram0 rw initrd=0x82000000,29M ip=192.168.1.14:192.168.1.13:192.168.1.1:255.255.255.0
其中root=/dev/ram0指明根文件系统存放在内存ram0中,initrd=0x82000000指明initrd在内存中的位置。

总的来说,我们需要linux需要一个根文件系统提供的库和命令集,但是在linux内核还没有完全初始化之前还没有办法访问外部存储设备上的根文件系统时,就需要一个折中的方法。如上面所讲的会在内存中先构建一个够linux初始化的根文件系统,于是就有了内存rootfs和initramfs。
————————————————

                        版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/katerdaisy/article/details/135767990

  • 22
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值