news 2026/10/6 2:52:48

27_实验二十六_etc与dev目录构建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
27_实验二十六_etc与dev目录构建

实验二十六 构建 etc 与 dev 目录——给骨架装上"灵魂"

对应课件:《第6章 构建Linux根文件系统-V2》6.2 节(中),Slide 34-48

系列说明:本系列基于华清远见 FS-MP1A(STM32MP157A)开发板,对应课件《第6章 构建Linux根文件系统》。实验二十五的rfs-busybox有了命令(bin/sbin)和库(lib),但它还不知道启动后先干什么(init 看谁的脸色)、不知道挂哪些文件系统、/dev还是空的。本篇补齐:写 etc 四件套(inittab / rcS / fstab / profile)、按 busybox 官方文档把 mdev 的设备管理流程跑起来、创建其余空目录——根文件系统从"躯壳"变成"系统"。全程仍在 Ubuntu 里,板子不开;上板点火是实验二十七的事。前置:实验二十五(rfs-busybox 就绪)。

一、init 进程的工作方式:一张 inittab 说清楚

内核挂上根文件系统后运行sbin/init(实验二十五装出来的),init 是 1 号进程,之后的一切程序都是它的子孙。init 睁眼第一件事读/etc/inittab(没有就用默认行为),按里面的条目创建子进程。每条格式:

<id>:<runlevels>:<action>:<process>
  • <id>:该子进程用的控制台,省略 = 与 init 同一个(我们只有 ttySTM0 一个串口,全部省略);
  • <runlevels>:busybox 的 init 不用这字段,留空;
  • <action>:init 怎么对待这个子进程(下表);
  • <process>:要执行的程序或脚本;前面带-表示"交互的"(起一个可敲命令的会话)。

<action>的八个取值(课件表 17.6,重点三个加粗):

图:课件 Slide 36~37——表 17.6《/etc/inittab 文件中<action>字段的意义》截图:sysinit、wait、once、respawn、askfirst、shutdown、restart、ctrlaltdel 八行的执行条件与说明(两页课件用的是同一张表截图)。

action什么时候执行init 等它吗
sysinit系统启动后最先执行,仅一次等它结束才继续
waitsysinit 之后,仅一次等
oncewait 之后,仅一次不等
respawn启动后子进程退出就重启它监视
askfirst与 respawn 类似,但先打印 “Please press Enter to activate this console.” 等你回车才启动监视
shutdown关机/重启时——
restartinit 收到 SIGHUP 时(需配置 CONFIG_FEATURE_USE_INITTAB)——
ctrlaltdel按 Ctrl+Alt+Del 时——

“Please press Enter to activate this console.” 这句话你见过——实验十六点火出厂内核时,串口最后几行就有它:那是出厂根的 inittab 里某条askfirst条目干的。本篇我们自己的 inittab 里也写一条,到时候一模一样地出现。

init 的工作节奏总结:启动前期跑 sysinit/wait/once 三类;正常运行期间维持 respawn/askfirst 两类(退了就拉起来);退出时跑 shutdown/restart/ctrlaltdel 三类。

二、实验环境(实际)

项目实际值
操作位置Ubuntu 虚拟机,实验二十五的rfs-busybox/目录;板子不开
上篇产物rfs-busybox/(bin、sbin、usr、linuxrc、lib 已齐)
内核基线实验十九~二十二编的 5.4.31(CONFIG_UEVENT_HELPER未开——本篇步骤 5 会用到这个事实)

开工自检(10 秒):ls rfs-busybox四样齐全;ls rfs-busybox/lib | wc -l有几十个库。缺了回实验二十五。

三、课件 ↔ 步骤对应表

课件 Slide内容对应步骤
34~37构建 etc:inittab 内容与 action 表步骤 1
38etc/init.d/rcS 脚本步骤 2
39~41fstab 六字段步骤 3
42profile 与 PS1步骤 4
43~44dev 方案:mdev + 内核 Pseudo 配置 + mdev.txt 文档步骤 5
46rcS 最终内容(mdev 七步并入)步骤 5
47uevent helper 报错与内核配置步骤 6
48其他空目录步骤 7

本篇动作 → 后面谁用 → 现在含糊的后果

