目录

  • 一、简介
  • 二、设计过程总结
    • 2.1 busybox制作精简的文件系统并完成ramfs启动
    • 2.2 通过精简的文件系统制作完整的文件系统并拷贝到硬盘
    • 2.3 rootfs切换到真正的根文件配置
    • 2.4 启动参数设置
  • 三、硬盘启动验证
  • 四、从硬盘启动失败总结
  • 五、本人其他博客链接
  • 六、其他优化项

一、简介

最近有一块开发板需要制作一个定制的Linux操作系统,通过该项目总结一下相关的资料,包含rootfs切换到真正的根文件系统、如何制作根文件系统和相关的启动配置
机器简介:基于ARM架构的A53开发板,集成了本公司自研主控芯片,采用uboot引导,系统安装在ssd上,内核从nand flash启动;

二、设计过程总结

1、busybox制作精简的文件系统并完成ramfs启动;
2、通过精简的文件系统制作完整的文件系统并拷贝到硬盘;
3、rootfs切换到真正的根文件配置;
4、启动参数设置;

2.1 busybox制作精简的文件系统并完成ramfs启动

1、首先下载busybox源码:
wget https://busybox.net/downloads/busybox-1.35.0.tar.bz2
2、修改启动配置;

vim etc/inittab
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::restart:/sbin/init
vim etc/init.d/rcS
#!/bin/sh
mount -t proc none /proc
mount -t sysfs none /sys

3、利用busybox小环境在内核中编译生产Image.gz;

make -j4 defconfig
make INSTALL_MOD_PATH=$rootfs  modules_install  //rootfs为busybox小环境
make -j4 vmlinux Image Image.gz "$@"
make dtbs

4、uboot中启动Image.gz可以将文件系统以ramfs的形式挂载在内存中;

2.2 通过精简的文件系统制作完整的文件系统并拷贝到硬盘

1、本次制作的完整文件系统是直接在其他机器上交叉下载相关的文件系统生成一个arm架构的根文件系统,然后再打包到硬盘中;

sudo apt-get install debian-archive-keyring
sudo apt-get install binfmt-support qemu qemu-user-static debootstrap
sudo debootstrap --arch=arm64 --foreign stretch debian_arm64_stretch http://mirrors.ustc.edu.cn/debian/
sudo cp /usr/bin/qemu-aarch64-static debian_arm64_stretch/usr/bin

2、大致的过程就是先下载arm平台可以交叉chroot的环境,本次采用x86机器操作,然后chroot到arm环境中下载相关的包后再退出即可;

./ch-mount.sh  debian_arm64_stretch/
cat ./ch-mount.sh
#!/bin/bashecho "MOUNTING"sudo mount -t proc /proc ${1}procsudo mount -t sysfs /sys ${1}syssudo mount -o bind /dev ${1}devsudo mount -o bind /dev/pts ${1}dev/ptssudo chroot ${1}

3、下载相关的包

apt update
apt install sudo
apt install ssh
apt install net-tools
apt install ethtool
apt install ifupdown
apt install iputils-ping
apt install rsyslog
apt install htop
apt install vim

注意:没有源的话要手动添加到etc/apt/sources.list文件中

4、打包到硬盘
将启动硬盘挂载到其他系统中格式化成ext4:

mkfs.ext4 /de/sdb
fdisk /de/sdb  //创建一个根分区设置100G(根据实际硬盘大小设置,建议在30G以上)
mkfs.ext4  /dev/sdb1
将制作的根文件系统拷贝到sdb1

本人博客:分区和打包根文件系统

2.3 rootfs切换到真正的根文件配置

可以直接在busybox环境中的/init添加,或者直接覆盖原来的etc/init.d/rcS

