1.概述
根文件系统
(1)实质: 特殊用途的文件系统, 是一些代码,一套软件。
(2)镜像格式: 由各种工具制成, 做出的镜像有不同格式, 内核启动文件系统时, 要用rootfstype= xxx指定格式, 内核会按这种格式解析根文件系统镜像;
(3)作用: 对存储设备的块/扇区进行管理,将对块/扇区的访问变成对目录和文件名的访问。
上层访问文件时,文件系统将目录+文件名转换成对块/扇区号的访问。
原因: 存储设备(块设备, 如硬盘、flash)是分块/扇区的,物理上底层去访问存储设备时是按照块/扇区号访问, 不方便人记忆, 文件操作遇到分散存储更麻烦。
(4)不同文件系统的差异: 在于对块/扇区的管理策略法不同,如坏块管理、碎片管理。
为什么需要根文件系统
(1)提供目录:
1)根目录/ : 最原始的绝对路径, 其他目录都是相对于/目录找的路径;
2)配置目录etc/: 内核启动后的应用层配置在根文件系统上。
(2)提供应用程序: 几乎可认为:发行版=内核+rootfs(其他应用程序都挂在rootfs);
1)进程1: init进程的用户态应用程序在根文件系统上;
2)人机交互界面: shell命令应用程序在根文件系统上。如ls、cd等命令;
总结:
linux体系只有内核是不能工作的,必须要rootfs相配合才能工作。
(内核需要etc/下的配置文件、bin/和sbin/下的shell命令,lib/下的库文件等···)
常见根文件系统类型
FAT、NTFS、ext2、ext3、jffs2、yaffs2、ubi等主要设计目的是为了管理块设备(硬盘、Nand···)
ZnFAT(振南FAT, 早期牛人针对单片机的个人写的文件系统)
根文件系统形式
(1)镜像文件:
1)来源: 用专用工具, 将文件夹格式的根文件系统, 制作可供烧录的镜像文件;
2)作用: 用来烧录到块设备上, 内核启动后去挂载;
3)烧录过程: 如fastboot flash 按文件系统标准格式化存储设备的分区, 为了文件系统能快速找到目录/文件;
4)镜像的文件系统类型: 一般文件系统类型在后缀中指出, 如rootfs.qt4.ext3, qt4表示带qt4界面移植的。
(2)文件夹:
1)包含特定内容的文件夹, 因为根文件系统可由主机的空文件夹添加必要文件而成, 然后开发板远程挂载;
2)制作简单流程:
随便mkdir创建空文件夹,然后添加必要文件(包括/etc、/bin、/lib··)形成文件夹形式的rootfs。
然后开发板kernel通过nfs方式远程挂载使用,但不能用来烧录。
3)文件夹形式的rootfs没有格式,镜像后才有格式,由制作工具决定。
制作并烧录rootfs.ext2初体验
(1)工具介绍: mke2fs, 用来制作ext2、ext3、ext4等类型的根文件系统
1)是一个应用程序,ubuntu默认安装好的;
2)工具名字格式: mkfs.xxx
制作ext2格式的叫mkfs.ext2/3/4, ls -l /sbin/mkfs.ext2发现是个指向make2fs的符号链接;
制作jffs2格式的叫mkfs.jffs2
(2)制作流程:
1)创建rootfs.ext2文件并挂载到一个目录下方便访问;
$cd /mnt/share/my_rootfs
$dd if=/dev/zero of=rootfs.ext2 bs=1024 count=2048 //创建空磁盘文件, ls可查rootfs.ext2
//写磁盘,输入空,输出rootfs.ext2文件,block大小是1024b, 共2048个block, 则文件大小=2048*1k=2M
$losetup /dev/loop1 rootfs.ext2//将rootfs.ext2映射成虚拟块设备loop1;(loop1已使用可用loop0)
$mke2fs -m 0 /dev/loop1 2048 //将 /dev/loop1格式化为2048个块
$mkdir rootfs
$mount -t ext2 /dev/loop1 ./rootfs/ //把 /dev/loop1虚拟设备作为ext2格式挂载到 ./rootfs/
2)在虚拟设备挂载目录创建普通格式的linuxrc(内核启动需要elf格式) 。
$cd rootfs
$touch linuxrc //虽然是空的, 但内核启动挂载文件系统时可挂载成功,而执行/linuxrc失败。
3)添加/lib目录及其库文件,/etc目录及其配置文件等。
//这里先不添加
4)取消挂载虚拟挂载, 并卸,镜像就做好了;
$umount /dev/loop1
$losetup -d /dev/loop1
4)fastboot烧录;
$cp rootfs.ext2 /mnt/share/my_rootfs -f; 然后复制~/my_rootfs/rootfs.ext2到F:/fastboot/my_rootfs;
fastboot flash system my_rootfs/rootfs.ext2; fastboot reboot;
//system分区指mmcblk0p2, inand分区2
(3)结果:能看到VFS: Mounted root(ext3 filesystem) on device 179:2
//虽然传参传了rootfstype=ext3, 但ext2还是挂载成功了, 说明他们兼容
文件夹rootfs挂载到开发板初体验
(1)什么是nfs:
1)Network file system, 一种网络通讯协议,由服务器和客户端构成。
2)作用: 利用nfs协议做可做很多应用,这里主要用来rootfs挂载。
主机ubuntu搭建nfs服务器:, 开发板运行kernel做nfs客户端:
3)优缺点:
(1)不用制作rootfs镜像, 一般作为产品开发阶段调试使用;[优]
(2)不适合真正产品,网线松动会导致内核根文件系统丢失;[缺]
(2)ubunutu搭建nfs服务器:
1)安装
apt install nfs-common //安装nfs服务
apt install nfs-kernel-server //安装nfs服务器
2)导出共享文件夹
vim /etc/exports
末尾添加一句: /mnt/share/my_rootfs/rootfs *(rw,sync,no_root_squash,no_subtree_check)
/rootfs | 共享的目录 |
* | 指定哪些用户可以访问 * 所有可以ping同该主机的用户 |
(ro,sync,no_root_squash): | 权限 |
3)将文件系统目录设为共享目录
chmod 777 -R /mnt/share/my_rootfs/rootfs
exportfs -r //更新导出目录
showmount -e 或者showmount localhost -e //查看导出的目录
4)重启nfs服务
/etc/init.d/nfs-kernel-server restart
5)挂载测试
mount -t nfs -o nolock localhost:/mnt/share/my_rootfs/rootfs /test //进入/mnt能看到rootfs则成功
//localhost能用当前ip替代, 192.168.0.106
//注意这里测试不要挂到/mnt, 因为挂载后原有的文件看不到了
//我挂到/opt后, opt下的交叉编译工具链没了, 要取消挂载
umount -v /opt //取消挂载
(3)配置内核, make menuconfig:
1)配置网络部分,使能CONFIG_IP_PNP, 为了能够看到NFS的Root file system on 选项
Networking support ->Networking options ->[*]TCP/IP networking 和
[*]IP: kernel level autoconfiguration
->[*] IP: DHCP support
->[*] IP: BOOTP support
2)配置开启nfs服务
File systems ---> Network File Systems --->
<*> NFS client support
[*] NFS client support for NFS version 3
[*] NFS client support for the NFSv3 ACL protocol extension
[*] NFS client support for NFS version 4 (EXPERIMENTAL)
[*] NFS client support for NFSv4.1 (DEVELOPER ONLY) //选中
[*] Root file system on NFS
(3)配置开发板:
1)内核配置为支持nfs;
2)uboot cmd下, 设置bootargs为nfs启动:
setenv bootargs root=/dev/nfs nfsroot=192.168.0.106:/mnt/share/my_rootfs/rootfs ip=192.168.0.20:192.168.0.106:192.168.0.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200
(默认是bootargs=console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext3)
(4)如果移植的内核tftp下载过, 不用重新编译, 网线连好, setenv后saveenv, reset就会启动内核;
(5)结果:
1)VFS:Cannot open root device "nfs" or unknown-block //Root file system on NFS 没配好
2)VFS:Failed to execute /linuxrc. Attempting defaults... //挂载成功, 但init进程打开失败
Kernel panic - not syncing: No init found...
启动内核后挂载网络文件系统
1)启动内核进入cmdline:
$mount -t nfs -o nolock,vers=3 192.168.0.106:/mnt/share/my_rootfs/rootfs /mnt
-t: 指定挂载的文件系统类型
到底什么是linuxrc
(1)是可执行的应用程序:
1)是应用层的,和内核源码一点关系没有
2)在开发板内核下是可执行的。
用arm-linux-gcc编译链接的, 因为运行平台是ARM架构的SoC的linux系统;
用gcc编译连接的, 就是在PC机linux系统下可执行。
(2)只能静态链接:
1)因为/linuxrc程序由内核直接调用执行,用户无法提供dll文件路径,没法动态连接;
2)linuxrc作为目标文件, 静态.动态链接参考c语言静态库和动态库;
(3)作用:
1)引出进程: 执行时, 引出用户界面的应用程序(cmdline或GUI)和其他进程, 就产生了进程2、3、4·····。
2)启动后配置: 负责系统启动后的应用层配置(一般叫运行时配置,简写etc);
内核启动完只是打好地基, 操作系统的一些应用要先配置才能用, 如桌面的图标配置。
目的是为了让操作系统用起来更方便,更适合个性化, 更实用。
(4)嵌入式操作系统的linuxrc来源: busybox
最小的rootfs应该具备什么内容
linuxrc | 进程1的应用程序 |
/dev | 设备文件。这里面有一两个设备文件是rootfs必须的。 linux中一切皆是文件,硬件设备也被虚拟化成一个设备文件来访问,(open打开,然后read/write/ioctl操作,最后close关闭) |
/sys | 不可省略的,空文件夹即可, 放一些新的虚拟/设备文件系统; |
/proc | 不可省略的,空文件夹即可; 这两个目录和驱动有关的。属于虚拟文件系统。 |
/usr | 系统的用户所有的一些文件的存放地,这个东西将来busybox安装时会自动生成。 |
/etc | 运行时配置文件, 所有配置文件会直接/间接被/linuxrc调用执行,完成操作系统的运行时配置。 |
/lib | 放操作系统的动态和静态链接库文件, 主要为了其存放动态链接库, 几乎所有应用程序都需要用这些共享库。 |
什么是VFS(vitrual file system)
(1)是 Linux 内核中的一个软件层,也是linux内核的一种设计理念, proc/目录中的文件都不是硬盘上的文件, 而是虚拟出的设备文件, 用到时会加载到内存中, 打开设备文件时会去内核中查找对应变量的值。
(2)作用: 将更多的硬件设备访问虚拟化成对目录+文件的访问, 给用户空间的程序提供文件系统接口;
借鉴了文件系统设计理念(将底层难管理的物理磁盘扇区式访问,转换成目录+文件名的方式访问);
(3)示例: 通过设备文件(目录+文件名,譬如/dev/mmcblk0p2)方式来访问系统中的硬件设备。
(4)意义:
1)实现了linux中一切届是文件, 对硬件设备/普通文件的访问接口统一化, 允许不同的文件系统共存。
2)统一了操作系统应用层对下层不同文件系统类型的访问接口。
不同文件系统访问细节不同, 没有VFS, 那cp命令时就不得不考虑cp的文件在什么文件系统类型下。
3)统一了不同文件系统对下层硬件设备(块设备)驱动的访问接口。
不同类型的文件系统在设计时就不用考虑各种硬件设备的具体的操作差异了。
(5)VFS和内核启动的关系:
1)文件系统挂载上了, 意味着VFS正确识别了rootfs
2)内核中有一些sys proc这种虚拟文件系统,和VFS机制有关。
3)/dev/目录下的设备文件都和VFS有关,所以学习驱动绕不开VFS。
(6)详细: 参考 https://blog.csdn.net/climbe/article/details/56667852