嵌入式Linux设置开机自动运行程序(基于BusyBox init)

本文详细介绍了在嵌入式Linux中,如何利用BusyBoxinit的启动流程,通过inittab文件配置开机自动运行程序,包括rcS和rcK脚本的运用,以及如何编写并管理S??*格式的脚本来实现实时任务执行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的

开机自动运行程序,或者说系统启动时自动运行程序,这是经常会需要用到的功能。这个功能通常依托于 init 程序实现。 init 是Linux在内核启动完成之后第一个启动的程序,该程序会运行一些特定位置的脚本,相当于实现开机运行程序的效果。

在常见的Linux发行版中 init 程序主要为 SysVinitSystemd 。在嵌入式Linux中根文件系统通常使用 buildroot 来建立, buildroot 默认是基于 BusyBox 构建根文件系统的,这种方式下默认的 init 程序可以称其为 BusyBox init 。 这篇文章将介绍通过 BusyBox init 实现开机自动运行程序的功能。

BusyBox init启动流程

inittab

BusyBox init 会在启动后读取 /etc/ 目录下的 inittab 文件,下面是其内容样式:

# /etc/inittab
#
# Copyright (C) 2001 Erik Andersen <andersen@codepoet.org>
#
# Note: BusyBox init doesn't support runlevels.  The runlevels field is
# completely ignored by BusyBox init. If you want runlevels, use
# sysvinit.
#
# Format for each entry: <id>:<runlevels>:<action>:<process>
#
# id        == tty to run on, or empty for /dev/console
# runlevels == ignored
# action    == one of sysinit, respawn, askfirst, wait, and once
# process   == program to run

# Startup the system
::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

# Put a getty on the serial port
console::respawn:/sbin/getty -L  console 0 vt100 # GENERIC_SERIAL

# Stuff to do for the 3-finger salute
#::ctrlaltdel:/sbin/reboot

# Stuff to do before rebooting
::shutdown:/etc/init.d/rcK
::shutdown:/sbin/swapoff -a
::shutdown:/bin/umount -a -r

可以从注释中看到这个文件记录的是一条条按照一定规则编写的语句。

BusyBox init 会在启动后执行第三个字段为 sysinit 的语句中的命令,会在关机时执行第三个字段为 shutdown 的语句中的命令。

在这里添加语句就可以实现开机运行程序了,不过一般不推荐这么做。

rcS 和 rcK

从上面文件中可以看到 sysinit 系列的语句最后一条会去执行 /etc/init.d/ 目录下的 rcS 脚本,也即开机时其它工作完成后会执行 rcS 这个脚本。同样的会在关机时先执行 /etc/init.d/ 目录下的 rcK 脚本。这两个脚本内容如下:

rcS

#!/bin/sh


# Start all init scripts in /etc/init.d
# executing them in numerical order.
#
for i in /etc/init.d/S??* ;do

     # Ignore dangling symlinks (if any).
     [ ! -f "$i" ] && continue

     case "$i" in
        *.sh)
            # Source shell script for speed.
            (
                trap - INT QUIT TSTP
                set start
                . $i
            )
            ;;
        *)
            # No sh extension, so fork subprocess.
            $i start
            ;;
    esac
done

rcK

#!/bin/sh


# Stop all init scripts in /etc/init.d
# executing them in reversed numerical order.
#
for i in $(ls -r /etc/init.d/S??*) ;do

     # Ignore dangling symlinks (if any).
     [ ! -f "$i" ] && continue

     case "$i" in
        *.sh)
            # Source shell script for speed.
            (
                trap - INT QUIT TSTP
                set stop
                . $i
            )
            ;;
        *)
            # No sh extension, so fork subprocess.
            $i stop
            ;;
    esac
done

可以看到 rcS 脚本会依据文件名排序依次读取 /etc/init.d/ 目录下名字为 S??* 格式的脚本文件,并执行其中的 start 方法。同用的 rcK 脚本会依据文件名逆排序读取 /etc/init.d/ 目录下名字为 S??* 格式的脚本文件,并执行其中的 stop 方法。

设置开机自动运行程序

对于我们需要设置开机运行程序而言,可以编写名字为 S??* 格式的脚本文件存放到 /etc/init.d/ 目录下,这样它就会在开机时被调用执行其中的 start 方法了。

