从零开始制作rootfs
1、什么是rootfs,为什么需要rootfs?
内核启动后会开启三个进程,分别是:
进程0(idle进程),空闲进程,也就是死循环
进程1(init进程),挂载根文件系统,并执行Linuxrc这个应用程序从内核态转为用户态,开启用户态的进程1(init进程),逐步开启其他进程
进程2(kthreadd进程)linux内核的守护进程,负责提供操作系统的核心功能(进程调度、内存管理、设备管理、文件体统)的实现
总结根文件系统的作用:
(1)init进程的应用程序(Linuxrc)在根文件系统上
(2)根文件系统提供了根目录/
(3)内核启动后的应用层配置(etc目录)在根文件系统上。几乎可以认为:发行版=内核+rootfs
(4)shell命令程序在根文件系统上。譬如ls、cd等命令
(5)/lib目录下的库文件等
所以:一套linux体系,只有内核本身是不能工作的,必须要rootfs
2、制作一个最小根文件系统
首先要明白镜像格式的根文件系统具有一定的格式,格式是内化的,我们这里以ext2格式的为例
我们首先制作文件夹形式的根文件系统,使用nfs挂载的方式来启动,最后再将我们制作的文件夹格式的跟文件系统使用mke2fs工具制作成ext2格式的镜像文件进行烧录。
2.1、搭建nfs服务器,自己的版本不同,搭建方法会有所差异,参考:《嵌入式开发环境搭建-基于14.04》
2.2、设置nfs启动方式的bootargs:
root=/dev/nfs nfsroot=192.168.1.141:/root/fs/rootfs ip=192.168.1.20:192.168.1.141:192.168.1.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200
2.3、在menuconfig中配置支持nfs启动方式,参考《210支持nfs作为根文件系统启动》
2.4、移植busybox
我们直接在我们的nfs挂在的目录中去创建一个空linuxrc文件,就可以挂载成功,但是执行必然是失败的,应为我们的Linuxrc并不是一个可执行的程序,移植busybox就可以解决这个问题。
busybox可以看做是一个打包了的shell命令集,可以从官网直接下载,首先要检查编译环境(也就是检查Makefile中的CROSS_COMPILE,ARCH),配置(make menuconfig)参照网盘中章节目录下的《busybox menuconfig配置.txt》,编译(make),最后make install安装(注意在make menuconfig中配置按目录为我们nfs挂在的目录)。
实验结果:挂载成功,执行/linuxrc(也就是busybox)成功,但是因为找不到/etc/init.d/rcS和/dev/tty2等文件所以一直在打印错误提示信息,但是其实有进入命令行。
2.5、添加一个典型的inittab
上面的问题是因为shell程序在执行时需要运行时的配置环境,所以我们要为其提供/etc目录下的运行时配置。
inittab的工作原理就是被/linuxrc(也就是busybox)执行时所调用起作用。
每一行的配置项都是由3个冒号分隔开的4个配置值共同确定的(有些配置值可以空缺)。这四个配置值就是id:runlevels:action:process。当满足action的条件时就会执行process这个程序。
inittab文件内容:略
实验结果:成功进入命令行界面,但是提示rcS文件找不到
2.6、添加/etc/init.d/rcS
改文件是linux的运行时配置文件中最重要的一个,其他的一些配置都是由这个文件引出来的。一个复杂项目中配置项很多,会分为好几类,rcS文件会调用这些文件干活。
rcS文件内容及解释如下:
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel //这几行定义了几个“环境变量”
mount -a //挂载所有的应该被挂载的文件系统(根据/etc/fstab文件的格式)
//我们要自己提前建好fstab文件中的空文件夹
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s //配合linux驱动生成相应的/dev目录下的设备文件
/bin/hostname -F /etc/sysconfig/HOSTNAME //定义了主机名,可以在命令行中显示
ifconfig eth0 192.168.1.20 //定义了ip地址,这两行的内容都可以开机后指定
实验结果:PATH runlevel prevlevel这几行定义了几个“环境变量”,可以成功打印出来,虚拟文件系统挂在成功,设备驱动文件生成成功,但是命令行下hostname命令查到的host名字确实是aston210。但是问题就是命令行的提示符是没有显示的。
2.7、添加profile文件
profile文件也是被busybox(init进程)自动调用的,所以是认名字的。
实验结果:命令行提示符前面显示:[@aston210]#,登录用户名没显示出来。原因就是我们直接进入了命令行而没有做登录。
2.8、添加用户登陆
之前intttab中有一个配置项::askfirst:-/bin/sh,这个配置项作用就是当系统启动后就去执行/bin/sh,执行这个就会出现命令行。因此我们这样的安排就会直接进入命令行而不会出现登录界面。
我们要出现登录界面,就不能直接执行/bin/sh,而应该执行一个负责出现登录界面并且负责管理用户名和密码的一个程序,busybox中也集成了这个程序(就是/bin/login和/sbin/gettty),因此我们要在inittab中用/bin/login或者/sbin/getty去替代/bin/sh。(改为s3c2410_serial2::sysinit:/bin/login)
实验结果:成功出现用户登录界面,但是死活密码不对。
2.9、设置用户登录密码
出现上述问题的原因在于我们并没有设置密码。
我们直接移植ubuntu里的/etc/passwd和/etc/shadow文件到当前制作的rootfs目录下(passwd文件中存放的是命名的设置,shadow中存放的是密码的密文),然后再做修改即可,修改时注意一些细节要和我们的开发板对应,如/bin/bash改为/bin/sh。以及登陆后进入的目录等。
移植后我们的用户名和密码就和我们的开发板上是一样的,如果要修改密码直接把shadow文件中的密文删除,然后登陆时就可以不用密码直接进入,然后我们使用passwd root给root用户设置密码。
至此我们一个最小的根文件系统就完成了。项目中用户登录使用getty会比较多,直接改为( s3c2410_serial2::sysinit:/sbin/getty -L s3c2410_serial2 115200 vt100)即可
3、制作镜像形式的rootfs并烧录运行
3.1、制作镜像形式的rootfs
(1)新建一个用于挂在的文件这里是ext2_rootfs,这里的count值一定要够用
dd if=/dev/zero of=rootfs.ext2 bs=1024 count=10240
losetup /dev/loop1 rootfs.ext2
ke2fs -m 0 /dev/loop1 10240
mount -t ext2 /dev/loop1 ./ext2_rootfs/
(2)向ext2_rootfs中复制内容
(3)卸载
umount /dev/loop1
losetup -d /dev/loop1
看待rootfs.ext2则制作成功
3.2、设置合适的bootargs并烧录镜像
bootargs为:set bootargs console=ttySAC2,115200 root=/dev/mmcblk0p2 rw init=/linuxrc rootfstype=ext2