学习根文件系统的组成以及如何构建根文件系统
根文件系统构建完成 == 我们开发板就拥有了一个完整的,可运行的最小系统
以后我们就可以在这个最小系统上编写测试linux驱动,移植第三方组件,最终得到一个功能完善,驱动齐全的操作系统
-
什么是根文件系统?
a. 根文件系统一般被叫做rootfs
b. 根文件系统并不是FAT,EXT这样的文件系统代码,rootfs更像是一个目录,在这个目录里面有许多的子目录,目根录和子目录下有许多的文件
c. 根文件系统是内核启动时所挂载(mount命令)的第一个文件系统
e. 根文件中保存着内核代码的影像文件,当系统引导启动程序会在根文件系统挂载(start_kernel函数下的rest_init函数中实现)之后将根文件系统中保存的一些基本初始化脚本和服务加载到内存中去运行
知识点1;单独的linux内核是无法正常工作的,必须要搭配根文件系统,不然会同时内核崩溃
f. 根文件系统是其他文件系统的根,linux中一切皆文件,故其他文件系统和软件也是文件,这些文件要保存在根文件系统中才可以运行
知识点2: 前面说的软件包括常用命令ls,mv…等 -
根文件系统下包含的常用子目录
1> /bin目录
bin文件就是可执行文件,故该目录下存放着系统需要的可执行文件,一般都是一些命令,例如ls,mv等,此目录下的命令所有用户都可以使用
2> /dev目录
dev是device的缩写,故该目录下的文件都和设备有关,即此目录下的文件都是设备文件
例如我们前面在uboot中设置的bootargs环境变量中设置liunx的终端为串口0(console= ttymxc0),ttymxc0文件就是在/dev目录下,故对文件/dev/ttymxc0的操作来实现串口0的数据收发
3> /etc目录
该目录下存放着各种配置文件
4> /lib目录
lib是library的缩写,故在该目录下存放着linux所必须的库文件,这些库文件是共享库,命令程序和用户编写的应用程序中要使用这些库文件
知识点: linux中的共享库和静态库的含义和区别
https://www.cnblogs.com/Daniel-G/p/3190315.html
5> /mnt目录
临时挂载命令,一般为空目录
例想将SD卡挂载到系统中: 则在该目录下创建一个对应的文件即可,/mnt/sd
6> /proc目录
虚拟文件系统,一般为空目录,当linux系统启动后会将此目录作为proc文件系统的挂载点,proc中的文件都是临时存在的
7> /usr目录
usr是Unix Software Resource的缩写,即Unix操作系统软件资源目录
知识点1: linux系统一般被称为类Unix操作系统,苹果的MacOS也是类Unix操作系统
8> /sbin目录
此目录下存放一些可执行文件,但是此目录下的文件或命令只有管理员才能使用
9> /sys目录
特殊文件系统,类似于proc文件系统,在linux系统启动后作为sysfs文件系统的挂载点
10> /opt目录
可选的文件,软件存放区,由用户选择将那些文件或软件放到该目录 -
使用BusyBox来构建根文件系统
1> BusyBox是一个集成了大量Linux命令和工具的软件
2> 使用BusyBox来构建根文件系统的流程一般为:
下载BusyBox源码,然后配置BusyBox,选择自己想要的功能,最后编译源码
3> 编译BusyBox来构建根文件系统
知识点1:对于根文件系统,我们通常在开发时是通过挂载nfs来挂载根文件系统带开发板中,当开发完成最后才会将根文件系统烧录到emmc中
1. 配置环境,搭建nfs环境并将BusyBox压缩包拷贝到服务器中并解压
2. 修改编译BusyBox的顶层Makefile,设置系统架构和编译工具链
3. 修改busybox源码权限对中文显示的限制
4. 配置busybox
配置方式有下列3种
a. defconfig: 缺省配置,即默认配置选项 ==> 一般选择默认配置即可
b. allyesconfig: 全选配置,即选中busybox的所有功能
c. allnoconfig: 最小分支
知识点2: busybox也支持图形化配置,输入make menuconfig来打开图形化配置界面
在这里使用图形化配置界面来选择是静态编译还是动态编译,选择动态编译,因为静态编译时DNS会出问题,无法进行域名解析
Localtion -->Settings -->Build static binary(no shard libs) ==>动态编译
还有其他配置看文档来配置
5. 编译Busybox
make install CONFIG_PREFIX=/home/wujiangchao/linux/nfs/rootfs
CONFIG_PREFIX:指定编译结果的存放目录
这样编译完成之后busybox的所有工具和文件就会被安装到rootfs目录中
知识点3:编译完成之后rootfs目录会有 bin,sbin,usr3个目录和linuxrc文件,前面说linux内核中pid=1的init进程会查找用户空间中的init程序并运行该程序,从而init进程由内核进程转为用户进程
如果设置bootargs环境变量中init=/linuxrc,那么linuxrx程序就是init进程查找并执行的程序,故用户空间的init程序是由busybox来生成的
4> 向busybox编译出来的文件中添加库文件
rootfs/lib目录: 库文件来自于交叉编译器中,将交叉编译器环境所致的"usr/local/arm"下的所有文件拷贝到rootfs下的lib目录中(根文件系统下(rootfs)的lib目录中)
rootfs/usr/lib; 将交叉编译器所在库中的一些指定库文件拷贝到这里
5> 创建其他文件夹
前面不是说了根目录rootfs下的常用子目录吗,所以这里要将那些常用子目录创建出来 -
根文件系统初步测试
1> 测试方法正如前面所说在开发阶段用nfs挂载根文件系统到开发板中
linux内核源码中有相应的文档讲解如何实现挂载根文件系统,文档路径:Documentation/filesystems/nfs/ nfsroot.txt
uboot中在bootargs环境变量中的"root"来设置根文件系统所在的地址
故我们设置"root"的值为:
root = /dev/nfs nfsroot=192.168.1.250:/home/wujiangchao/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.251:192.168.1.250:192.168.1.1:255.255.255.0::eth0:offnfsroot:代表根文件系统的存放路径,因为是nfs挂载,故需说明根文件系统在服务器上的绝对路径,服务器ip:/根文件系统在服务器上的绝对路径 proto=tcp: 表示使用TCP协议 rw:表示nfs挂载的根文件系统为可读可写 ip=192.168.1.251: 开发板的ip地址 192.168.1.250: 服务器ip 192.168.1.1: 网关 255.255.255.0: 子网掩码 eth0: 设备名即网卡名,一般为eth0,eth1 off: 自动配置,我们这里选择不使用自动配置
2> 要想将根文件系统提供nfs挂载到开发板中需要重新设置bootargs
setenv bootargs ‘console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.250:/home/xxx/linux/nfs/rootfs,proto=tcp rw ip=192.168.1.251:192.168.1.250:192.168.1.1:255.255.255.0::eth0:off’
saveenv
然后在使用boot命令启动linux内核
5> /etc/init.d/rcS文件,开机启动服务文件 (在这个文件中设置开机自启动相关内容)
1> rcS是个shell脚本,该文件的作用是规定启动那些文件的脚本文件
2> 代码如下
#!/bin/sh //脚本文件的标准式开头
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH //PATH变量中保存着可执行文件可能存在的目录,即我们将要执行的可执行文件存放在这些目录下,作用执行命令/可执行文件是就不会提示找不到文件这种问题
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib //LD-LIBRARY-path变量保存着库文件所在的目录
export PATH LD_LIBRARY_PATH //使用export关键字,将前面定义了保存可执行文件(命令)和库文件的变量导出,相当于声明一些全局变量
mount -a //该命令表示挂载所有的文件系统,这些文件系统由文件/etc/fsdtb来指定
mkdir /dev/pts //创建目录/dev/pts
mount -t devpts devpts /dev/pts //将devpts挂载到/dev/pts目录中
echo /sbin/mdev > /proc/sys/kernel/hotplug //输出重定向
mdev -s //通过这两行来实现,使用mdev来管理热插拔设备,同时实现linux内核可以在/dev目录下自动创建设备节点
3> 对于脚本文件一般需要赋予其可执行文件,故 chmod 777 rcS
4> 例如将一个文件(hello.c)生成的可执行文件作为开机自启动文件
1. 通过交叉编译器,编译生成可在开发板系统运行的可执行文件 arm-linux-guneabihf-gcc hello.c -o hello.o
2. 先测试该.o文件有无效果
a. 将该.o文件拷贝到根文件系统的driver目录下(/home/xxx/linux/nfs/rootfs/driver)
b. 重启开发板,将根文件系统通过nfs挂载到开发板中
c. 在开发板中运行该.o文件,查看效果
cd /drivers
./hello
e. 如果运行ok,那么就在rcS文件中添加该可执行文件的运行步骤
cd /drivers
./hello &
cd /
上面3条命令,都是在开发板中输入的命令, &:表示以后台的方式运行该可执行文件 杀死后台进程的命令 kill -9 程序的对应的pid
6> 创建/etc/fsdtb文件
1> 前面第5点中声说明,需要文件/etc/fsdtn文件来指定那些文件系统(分区)需要自动挂载
2> 挂载一个文件系统的格式如下:
file system: 要挂载的特殊设备或块设备,例如:/dev/sda等
mount point: 挂载点
type: 文件系统的类型,比如ext2.ext3,proc等
options: 挂载选项,在Ubuntu中输出"man mount"命令可以查看具体的选项,一般使用defaults,即默认选项,defaults选项包含了rw,suid,dev,exec,auto,nouser和async
dump: 是否允许备份,1=允许备份,0=不允许备份,一般不备份,故设置为0
pass: 磁盘检查设置,0=不检查,一般根目录’/'设置为1,其他都设置为0
fstab文件中代码如下:
#<file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0 //proc文件是根目录下的常用子目录,作为虚拟文件系统proc的挂载点
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0