ZYNQ应用程序开机启动

方案一:检查当前使用的 init 系统

1. 确认 init 系统

bash

复制代码
# 查看进程树
ps aux | head -20

# 查看 init 进程
ls -l /sbin/init
file /sbin/init

# 查看系统版本
cat /etc/os-release
uname -a

2. 常见嵌入式 init 系统

  • BusyBox init :使用 /etc/inittab

  • SysV init :使用 /etc/init.d/ 和运行级别

  • OpenRC :使用 /etc/init.d//etc/runlevels/

  • runit :使用 /etc/service/

  • procd:OpenWRT 使用

3. 启动顺序

内核启动 → init进程 → /etc/inittab → 执行 ::sysinit: → /etc/init.d/rcS → /etc/rcS.d/S* 脚本

方案二:使用 BusyBox init(最常见)

1. 编辑 inittab 文件

bash

复制代码
# 查看当前配置
cat /etc/inittab

# 编辑 inittab
vi /etc/inittab

2. 在 inittab 中添加应用启动

bash

复制代码
# 在文件末尾添加(示例格式)
# ::[action]:[process]

# 系统启动时运行一次
::sysinit:/home/root/myapp --init

# 作为守护进程运行(崩溃自动重启)
::respawn:/home/root/myapp

# 或指定控制台
ttyPS0::respawn:/home/root/myapp

# 启动后延迟运行
::wait:/bin/sleep 5 && /home/root/myapp

3. 完整的 inittab 示例

bash

复制代码
# /etc/inittab
::sysinit:/etc/init.d/rcS

# 启动 getty(串口登录)
ttyPS0::respawn:/sbin/getty -L ttyPS0 115200 vt100

# 启动您的应用程序
::respawn:/home/root/myapp --daemon
::respawn:/home/root/another_app

# 关机脚本
::shutdown:/etc/init.d/rcK

4. 重新加载 inittab

bash

复制代码
# 方法1:重启系统
reboot

# 方法2:重新初始化(如果支持)
init q
# 或
kill -HUP 1

方案三:使用 SysV init 脚本

1. 创建 init.d 脚本

bash

复制代码
# 创建启动脚本
sudo vi /etc/init.d/myapp

2. init.d 脚本模板

bash

复制代码
#!/bin/sh
### BEGIN INIT INFO
# Provides:          myapp
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: My Zynq Application
# Description:       My custom application on Zynq
### END INIT INFO

APP_NAME="myapp"
APP_PATH="/home/root/myapp"
PID_FILE="/var/run/${APP_NAME}.pid"
LOG_FILE="/var/log/${APP_NAME}.log"

case "$1" in
    start)
        echo "Starting $APP_NAME..."
        start-stop-daemon -S -b -m -p $PID_FILE -x $APP_PATH \
            -- --daemon >> $LOG_FILE 2>&1
        echo "done."
        ;;
    stop)
        echo "Stopping $APP_NAME..."
        start-stop-daemon -K -p $PID_FILE
        rm -f $PID_FILE
        echo "done."
        ;;
    restart)
        $0 stop
        sleep 2
        $0 start
        ;;
    status)
        if [ -f $PID_FILE ]; then
            PID=$(cat $PID_FILE)
            if kill -0 $PID 2>/dev/null; then
                echo "$APP_NAME is running (PID: $PID)"
            else
                echo "$APP_NAME PID file exists but process not found"
            fi
        else
            echo "$APP_NAME is not running"
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|status}"
        exit 1
        ;;
esac

exit 0

3. 设置权限和启用

bash

复制代码
# 添加执行权限
chmod +x /etc/init.d/myapp

# 创建符号链接到运行级别目录
# 查看可用运行级别
ls /etc/rc.d/
ls /etc/rc?.d/

# 通常使用 rc3.d 或 rc5.d
ln -s /etc/init.d/myapp /etc/rc3.d/S99myapp
ln -s /etc/init.d/myapp /etc/rc5.d/S99myapp

# 禁用(删除符号链接)
rm /etc/rc3.d/S99myapp

方案四:使用 rc.local(最简单)

1. 编辑 rc.local

bash

复制代码
# 检查是否存在
ls -l /etc/rc.local

# 创建或编辑
vi /etc/rc.local

2. 添加启动命令

bash

复制代码
#!/bin/sh
# rc.local - 开机启动脚本

# 等待系统准备就绪
sleep 5

# 启动应用程序(后台运行)
/home/root/myapp > /var/log/myapp.log 2>&1 &

# 启动更多应用
/home/root/another_app --daemon &

# 必须的退出语句
exit 0

3. 设置权限

bash

复制代码
chmod +x /etc/rc.local

方案五:使用 BusyBox runit(如果有)

bash

复制代码
# 检查是否安装 runit
which runsvdir

# 创建服务目录
mkdir -p /etc/sv/myapp

# 创建运行脚本
cat > /etc/sv/myapp/run << 'EOF'
#!/bin/sh
exec /home/root/myapp 2>&1
EOF

chmod +x /etc/sv/myapp/run

# 创建日志脚本(可选)
cat > /etc/sv/myapp/log/run << 'EOF'
#!/bin/sh
exec svlogd -tt /var/log/myapp
EOF

chmod +x /etc/sv/myapp/log/run

# 启用服务
ln -s /etc/sv/myapp /etc/service/

方案六:创建自定义启动脚本

1. 在 /etc/init.d 创建

bash

复制代码
cat > /etc/init.d/S99myapp << 'EOF'
#!/bin/sh
# /etc/init.d/S99myapp

start() {
    echo "Starting my application..."
    # 等待网络
    while ! ping -c1 google.com &>/dev/null; do
        sleep 1
    done
    
    # 启动应用
    /home/root/myapp &
    echo $! > /var/run/myapp.pid
    echo "done."
}

stop() {
    echo "Stopping my application..."
    kill $(cat /var/run/myapp.pid) 2>/dev/null
    rm -f /var/run/myapp.pid
    echo "done."
}

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

exit 0
EOF

chmod +x /etc/init.d/S99myapp

2. 在启动序列中调用

bash

复制代码
# 在启动脚本中调用
echo "/etc/init.d/S99myapp start" >> /etc/init.d/rcS

方案七:使用 crontab @reboot

bash

复制代码
# 编辑 root 的 crontab
crontab -e

# 添加开机启动
@reboot /home/root/myapp > /tmp/myapp.log 2>&1
@reboot sleep 10 && /home/root/another_app --daemon

最佳方案方法

1. 检查系统结构

bash

复制代码
# 查看 init 系统
ls -la /sbin/init
ls -d /etc/*init*
ls /etc/

# 查看启动脚本
find /etc -name "*rc*" -type f
find /etc -name "*init*" -type d

# 检查进程1
cat /proc/1/comm

2.检查您的 Zynq 系统是否支持 SysV init

bash

复制代码
# 查看是否存在 init.d 目录
ls -la /etc/init.d/

# 查看运行级别目录
ls -la /etc/rc.d/  # 或 ls -la /etc/rc?.d/

# 查看当前运行级别
runlevel
# 输出示例: N 5   (前一个运行级别为N,当前为5)

# 查看默认运行级别
cat /etc/inittab | grep initdefault

3.对于大多数 ZYNQ系统,按优先级推荐:

  1. 首选:/etc/inittab - 最稳定,崩溃自动重启

  2. 备选:/etc/init.d/ 脚本 - 功能完整

  3. 备选:/etc/rc.local - 最简单

  4. 最后:crontab @reboot - 通用但依赖 cron