名字为 S??* 格式的脚本文件默认在 /etc/init.d/ 目录下已经有一些了:
在这里插入图片描述

我们可以参考它们来编写自己的脚本开机脚本,这里创建名为 S77test 的文件,其中内容如下:

#!/bin/sh

umask 077

start() {
        echo "Starting test log: Naisu is coming!!!"
}

stop() {
        echo "Stopping test log: Naisu is leaving!!!"
}

restart() {
        stop
        start
}

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart|reload)
        restart
        ;;
  *)
        echo "Usage: $0 {start|stop|restart}"
        exit 1
esac

exit $?

备注1:各个函数中不建议出现长时间阻塞的操作,如果有需求建议在命令后面加上 (空格)& 放到后台运行;
备注2:行尾必须是以只有换行符形式,不能是windows上回车加换行的形式;

调整脚本权限:

chmod 755 /etc/init.d/S77test

下面就是脚本在开关机时运行的演示了:
在这里插入图片描述

总结

在使用 BusyBox init 的嵌入式Linux系统中设置开机自动运行程序并不复杂,只要了解其脚本调用流程基本就可以了。

### 如何创建和使用Linux根文件系统镜像 #### 创建根文件系统的准备工作 为了创建一个可用的 Linux 根文件系统镜像,首先要准备必要的工具和环境。确保安装了 `mkfs` 工具集以及任何可能需要用于构建文件系统的额外软件包。 #### 构建基础文件结构 建立基本的目录层次结构是第一步,在目标位置创建类似于标准 Unix/Linux 的树形结构,这通常包括 `/bin`, `/etc`, `/lib`, `/usr` 等重要目录[^3]。 ```bash mkdir -p rootfs/{bin,etc,home,mnt,opt,tmp,usr,var} chmod 1777 rootfs/tmp/ ``` #### 配置启动脚本和服务 配置初始化过程中的关键组件,比如编写简单的启动脚本来执行一些命令或是设置网络参数等。下面是一个例子,它会在每次开机时打印欢迎信息并自动挂载所有定义好的分区: ```bash echo '#!/bin/sh' > rootfs/etc/init.d/rcS echo 'echo "Welcome to My Custom Linux!"' >> rootfs/etc/init.d/rcS echo '/bin/mount -a' >> rootfs/etc/init.d/rcS chmod +x rootfs/etc/init.d/rcS ``` 对于更复杂的场景,则需进一步完善此部分逻辑,甚至引入 BusyBox 或 systemd 来管理服务进程。 #### 打包成 img 文件 一旦完成了上述工作,下一步就是把整个根文件夹打包成为一个 .img 文件以便于后续部署到实际硬件设备上运行。这里介绍一种通用的方法来生成 ext 类型(如 ext2/ext3/ext4)的磁盘映像文件[^2]: ```bash dd if=/dev/zero of=rootfs.img bs=1M count=64 # 创建固定大小 (此处为 64MB) 的空白图像文件 losetup /dev/loop0 rootfs.img # 关联 loop 设备与新创建的 image file mkfs.ext4 /dev/loop0 # 对关联后的环回设备进行格式化处理 mount /dev/loop0 mnt/root # 挂载该虚拟磁盘至本地某个临时路径下 cp -rpf rootfs/* mnt/root/ # 复制之前做好的 root filesystem 内容至此处 umount mnt/root # 卸载前先解除挂载关系 losetup -d /dev/loop0 # 解除 loop device 映射 ``` 以上步骤展示了如何将自定义的内容封装进一个可移植性强、易于分发的形式——即所谓的 “image”。 #### 使用根文件系统镜像 要让嵌入式板卡或其他支持此类功能的操作平台能够识别并加载这个新的根文件系统,可以采取多种方式实现烧录动作;最常见的是通过 SD 卡读卡器连接电脑端完成数据传输后再插入待测试机器中启动尝试。 另外也可以借助诸如 U-Boot 这样的引导程序直接从 USB 存储介质或者 TFTP 服务器加载指定地址空间内的 kernel 和 initramfs 组件组合起来形成完整的 boot chain.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naisu Xu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值