本篇动作后面哪一篇要用现在含糊的后果
inittab 的::sysinit:/etc/init.d/rcS实验二十七点火后 init 的第一个动作就是它rcS 没跑 = 什么都没挂载 = 系统半死
rcS 里的 mdev 七步实验二十七起 /dev 自动建设备文件/dev 空 → 串口外的设备全失联
fstab 的 tmpfs /tmp 行实验二十七启动日志mount -a的执行对象fstab 格式错一行,rcS 第一句就报错
profile 的 PS1实验二十七起命令行提示符的样子([root@fsmp1a: /]#)提示符不对不知道是哪个文件在管
uevent helper 报错预告实验二十七点火时若看到can't create /proc/sys/kernel/hotplug照方抓药以为根文件系统做坏了

四、实验步骤

以下命令都假设当前在rfs-busybox/里(cd rfs-busybox),nano是顺手工具:Ctrl+O回车保存(这台 Ubuntu 的 nano 是 4.8,底栏就是^O 写入;新版 nano 的Ctrl+S未默认绑定,按了可能没反应——以^O 写入为准)、Ctrl+X退出——完整键位卡见实验二十步骤 1,本系列通用。本篇四处文件都是新建,不存在定位问题,nano 直接敲内容即可。

步骤 1:写 etc/inittab(Slide 34)

mkdir-petc/init.dnanoetc/inittab

内容照课件 Slide 34 逐行照抄(六条生效行 + 穿插的六行注释,注释行也照抄,复制出来与课件截图一模一样):

# /etc/inittab #this is run first except when booting in single-user mode. ::sysinit:/etc/init.d/rcS # /bin/sh invocations on selected ttys # start an "askfirst" shell on the console (whatever that may be) ::askfirst:-/bin/sh # stuff to do when restarting the init process ::restart:/sbin/init # stuff to do before rebooting ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a

图:课件 Slide 34——创建的/etc/inittab内容(共 12 行):6 条生效行::sysinit:/etc/init.d/rcS、::askfirst:-/bin/sh、::restart:/sbin/init、::ctrlaltdel:/sbin/reboot、::shutdown:/bin/umount -a -r、::shutdown:/sbin/swapoff -a,穿插 6 行#注释——与上面代码块逐行一致。

逐条读生效行(#开头的都是注释,给读者看的,init 不执行):第一条是灵魂——系统起来后 init 等着执行/etc/init.d/rcS(我们的启动脚本,步骤 2);第二条起一个交互 shell,-表示交互(每次都要回车确认,即那句 “Please press Enter”);后面四条是重启/关机时的收尾动作。对照第一节的 action 表,六条各就各位。

步骤 2:写 etc/init.d/rcS(Slide 38)

nanoetc/init.d/rcS
#!/bin/sh# This is the first script called by init process/bin/mount-a# use mdevmount-ttmpfs-osize=64k,mode=0755 tmpfs /devmkdir/dev/ptsmount-tdevpts devpts /dev/ptsmount-tproc proc /procmount-tsysfs sysfs /sysecho/sbin/mdev>/proc/sys/kernel/hotplug mdev-s

图:课件 Slide 38——inittab 内容截图,第 3 行::sysinit:/etc/init.d/rcS中/etc/init.d/rcS被下划线标出——rcS 由 inittab 指定,两个文件是上下游。

图:课件 Slide 38——rcS 脚本内容(第 3 行/bin/mount -a标注"挂载 etc/fstab 中指定的文件系统",第 10~11 行标注 mdev 相关)。

逐行读:

行干什么
#!/bin/sh脚本解释器声明
/bin/mount -a把 fstab(步骤 3)里登记的文件系统全部挂上
mount -t tmpfs ... tmpfs /dev在 /dev 上挂内存文件系统——设备文件生在内存里,减少对 Flash/eMMC 的读写(实验二十四第一节 tmpfs 的应用)
mkdir /dev/pts+mount -t devpts devpts /dev/pts远程虚拟终端(telnet)用的挂载点
mount -t proc proc /proc挂 proc——cat /proc/cpuinfo的前提
mount -t sysfs sysfs /sys挂 sysfs——mdev 的信息源(下一行)
echo /sbin/mdev > /proc/sys/kernel/hotplug告诉内核:“设备插拔时请调用 /sbin/mdev”——内核的热插拔代理
mdev -s扫描 /sys,把启动时已存在的设备全部生成对应文件(s = scan)

保存后必须加可执行权限(课件红字提醒,脚本没有 x 位 init 调不动):

chmod+x etc/init.d/rcSls-letc/init.d/rcS# -rwxr-xr-x,x 位在

步骤 3:写 etc/fstab(Slide 39~41)

nanoetc/fstab
# <device> <mount point> <type> <options> <dump> <fsck order> tmpfs /tmp tmpfs defaults 0 0

图:课件 Slide 39——创建的/etc/fstab内容:一行tmpfs /tmp tmpfs defaults 0 0。rcS 的mount -a挂的就是这张表里登记的(proc/sysfs/devpts 在 rcS 里手工挂了,没进表)。

六个字段的含义(本篇只用了一行的量,但字段规则值得记全):

字段含义备注
device挂什么设备文件(如 /dev/mtdblock1)、NFS 时写<host>:<dir>;proc/tmpfs 等虚拟文件系统此字段无意义,任意值
mount point挂到哪目录需先存在
type文件系统类型ext4、nfs、sysfs……或auto让内核自辨
options挂载参数逗号分隔,defaults= rw,suid,dev,exec,auto,nouser,async 组合
dump是否备份0 = 不备份(通用)
fsck order开机检查顺序0 = 不查;通常根 1、其他 2

图:课件 Slide 40——options 字段常用取值表:auto/noauto(mount -a 是否自动挂)、user/nouser(普通用户可否挂)、exec/noexec(可否运行挂载区程序)、ro/rw(只读/读写)、sync/async(是否同步写盘)、defaults(组合值)。

步骤 4:写 etc/profile(Slide 42)

nanoetc/profile
#!/bin/shexportHOSTNAME=fsmp1aexportUSER=rootexportHOME=rootexportPS1="[$USER@$HOSTNAME: \w]# "PATH=/bin:/sbin:/usr/bin:/usr/sbin:$PATHLD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATHexportPATHLD_LIBRARY_PATH

图:课件 Slide 42——创建的/etc/profile内容(第 5 行export PS1="[$USER@$HOSTNAME: \w]# "标注"PS1 设置命令行提示符")。课件截图里 HOSTNAME 写的是fsmpl1a,应为fsmp1a的笔误——照录说明,名字本身随便定,实验二十九还会用 profile.d 的方式再改提示符格式。

profile 是用户登录时执行的脚本:设提示符(PS1)、补 PATH、告诉动态连接器去哪找库(LD_LIBRARY_PATH)。\w= 当前路径、\u= 用户名、\h= 主机名——实验二十九的 PS1 参数表会展开讲。

步骤 5:dev 目录与 mdev 七步(Slide 43~46)

/dev的方案实验二十四定了:mdev 自动管理。先确认内核侧两个前提(我们的内核 5.4.31——实验十九的 multi_v7+fragment 基线——里这两项都是开的,这里只是"查一眼"):

grep-E"CONFIG_SYSFS=y|CONFIG_TMPFS=y"<内核源码>/.config# 两行都应有——sysfs 是 mdev 的信息源,tmpfs 给 /dev 落脚

图:课件 Slide 43——内核 .config 的 Pseudo filesystems 段:CONFIG_PROC_FS=y、CONFIG_SYSFS=y、CONFIG_TMPFS=y(红框)等。

busybox 源码里的官方说明书<busybox源码>/docs/mdev.txt给了完整流程:

图:课件 Slide 44——mdev.txt 节选:mdev 有 initial population(初始生成)与 dynamic updates(动态增删)两种用途,都需要 sysfs 挂在 /sys;文档给出的典型 init 脚本片段 = mount proc、mount sysfs、echo /sbin/mdev > /proc/sys/kernel/hotplug、mdev -s,更完整的 setup 还要先挂 tmpfs /dev、建 /dev/pts、挂 devpts。

把文档七步对到 rcS 上——步骤 2 写的 rcS 恰好就是这七步的落地版:

mdev.txt 步骤rcS 对应行
(1) 挂 tmpfs 到 /devmount -t tmpfs -o size=64k,mode=0755 tmpfs /dev
(2) 建 /dev/ptsmkdir /dev/pts
(3) 挂 devptsmount -t devpts devpts /dev/pts
(4) 挂 procmount -t proc proc /proc
(5) 挂 sysfsmount -t sysfs sysfs /sys
(6) 设热插拔代理echo /sbin/mdev > /proc/sys/kernel/hotplug
(7) 扫描生成设备文件mdev -s

图:课件 Slide 46——并入 mdev 相关命令后的 rcS 完整内容(第 4~11 行红框),与步骤 2 我们写的一致。另按课件提醒:要手工建一个空的dev目录——tmpfs 挂上去之前,挂载点得先存在:

mkdirdev

步骤 6:认知预告——uevent helper 报错与内核配置(Slide 47)

本步不动手——内核的 menuconfig 与重编都归实验二十七步骤 1(那边有显式的cd与完整操作)。现在人在rfs-busybox里敲make menuconfig会报:

make: *** 没有规则可制作目标“menuconfig”。 停止。

不是坏了,是站错了地方——rfs-busybox是根文件系统目录,没有 Makefile;menuconfig是内核源码树的命令,得先回内核顶层(实验二十七步骤 1 第一条就是那个cd)。

课件在此预告了一个上板才会露头的报错,先把它的来龙去脉记下(实验二十七点火时对号):

图:课件 Slide 47——开发板串口输出:Run /sbin/init as init process、/etc/init.d/rcS: line 11: can't create /proc/sys/kernel/hotplug: nonexistent directory,以及 “Please press Enter to activate this console.”。

报错的成因:echo ... > /proc/sys/kernel/hotplug需要内核开启CONFIG_UEVENT_HELPER(/proc/sys/kernel/hotplug 这个出口由它提供)。我们的内核基线是 multi_v7+fragment,这个选项是关的(2026-09-26 对着 multi_v7_defconfig 查证:只有 fragment-03 里一句CONFIG_UEVENT_HELPER_PATH="",开关本身默认 n)——所以这条报错在我们板上必然出现,不是根文件系统做错了。

修法(课件给的内核配置,实验二十七点火前顺手做):

图:课件 Slide 47——需修改的内核配置路径:Location: -> Device Drivers -> Generic Driver Options -> Support for uevent helper(选中)。

图:课件 Slide 47——内核 menuconfig 的 Generic Driver Options 菜单:[*] Support for uevent helper已选中(红框),其下还有() path to uevent helper、[*] Maintain a devtmpfs filesystem to mount at /dev、[*] Automount devtmpfs at /dev...等选项。

操作记忆卡(实验二十七步骤 1 展开):内核顶层make menuconfig→ Device Drivers → Generic Driver Options → 勾[*] Support for uevent helper→ 退出保存 →make -j4 uImage dtbs LOADADDR=0xC2000040重编 → 按实验二十三的流程把新 uImage 送进 TFTP。

顺带一个会让人疑惑的观察,提前说明白:我们的内核同时开着CONFIG_DEVTMPFS与CONFIG_DEVTMPFS_MOUNT(multi_v7 默认 y)——内核挂上根后会自动把 devtmpfs 挂到 /dev 并生成设备文件。所以点火时你可能看到 /dev 里已经有 ttySTM0 等文件,那是内核 devtmpfs 干的、不是 mdev 没干活;rcS 的 tmpfs + mdev 是课件方案的完整教学版,两者叠加不冲突。看到什么、谁干的,实验二十七的日志里见分晓。

步骤 7:其他空目录(Slide 48)

mkdirproc mnt tmp sys root var usr/libls# bin dev etc lib linuxrc mnt proc root sbin sys tmp usr var

proc、sys、tmp、mnt 是挂载点(rcS/fstab 要往里挂东西),root 是 root 用户的家,var 放可变数据,usr/lib是 profile 里 LD_LIBRARY_PATH 报过的路径(虽然暂时没有库放那里,建上不亏)。

就地验证(分两层看,各看各的):

ls# bin dev etc lib linuxrc mnt proc root sbin sys tmp usr var 十三样findetc-typef|sort# etc/fstab etc/init.d/rcS etc/inittab etc/profile 恰四个

别用find . -maxdepth 2 | sort | head -30看整棵树(最初稿就写的它,实测翻车):bin里有近百个符号连接,排序后全挤在./bin/...段,head -30里只有bin,etc排在后面根本露不了面——顶层结构交给ls,etc里有什么交给find etc,各看各的才看得全。

五、注意事项

  1. rcS 必须有可执行权限(chmod +x)——课件红字;init 调一个没有 x 位的脚本会直接失败,症状是"启动卡住无输出"。
  2. fstab 的字段分隔用 Tab 或空格都行,但列数必须是 6——少一列mount -a就报错。
  3. inittab 的::askfirst:-/bin/sh前导减号不能丢——丢了它就不是交互会话,回车进不了命令行。
  4. hotplug 报错不是根做错了——是内核没开 UEVENT_HELPER(本篇步骤 6),去内核 menuconfig 勾上重编,别在根文件系统里打转。
  5. etc 下文件的换行必须是 LF——Windows 记事本编辑会带 CRLF,板上sh会报诡异的\r: not found;在 Ubuntu 里编辑天然无此问题,从 Windows 拷文件时留意。
  6. 改错想重来:这些文件都是纯文本,nano 重开覆盖即可;rfs-busybox整个目录删了重做也不过几分钟(busybox 不用重编)。

六、验证点一览

验证点命令通过的样子在哪一步敲
inittab 六条在位cat etc/inittabsysinit/askfirst/restart/ctrlaltdel/shutdown×2 各一条步骤 1
rcS 可执行ls -l etc/init.d/rcS-rwxr-xr-x步骤 2
fstab 一行四项cat etc/fstabtmpfs /tmp tmpfs defaults 0 0步骤 3
profile 在位head -5 etc/profileHOSTNAME/USER/PS1 各行步骤 4
内核前提grep -E "CONFIG_SYSFS=y|CONFIG_TMPFS=y" <内核>/.config两行都在步骤 5
dev 空目录ls -d dev目录存在步骤 5
全树齐find . -maxdepth 1bin dev etc lib linuxrc mnt proc root sbin sys tmp usr var步骤 7

不达标时的排查:

现象先查什么
板上(实验二十七)init 后直接 kernel panic:no initsbin/init在不在(ls -l 看它是不是指向 busybox 的连接);bin/busybox 在不在
板上 rcS 逐行报not found脚本换行符是否 CRLF(Windows 中转过文件?);解释器#!/bin/sh第一行有没有被 nano 加了多余字符
板上 /dev 空的rcS 的 mdev 段跑没跑(报错行号);mdev 勾没勾(实验二十五步骤 2);UEVENT_HELPER 勾没勾(本篇步骤 6)
板上提示符不是 profile 设的样子profile 文件名拼写;-bashvssh的差异(busybox ash 登录会读它)

七、实验完成标志

  • etc/inittab六条写好,::sysinit:/etc/init.d/rcS在第一有效行(步骤 1 实测)
  • etc/init.d/rcS十一行写好、chmod +x落实、权限位可见(步骤 2 实测:ls -l见-rwxrwxr-x,属主执行位在)
  • etc/fstab一行 tmpfs /tmp、六字段齐(步骤 3 实测)
  • etc/profile写好,PS1 与 LD_LIBRARY_PATH 设上(步骤 4 实测)
  • dev空目录与 mdev 七步对上 mdev.txt 文档;内核 SYSFS/TMPFS 均 =y 已 grep 确认(步骤 5 实测)
  • uevent helper 报错的成因与修法记下(内核勾Support for uevent helper+ 重编,实验二十七落实)(步骤 6)
  • proc mnt tmp sys root var usr/lib全建,顶层ls十三样、find etc四文件(步骤 7 实测)

八、下一步:NFS 挂载根文件系统

根文件系统做完了,但它在 Ubuntu 里躺着——怎么让板子用上它?下一篇(实验二十七)搭 NFS:Ubuntu 出一个共享目录,板子的 bootargs 改成root=/dev/nfs从网络挂根——从此改根文件系统不用重烧卡,Ubuntu 里改完板上重启就生效;顺手把 uevent helper 那个内核配置处理掉、点火进我们自己的根文件系统。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/6 2:52:38

ABAP CDS 访问控制,把数据读取权限落实到每一条业务记录

同一张销售订单报表,总部财务需要查看多个公司的订单,海外子公司的财务只应查看本公司的订单。页面可以完全一样,查询程序也可以完全一样,真正需要变化的是返回的数据范围。我们在设计这类应用时,不能只考虑菜单是否可见、按钮是否可用,还要落实到一个更具体的问题,当前…

作者头像 李华
网站建设 2026/10/6 2:52:32

信创适配|织灵 Coda Loom 2.0 通过统信软件服务器操作系统双版本互认证

2026 年 9 月&#xff0c;可达智灵与统信软件技术有限公司完成产品互认证&#xff1a;织灵 Coda Loom 系统 V2.0 在统信服务器操作系统 V20、V25 两个版本上整体运行稳定&#xff0c;满足功能及兼容性测试要求。两份《统信软件产品互认证证明》认证日期均为 2026 年 9 月 3 日&…

作者头像 李华
网站建设 2026/10/6 2:48:35

YOLO26小目标AP上不去?三个核心死穴精准打击,工业场景实测涨3.7%

最近在做PCB板缺陷检测的项目&#xff0c;拿YOLO26-s训了一版&#xff0c;大目标的焊盘、插件检测AP都能到95%以上&#xff0c;偏偏针脚虚焊、微孔划痕这类2020以下的小目标&#xff0c;AP卡在27%死活上不去。 调过anchor比例&#xff0c;加过CBAM注意力&#xff0c;把FPN层砍了…

作者头像 李华
网站建设 2026/10/6 2:46:56

【HOGP】规范精讲[4]: 吃透BLE HID主机规范——HOGP中HID Host全流程设计与实现

在蓝牙低功耗生态里,键盘、鼠标、游戏手柄这类人机交互设备之所以能稳定、低延迟连接手机、电脑、平板,核心依赖一套成熟的协议框架——HID Over GATT Profile,简称HOGP。这套规范把传统USB HID的交互逻辑完整迁移到BLE GATT之上,既保留了即插即用的兼容性,又发挥了BLE低功…

作者头像 李华