vim /init
#!/bin/bash
echo "Hello Linux"
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
export ROOTMNT=/root
export ROFLAG=-rmount -n -t devtmpfs udev /dev
mount -n -t proc proc /proc
mount -n -t sysfs sysfs /sys
mount -n -t ramfs ramfs /run
udevd --daemon
udevadm trigger --action=add
udevadm settle
for x in $(cat  /proc/cmdline); docase $x in root=*)ROOT=${x#root=};;ro)ROFLAG=-r;;rw)ROFLAG=-w;;esac
donemount ${ROFLAG} ${ROOT} ${ROOTMNT}
export ROOTMNT=/a
udevadm control --exit
mount -n --move /dev  /a/dev
mount -n --move /run  ${ROOTMNT}/run
mount -n --move /proc ${ROOTMNT}/proc
mount -n --move /sys  ${ROOTMNT}/sys
switch_root ${ROOTMNT} /sbin/init#!/bin/bash
mount -o remount,rw /dev/sda1 /
udevd --daemon
udevadm trigger --action=add
udevadm settleexport HOME=/root
exec /bin/bash -lmkdir /mnt/sysroot
mount /dev/sda1  /mnt/sysroot
echo "The pid now is $$"
exec switch_root  /mnt/sysroot /sbin/initmount -t ext4 /dev/sda1 /mnt/sysroot
mount -n --move /sys /mnt/sysroot/sys
mount --move /proc /mnt/sysroot/proc
mount --move /dev /mnt/sysroot/dev
exec switch_root -c /dev/console /mnt/sysroot /sbin/init
chroot  /mnt/sysroot    /bin/bashecho "Mount real rootfs to /mnt/..."
mount -t ext4 /dev/sda1 /mnt  #挂载真正的文件系统
#echo "Switch to read rootfs..."
exec switch_root /mnt /sbin/init   #切换到真正的文件系统sleep 10
mkdir /mnt/lower /mnt/upper /mnt/work /mnt/sysroot
/bin/mount -t squashfs /media/sr0/casper/filesystem.squashfs /mnt/lower -o loop
/bin/mount -t overlay -o lowerdir=/mnt/lower,upperdir=/mnt/upper,workdir=/mnt/work overlay /mnt/sysroot
echo "The pid now is $$"                   //打印当前pid 确保为1
exec switch_root  /mnt/sysroot /sbin/init             //转换

注意:本次制作的根分区是在硬盘的sda1分区

2.4 启动参数设置

1、linux挂载分区时所依赖的信息存放于根文件系统/etc/fstab这个文件中

cat /etc/fstab
/dev/sda1 / ext4 defaults 0 1

本人博客:/etc/fstab详解

2、启动参数设置

setenv bootargs console=ttyS0,115200  root=/dev/sda1  rw  init=/init

本人博客:uboot启动详解

三、硬盘启动验证

在linux启动完成后可以通过:

mount |grep sd
/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro)
//说明此时已经从sda1启动

四、从硬盘启动失败总结

本人在完成这个项目过程中也是费了很长时间从ramfs到硬盘根文件系统的过渡,分析主要原因如下:
1、busybox中init文件代码存在问题,后面采用的方法是直接在uboot启动的ramfs中直接生成img,然后手动解开img,再将里面的init替换成Image.gz中的init:

mkinitramfs -o test.img 5.10.0
mkdir a
cd a;cpio -idvm <../test.img

本人博客:mkinitrd命令详解(注意部分系统为mkinitramfs)

本人博客:cpio格式手动解开命令

2、启动参数中需要加init=/init;
3、硬盘/etc/fstab中要加入自动挂载参数:/dev/sda1 / ext4 defaults 0 1

附mkinitramfs生成的img中init文件如下

