rootfs 注本篇笔记只是在BusyBox Buildroot基础上进行讲解BusyBoxBuildroot和rootfs的关系Buildroot 造出 rootfsBusyBox 住在 rootfs 里负责开机后当 pid 1。BuildrootPC 上构建 │ 编译 BusyBox、拷贝配置/脚本、打包 ▼ rootfs 镜像ext4 / squashfs / tar… │ 烧录 / 挂载 ▼ 板子上的 / ├── /sbin/init ← BusyBox 开机后的第一个程序 ├── /etc/inittab ├── /etc/init.d/rcS └── …阶段一 开机用户态的起点/sbin/initkernel_execve(/sbin/init) → busybox 启动 → 识别 applet 名 init → init_main(argc, argv) // 用户态真正入口init.c里面阶段二init_main 主流程int init_main(int argc, char **argv) { /* 屏蔽一批信号延后处理CAD / halt / reboot / CHLD… */ sigprocmask(SIG_BLOCK, G.delayed_sigset, NULL) if (getpid() ! 1) die(must be run as PID 1); // 内核约定init 必须是 1 号进程 console_init(); set_sane_term(); xchdir(/); setsid(); /* PATH / SHELL / USER 等环境 */ message(..., init started: %s, bb_banner) if (单用户模式参数) new_init_action(RESPAWN, shell, ...); else parse_inittab(); // ★ 读 /etc/inittabinit 的任务清单 /* 一次性阶段 */ run_actions(SYSINIT); // 含 rcS 开机服务总开关脚本 run_actions(WAIT) run_actions(ONCE); while (1) { run_actions(RESPAWN | ASKFIRST); /* 等信号、收尸、必要时重启 respawn 进程 */ check_delayed_sigs(...); waitpid(...); sleep1(); }阶段三解析 /etc/inittab::sysinit:/bin/mount -t proc proc /proc ::sysinit:/bin/mount -o remount,rw / ::sysinit:/bin/mkdir -p /dev/pts /dev/shm ::sysinit:/bin/mount -a ::sysinit:/bin/mkdir -p /run/lock/subsys ::sysinit:/sbin/swapon -a null::sysinit:/bin/ln -sf /proc/self/fd /dev/fd null::sysinit:/bin/ln -sf /proc/self/fd/0 /dev/stdin null::sysinit:/bin/ln -sf /proc/self/fd/1 /dev/stdout null::sysinit:/bin/ln -sf /proc/self/fd/2 /dev/stderr ::sysinit:/bin/hostname -F /etc/hostname # now run any rc scripts ::sysinit:/etc/init.d/rcS ......行格式[id]:[runlevels]:[action]:[process]字段BusyBox 含义id终端节点空 默认 consolettyS0→/dev/ttyS0runlevels忽略BusyBox init无 SysV runlevelactionsysinit/wait/once/respawn/askfirst/shutdown/process要执行的命令行注如果没有inittab的话会有一套默认动作执行阶段四run_actions(SYSINIT) 跑通 sysinitstatic void run_actions(int action_type) { for (a G.init_action_list; a; a a-next) { if (!(a-action_type action_type)) continue; if (a-action_type (SYSINIT | WAIT | ONCE | ...)) { pid_t pid run(a); /* fork/vfork 子进程 exec */ if (a-action_type (SYSINIT | WAIT | ...)) waitfor(pid); /* SYSINIT等子进程结束 */ } /* RESPAWN/ASKFIRST只在 pid0 时启动不等待 */ } }阶段五rcS 按序号执行 init.d只匹配Sxx两位序号名字启动顺序根据字典序来排S00S03S49S99在本项目中建立分区文件的脚本buildroot/board/rockchip/rk3562/ctu-overlay/etc/init.d/S03ctu-mount等。UI合成器的有buildroot/package/weston/S49weston。都是两位序号名字。也可以个性化编写脚本跑系统喂狗或者开机软件等阶段六主循环 respawn / 关机 shutdown主循环while (1) { run_actions(RESPAWN | ASKFIRST); check_delayed_sigs(NULL); while ((wpid waitpid(-1, NULL, WNOHANG)) 0) { a mark_terminated(wpid); /* RESPAWN 项 pid 置 0 → 下次再 run */ } sleep1(); }关机::shutdown:/etc/init.d/rcK ::shutdown:/sbin/swapoff -a ::shutdown:/bin/umount -a -rrcK 反向对 S?? 调stopRootfs 的制作注制作在 PC 上完成启动是板子每次上电跑已经做好的文件。二者别混。制作视角三者关系Buildroot 造出 rootfsBusyBox 被编进 rootfs板上当/sbin/initpid 1。BusyBox 源码 ──make──► busybox ELF /bin/ls、/sbin/init … 链接 │ ▼ 装进某个目录CONFIG_PREFIX / TARGET_DIR 其余材料skeleton、inittab、libc、overlay…──► 完整 rootfs 树 │ ▼ mkfs / Buildroot 打镜像 rootfs.img可烧录通用只用 BusyBox 源码怎么编cd busybox-x.y.z make menuconfig # 打开 Init→init交叉编译设 Cross Compiler prefix make -j$(nproc) # 编出一个多呼 ELF mkdir -p /tmp/myroot make CONFIG_PREFIX/tmp/myroot installmake install会把busybox拷进 CONFIG_PREFIX常见/bin/busybox按 .config 建/sbin/init、/bin/sh、/bin/ls… 链接指向它交叉编译注意必须用板子同架构工具链别用宿主机 gcc 直接编目标程序可选CONFIG_STATICy静态链接可不依赖目标机 libc体积更大没开CONFIG_INIT→ 没有/sbin/init内核 exec 后起不来凑齐可启动 rootfsBusyBox alone 不够此时/tmp/myroot只有 BusyBox 那一层。还要需要作用/etc/proc/sys/dev/tmp…挂载点与配置落点/etc/inittabinit 任务清单/etc/init.d/rcSS??*开机脚本passwd / hostname登录、主机名动态库非静态时否则一 exec 就缺 .so设备节点或 mdev/udevconsole / 串口手搓示意ROOT/tmp/myroot # 已 make CONFIG_PREFIX$ROOT install mkdir -p $ROOT/{etc/init.d,proc,sys,dev,tmp,root} # 放入 inittab含 sysinit getty respawn、简易 rcS # 动态链接则拷 .so 到 $ROOT/lib # 再 mkfs.ext4 / 打包成镜像烧进去Buildroot 怎么自动做上面这些产品不天天手敲 CONFIG_PREFIXBuildroot 内部等价Buildroot make ├─ 准备 TARGET_DIR 即将成为 rootfs 的目录树 ├─ 解压/配置 BusyBox ├─ CROSS_COMPILE… make ├─ make CONFIG_PREFIX$(TARGET_DIR) install ├─ 再装 inittab、initscripts、其它包、overlay └─ 按配置打成 ext4 / squashfs …只重编 BusyBoxcd buildroot make busybox-menuconfig make busybox-rebuild本 SDK./build.sh rootfs → mk-rootfs.sh → mk-buildroot.sh rockchip_kx_rk3562_sp → output/.../target/TARGET_DIR→ rootfs.imgOverlay后写覆盖先写BR2_ROOTFS_OVERLAYboard/rockchip/common/base board/rockchip/rk3562/sp-overlay board/rockchip/rk3562/ctu-overlay想改改哪里init / appletbusybox menuconfig / busybox 配置早期启动动作package/busybox/inittab开机服务overlay 或 package 的S??*如 S03ctu-mount、S49weston整包选型rockchip_kx_rk3562_sp_defconfig做完自检ls -l …/target/sbin/init # 期望指向 busybox cat …/target/etc/inittab ls …/target/etc/init.d/做出来的文件 ↔ 启动阶段镜像里有启动时/sbin/initBusyBox阶段一 init_main/etc/inittab阶段二/三 parse_inittab → SYSINIT/etc/init.d/rcSS??*阶段四/五 按序号起服务getty respawn阶段六 主循环保活登录