制作一个根文件系统涉及到以下三块:
本文的目的是制作一个ramdisk根文件系统,自然内核要支持该类型的文件系统,打开相关配置选项
cp arch/arm/configs/imx6ull_defconfig .config
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
1.支持initial RAM filesystem和RAM disk
2.支持RAM block,并设置RAM disk的数量和大小。这里设置的RAM disk的数量为8,内核启动后会在/dev下创建8个设备节点,实际在uboot中指定使用的是/dev/ram0,所以RAM disk的数量至少是1;设置的ramdisk是大小为8192K,如果这个大小和制作的的ramdisk不匹配,内核启动时会出现kernel panic,提示ramdisk格式不正确,挂载不上ramdisk,实际试验只要制作的ramdisk小于8192K就能正常启动。
3.支持ext2文件系统。ramdisk是一种内存虚拟磁盘技术,实质上并不是一种文件系统,它在内存上使用的是ext2类型格式。
重新编译内核,并把.config文件复制为imx6ull_defconfig保存
make zImage -j4 #生成的镜像为 arch/arm/boot/zImage
cp .config arch/arm/configs/imx6ull_defconfig
1.从https://www.busybox.net/可以下载到busybox的源码
2.将busybox-1.32.1.tar.bz2放到编译服务器上解压,并配置busybox
进入目录,make menuconfig
3.编译安装
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- #已设置cross compile prefix的话可直接make
make install
在安装目录下生成bin、linuxrc、sbin、usr,linuxrc即init进程,启动过程中由内核调用,bin和sbin目录下包含各种命令和工具,可以在配置busybox时选择是否开启某命令,其中linuxrc和各种命令工具都是指向bin/busybox的软链接。
sudo mkdir fs_temp
cd fs_temp
sudo mkdir mnt tmp var sys proc etc lib dev root home
#将busybox编译成的bin、linuxrc、sbin、usr拷到该目录下
cp -R ../ramdsikfs/* ./
cd dev
sudo mknod console c 5 1 #创建控制台设备文件
sudo mknod null c 1 3 #创建一个空的设备文件
sudo mknod ttymxc0 c 207 16 #创建串口设备
#以上几个节点在内核执行init进程时要用到,所以要提前创建
海思平台etc目录下存在如下文件,可根据功能需求添加,其中init.d/rcS、inittab、fstab是必须的。实际我是在imx6ull开发板上调试的,只创建了以上三个文件,给出的其他文件内容来自海思sdk,读者注意区分。
1.inittab配置文件
::sysinit:/etc/init.d/rcS
#getty要求设备启动输入login和passwd,配合group、passwd和shadow使用
#::respawn:/sbin/getty -L ttymxc0 115200 vt100 -n root -I "Auto login as root ..."
ttymxc0::askfirst:-/bin/sh #不需要输入login和passwd
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a
注:使用getty时会调用/bin/login,一定要创建group、passwd和shadw,我调试的时候没有创建这几个文件,无论输入什么都是Login incorrect
2.init.d目录
rcS脚本
#! /bin/sh
/bin/mount -a
#执行init.d目录下S[0-9][0-9]*脚本
#海思是执行以下几个脚本去创建节点,挂接devpts、tmpfs,使用udev和进行网络设置
#我自己操作时是手动创建节点的,是没有以下代码的
for initscript in /etc/init.d/S[0-9][0-9]*
do
if [ -x $initscript ] ;
then
echo "[RCS]: $initscript"
$initscript
fi
done
S00devs脚本
#!/bin/sh
#创建节点
mknod /dev/console c 5 1
mknod /dev/ttyAMA0 c 204 64
mknod /dev/ttyS000 c 204 64
mknod /dev/null c 1 3
S01udev脚本
#!/bin/sh
#udev有关
mkdir /dev/pts
mount -t devpts devpts /dev/pts
mount -t tmpfs tmpfs /run
mkdir -p /dev/.udev
udevd --daemon
udevadm trigger
mdev -s
S80network脚本
#!/bin/sh
#设置网络参数
ipaddr=
bootp=
gateway=
netmask=
hostname=
netdev=
autoconf=
for ipinfo in `cat /proc/cmdline`
do
case "$ipinfo" in
ip=*)
for var in ipaddr bootp gateway netmask hostname netdev autoconf
do
eval read $var
done << EOF
`echo "$ipinfo" | sed "s/:/\n/g" | sed "s/^[ ]*$/-/g"`
EOF
ipaddr=`echo "$ipaddr" | cut -d = -f 2`
[ x$ipaddr == x ] && ipaddr=x
;;
esac
done
[ -z "$ipaddr" ] && exit 0
echo " IP: $ipaddr"
echo " BOOTP: $bootp"
echo " GATEWAY: $gateway"
echo " NETMASK: $netmask"
echo "HOSTNAME: $hostname"
echo " NETDEV: $netdev"
echo "AUTOCONF: $autoconf"
if [ x$ipaddr == x- ] ; then
# use DHCP
:
else
cmd="ifconfig $netdev $ipaddr"
[ x$netmask != x- ] && cmd="$cmd netmask $netmask"
eval $cmd
[ x$gateway != x- ] && route add default gw $gateway
fi
ifconfig lo 127.0.0.1
3.fstab文件:该文件被用来定义文件系统的"静态信息",这些信息被用来控制mount命令的行为,内容如下,表示执行rcS脚本中"mount -a"命令后要去挂载的文件系统。
#
proc /proc proc defaults,nodev,nosuid 0 0
sysfs /sys sysfs defaults,nodev,nosuid 0 0
tmpfs /dev tmpfs defaults 0 0
debugfs /sys/kernel/debug debugfs defaults 0 0
tmpfs /tmp tmpfs mode=1777 0 0
4.mstab文件:记载的是现在系统已经装载的文件系统,包括操作系统建立的虚拟文件等;而/etc/fstab是系统准备装载的。每当 mount 挂载分区、umount 卸载分区,都会动态更新 mtab,mtab 总是保持着当前系统中已挂载的分区信息,fdisk、df 这类程序,必须要读取 mstab 文件,才能获得当前系统中的分区挂载情况。当然我们自己还可以通过读取/proc/mount也可以来获取当前挂载信息 。
proc /proc proc rw 0 0
sysfs /sys sysfs rw 0 0
devfs /dev devfs rw 0 0
devpts /dev/pts devpts rw 0 0
5.profile文件,环境变量相关,修改的内容是对所有用户起作用的
6.passwd和shadow文件,记录登录账户和密码
7.udev和mdev,用于自动创建节点,之后会另写一个文章介绍,本文以怎么制作根文件系统为主
1.增加文件权限
cd temp_fs
sudo chown root -R *
sudo chgrp root -R *
sudo chmod 4755 bin/busybox
2.制作ramdisk镜像,并拷贝temp_fs的内容到里面
sudo dd if=/dev/zero of=ramdisk bs=1024 count=8192
sudo mke2fs -F -m0 ramdisk #格式化,-F强制,-m0不为管理员预留空间
sudo mount -t ext2 ramdisk /mnt/loop/
cd /mnt/loop/
sudo cp ~/work/temp_fs/* ./ -afR
cd -
sudo umount /mnt/loop/
gzip -v9 ramdisk #生成ramdisk.gz
修改u-boot的启动bootargs,我这边使用imx6ull开发板调试的
#将ramdisk.gz网络加载到0x83800000上
tftp 0x83800000 ramdisk.gz
#设置bootargs
setevn bootargs 'console=ttymxc0,115200 root=/dev/ram0 rw init=/linuxrc initrd=0x83800000,0x800000'
#启动
run bootcmd
下图是内核启动打印,成功进入文件系统。为什么mount root识别成的是ext4文件系统,具体还得看内核代码
至此,一个简单的ramdisk文件系统制作完毕,至于如何给文件系统添加想要的功能,等待下次用到的时候再更新吧~~