#!/bin/bash# Default PATH differs between shells, and is not automatically exported
# by klibc dash.  Make it consistent.
export PATH=/sbin:/usr/sbin:/bin:/usr/bin[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
mount -t proc -o nodev,noexec,nosuid proc /proccase " $(cat /proc/cmdline) " in
*\ quiet\ *)quiet=y;;
*)quiet=necho "Loading, please wait...";;
esac
export quiet# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
mount -t devtmpfs -o nosuid,mode=0755 udev /dev
mkdir /dev/pts
mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true
mount -t tmpfs -o "noexec,nosuid,size=10%,mode=0755" tmpfs /run
mkdir -m 0755 /run/initramfs# Export the dpkg architecture
export DPKG_ARCH=
. /conf/arch.conf# Set modprobe env
export MODPROBE_OPTIONS="-qb"# Export relevant variables
export ROOT=
export ROOTDELAY=
export ROOTFLAGS=
export ROOTFSTYPE=
export IP=
export BOOT=
export BOOTIF=
export UBIMTD=
export break=
export init=/sbin/init
export readonly=y
export rootmnt=/root
export debug=
export panic=
export blacklist=
export resume=
export resume_offset=
export drop_caps=
export fastboot=n
export forcefsck=n
export fsckfix=# Bring in the main config
. /conf/initramfs.conf
for conf in conf/conf.d/*; do[ -f ${conf} ] && . ${conf}
done
. /scripts/functions# Parse command line options
for x in $(cat /proc/cmdline); docase $x ininit=*)init=${x#init=};;root=*)ROOT=${x#root=}if [ -z "${BOOT}" ] && [ "$ROOT" = "/dev/nfs" ]; thenBOOT=nfsfi;;rootflags=*)ROOTFLAGS="-o ${x#rootflags=}";;rootfstype=*)ROOTFSTYPE="${x#rootfstype=}";;rootdelay=*)ROOTDELAY="${x#rootdelay=}"case ${ROOTDELAY} in*[![:digit:].]*)ROOTDELAY=;;esac;;nfsroot=*)NFSROOT="${x#nfsroot=}";;ip=*)IP="${x#ip=}";;boot=*)BOOT=${x#boot=};;ubi.mtd=*)UBIMTD=${x#ubi.mtd=};;resume=*)RESUME="${x#resume=}"case $RESUME inUUID=*)RESUME="/dev/disk/by-uuid/${RESUME#UUID=}"esac;;resume_offset=*)resume_offset="${x#resume_offset=}";;noresume)noresume=y;;drop_capabilities=*)drop_caps="-d ${x#drop_capabilities=}";;panic=*)panic="${x#panic=}"case ${panic} in*[![:digit:].]*)panic=;;esac;;ro)readonly=y;;rw)readonly=n;;debug)debug=yquiet=nif [ -n "${netconsole}" ]; thenexec >/dev/kmsg 2>&1elseexec >/run/initramfs/initramfs.debug 2>&1fiset -x;;debug=*)debug=yquiet=nset -x;;break=*)break=${x#break=};;break)break=premount;;blacklist=*)blacklist=${x#blacklist=};;netconsole=*)netconsole=${x#netconsole=}[ "x$debug" = "xy" ] && exec >/dev/kmsg 2>&1;;BOOTIF=*)BOOTIF=${x#BOOTIF=};;fastboot|fsck.mode=skip)fastboot=y;;forcefsck|fsck.mode=force)forcefsck=y;;fsckfix|fsck.repair=yes)fsckfix=y;;fsck.repair=no)fsckfix=n;;esac
done# Default to BOOT=local if no boot script defined.
if [ -z "${BOOT}" ]; thenBOOT=local
fiif [ -n "${noresume}" ] || [ "$RESUME" = none ]; thenexport noresume=yunset resume
elseresume=${RESUME:-}
fimaybe_break top# Don't do log messages here to avoid confusing graphical boots
run_scripts /scripts/init-topmaybe_break modules
[ "$quiet" != "y" ] && log_begin_msg "Loading essential drivers"
[ -n "${netconsole}" ] && modprobe netconsole netconsole="${netconsole}"
load_modules
[ "$quiet" != "y" ] && log_end_msgif [ "$ROOTDELAY" ]; thensleep $ROOTDELAY
fimaybe_break premount
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-premount"
run_scripts /scripts/init-premount
[ "$quiet" != "y" ] && log_end_msgmaybe_break mount
log_begin_msg "Mounting root file system"
# Always load local and nfs (since these might be needed for /etc or
# /usr, irrespective of the boot script used to mount the rootfs).
. /scripts/local
. /scripts/nfs
. /scripts/${BOOT}
parse_numeric ${ROOT}
maybe_break mountroot
mount_top
mount_premount
mountroot
log_end_msgif read_fstab_entry /usr; thenlog_begin_msg "Mounting /usr file system"mountfs /usrlog_end_msg
fi# Mount cleanup
mount_bottom
nfs_bottom
local_bottommaybe_break bottom
[ "$quiet" != "y" ] && log_begin_msg "Running /scripts/init-bottom"
# We expect udev's init-bottom script to move /dev to ${rootmnt}/dev
run_scripts /scripts/init-bottom
[ "$quiet" != "y" ] && log_end_msg# Move /run to the root
mount -n -o move /run ${rootmnt}/runvalidate_init() {run-init -n "${rootmnt}" "${1}"
}# Check init is really there
if ! validate_init "$init"; thenecho "Target filesystem doesn't have requested ${init}."init=for inittest in /sbin/init /etc/init /bin/init /bin/sh; doif validate_init "${inittest}"; theninit="$inittest"breakfidone
fi# No init on rootmount
if ! validate_init "${init}" ; thenpanic "No init found. Try passing init= bootarg."
fimaybe_break init# don't leak too much of env - some init(8) don't clear it
# (keep init, rootmnt, drop_caps)
unset debug
unset MODPROBE_OPTIONS
unset DPKG_ARCH
unset ROOTFLAGS
unset ROOTFSTYPE
unset ROOTDELAY
unset ROOT
unset IP
unset BOOT
unset BOOTIF
unset UBIMTD
unset blacklist
unset break
unset noresume
unset panic
unset quiet
unset readonly
unset resume
unset resume_offset
unset fastboot
unset forcefsck
unset fsckfix# Move virtual filesystems over to the real filesystem
mount -n -o move /sys ${rootmnt}/sys
mount -n -o move /proc ${rootmnt}/proc# Chain to real filesystem
exec run-init ${drop_caps} ${rootmnt} ${init} "$@" <${rootmnt}/dev/console >${rootmnt}/dev/console 2>&1
echo "Something went badly wrong in the initramfs."
panic "Please file a bug on initramfs-tools."

五、本人其他博客链接

1、手动分区和打包根文件系统

2、/etc/fstab详解

3、uboot启动详解

4、mkinitrd命令详解(注意部分系统为mkinitramfs)

5、cpio格式手动解开命令

6、grub.cfg启动详解

六、其他优化项

1、测试阶段内核Image.gz和设备数dtb都是用tftp启动,项目完成后将文件写至nand中启动;
2、硬盘采用UUID的方式启动,适用于多块硬盘连接到机器上无法固定启动硬盘号的情况;

Linux系统rootfs切换到真正的根文件系统详细源码解析(附工作项目手动制作根文件实例)相关推荐

  1. .Net Core 认证系统之基于Identity Server4 Token的JwtToken认证源码解析

    介绍JwtToken认证之前,必须要掌握.Net Core认证系统的核心原理,如果你还不了解,请参考.Net Core 认证组件源码解析,且必须对jwt有基本的了解,如果不知道,请百度.最重要的是你还 ...

  2. 树莓派linux编译不了动态库,linux系统下的树莓派与Qt 5.12.3源码的交叉编译

    {写在前面:按照这个方法,基本可以成功在linux系统下交叉编译Qt5.12.3,其他版本的源码也编译} 我的环境:Linux Mint 19.1;树莓派 3;Qt源码5.12.3 当两个系统全部安装 ...

  3. (十二)洞悉linux下的Netfilteramp;iptables:iptables命令行工具源码解析【下】

    iptables用户空间和内核空间的交互 iptables目前已经支持IPv4和IPv6两个版本了,因此它在实现上也需要同时兼容这两个版本.iptables-1.4.0在这方面做了很好的设计,主要是由 ...

  4. openxr runtime Monado 源码解析 源码分析:CreateInstance流程(设备系统和合成器系统)Compositor comp_main client compositor

    monado系列文章索引汇总: openxr runtime Monado 源码解析 源码分析:源码编译 准备工作说明 hello_xr解读 openxr runtime Monado 源码解析 源码 ...

  5. 服务器系统切换用户,linux系统如何切换到root用户_网站服务器运行维护,linux,root...

    windows系统如何强制关机?_网站服务器运行维护 windows系统强制关机的方法:1.Win系统笔记本,找到电源键,长按不放直到屏幕完全变黑,松开手指:2.台式机,找到电源键,用手指长按,直到电 ...

  6. 对嵌入式Linux中的根文件系统的理解和解析

    虽然前面已经利用Busybox制作了根文件系统,但是对于根文件系统的作用和普通的文件系统之间的区别还是有点模糊.通过查找资料总结了一 下对根文件系统的理解,也欢迎大家一起讨论.    首先要明白的是& ...

  7. 深入理解linux系统的目录结构(总结的非常详细)

    转自:佚名 的<深入理解linux系统的目录结构(总结的非常详细)> 原址:https://www.jb51.net/LINUXjishu/151820.html 对于每一个Linux学习 ...

  8. linux系统python生成so_Python 项目转化为so文件实例

    思路是先将py转换为c代码,然后编译c为so文件,所以要安装以下内容: python 安装:cython pip install cython linux 安装:python-devel,gcc yu ...

  9. Linux的内核设计与实现之进程管理(含源码)

    Linux内核设计与实现--进程篇之进程管理 目录 概述 进程与线程 进程管理 进程描述符及任务结构 进程状态 进程上下文 线程创建 写时拷贝 fork() vfork() 创建线程 内核线程 进程终 ...

最新文章

  1. 技术图文:C# VS. Python 读取CSV文件指南
  2. python3 得到一个可用未绑定端口
  3. 2.5 linux C 进程与多线程入门--(5)使用互斥量进行同步
  4. Java实现替换多个字符串中的参数
  5. Linux信号实践(3) --信号内核表示
  6. 手机丢了,支付宝和微信里面的钱该怎么办?
  7. MongoDB CookBook读书笔记之备份与恢复
  8. 国际国家代号mysql_最全的各国 语言(文化)代码与国家地区对照表(国际通用标准形式)...
  9. 华为NP课程笔记3-OSPF3
  10. 斐讯K2破解任意校园网教程
  11. Oracle 12c 数据库可插拔体系结构
  12. 让ppsx幻灯片进入可编辑状态
  13. 流行手机谜语大解密 (爱情诗)
  14. 疫情下的科技内卷:租房被卷进“网购”时代
  15. 掷一枚硬币,直到连续出现两次正面朝上的时候停止,问掷硬币次数的期望
  16. day_02-个人博客系统
  17. 基于unity制作的AR视频播放
  18. IOS第二十九天——HTTP下载一个图片
  19. 网页编辑器的快捷键及常用操作
  20. 操作系统用户界面——用户界面

热门文章

  1. 【路径规划】基于matlab蚁群优化遗传算法机器人栅格地图最短路径规划【含Matlab源码 1581期】
  2. 数据库分类,市场上常见数据库
  3. 12、Storage(存储)(基础知识)
  4. 将本地docker镜像推送到阿里云仓库
  5. 好像还挺好玩的GAN重制版4——Pytorch搭建SRGAN平台进行图片超分辨率提升
  6. 基于STM32单片机的直流电机控制系统加减速正反转设计方案原理图程序
  7. strus2常用标签自己一点小小的应用1
  8. JAVAWEB之JSTL标签
  9. YOLO v3 详解
  10. jquery.ajaxSetup()函数详解