嵌入式 Linux init 进程 | 深入剖析原理、自启与方案抉择

嵌入式 Linux init 进程 | 深入剖析原理、自启与方案抉择
1. init是什么init是Linux系统中的“天字一号”进程它的进程号PID恒为1是所有其他进程的父进程。其启动流程如init进程的核心功能包括2. init的分类嵌入式Linux系统中init的分类从简单到复杂三种主流方案BusyBox init、SysVinit和systemd。Buildroot等构建系统也明确将这三类列为可选的初始化系统。当前系统init类型的指令cat /proc/1/comm2.1 BusyBox init——轻量级选手BusyBox init是专门为资源受限的嵌入式环境设计的最轻量级解决方案。它是Buildroot的默认init方案对于大多数嵌入式系统而言已经足够使用。比如Buildroot_2019.022.2 SysVinit——经典传统派SysVinit源自ATT在1983年发布的System V Unix系统曾是绝大多数桌面Linux发行版采用的init方案。2.3 systemd——现代全能型选手systemd由Lennart Poettering主导开发是当前Linux桌面和服务器领域最主流的init系统已被Ubuntu、Fedora、Debian等主流发行版全面采用。3. 各init开机自启动应用的区别三种init方案在开机自启动应用的方式上有显著差异3.1 SysVinitSysVinit的启动脚本命名规则为SxxnameS表示Startxx为两位数字编号数字越小越先启动启动过程中会按编号顺序逐个执行脚本例如init进程启动之后会对/etc/inittab文件的解释及执行。/etc/inittab文件里有什么内容如可以看到里面用到了两个脚本文件/etc/init.d/rcS/etc/init.d/rcK其中可以看出/etc/init.d/rcS是在系统开机之后执行的脚本/etc/init.d/rcK是在系统关机时执行的脚本。下面看看/etc/init.d/rcS里面的内容这个rcS脚本会循环调用/etc/init.d文件夹下的以S数字开头的脚本文件。即SysVinit这种机制简单直观但随着服务数量的增长串行启动的效率瓶颈越来越明显。3.2 BusyBox initBusyBox init与SysVinit程序自启动的方式大同小异。可以把 BusyBox init 看作 SysVinit 的精简子集它们之间最核心的区别在于 SysVinit 拥有运行级别的概念而 BusyBox init 则巧妙地绕过了它但又能“模拟”出近乎一致的效果。配置文件/etc/inittab或/etc/init.d/rcS。通过 rcS 脚本挂载适合一次性启动不自动守护。通过 inittab 守护进程自动重启保活。自启动方式直接编辑 inittab 或创建 S* 脚本。3.3 systemdsystemd则截然不同我们只需编写一个简单的.service文件描述服务的启动命令、运行条件和其他依赖关系然后执行systemctl enable即可设置开机自启动。启动时systemd会解析所有Unit文件间的依赖关系并行启动不冲突的服务大大缩短了启动时间。自定义服务必须放在/etc/systemd/system/下。开机自启动自定义服务的例子1. 将程序安装到合适的位置systemd 服务通常使用绝对路径来指定可执行文件。建议将二进制文件放在/usr/local/bin/或/opt/下例如自定义一个hello程序sudo cp ~/hello /usr/local/bin/同时确保文件具有可执行权限sudo chmod x /usr/local/bin/hello2. 创建 systemd 服务单元文件在/etc/systemd/system/目录下创建hello.servicesudo vim /etc/systemd/system/hello.service写入以下内容[Unit] DescriptionHello Systemd Demo Service Afternetwork.target [Service] Typesimple ExecStart/usr/local/bin/hello Restartalways RestartSec5s Usernobody Groupnogroup StandardOutputjournal StandardErrorjournal [Install] WantedBymulti-user.target关键参数解释Typesimple服务主进程就是ExecStart启动的进程。ExecStart指定要运行的程序完整路径。Restartalways无论程序因何退出包括正常退出都自动重启。因为我们循环中用了sleep(10)理论上不会退出加上always可以兜底。Usernobody/Groupnogroup使用低权限用户运行降低安全风险。StandardOutputjournal将程序的标准输出重定向到 systemd 日志journalctl。WantedBymulti-user.target将服务挂钩到多用户目标实现开机自启。注意如果你的程序需要写文件或访问某些目录nobody用户可能没有权限可以根据实际需求修改为其他普通用户如www-data或你自己的用户名。3. 启动服务并设置开机自启# 1. 重新加载 systemd 配置让 systemd 识别新的服务文件 sudo systemctl daemon-reload # 2. 立即启动服务验证是否能正常运行 sudo systemctl start hello.service # 3. 查看服务状态和最近的日志 sudo systemctl status hello.service此时能看到下面的输出且Active状态为active (running)日志中已经出现了hello systemd# 4. 设置开机自动启动 sudo systemctl enable hello.service执行enable后systemd 会在/etc/systemd/system/multi-user.target.wants/目录下创建一个指向hello.service的符号链接下次系统启动时就会自动运行该服务。4. 验证开机自启重启系统sudo reboot重新登录后检查服务状态systemctl status hello.service常用指令命令用途sudo systemctl start hello立即启动服务sudo systemctl stop hello立即停止服务sudo systemctl restart hello重启服务sudo systemctl enable hello设置开机自启sudo systemctl disable hello取消开机自启systemctl status hello查看服务状态和最近日志journalctl -u hello -b查看本次启动以来服务的完整日志journalctl -u hello -f实时跟踪日志输出类似tail -f4. 当前主流的init方案在桌面和服务器领域systemd已毫无疑问地成为绝对主流。在嵌入式Linux领域情况则更为多元Yocto Project虽然默认仍使用SysVinit但已全面支持systemd切换Buildroot默认选择BusyBox init因为它在资源受限的嵌入式系统中最轻量、最高效。选型建议此外还有一些小众但值得关注的init方案4. 小结init进程虽小PID1却是整个Linux系统的“第一推动力”。从极致精简的BusyBox init到经典稳健的SysVinit再到功能强大的systemd每一种方案都有其适合的应用场景。在嵌入式系统开发中正确选择init方案并掌握其开机自启动配置方法是确保产品稳定可靠的关键一步。