You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux中程序退出(含Ctrl+C)时执行自定义代码的实现方法

解决树莓派程序退出时自动拉低GPIO引脚的方案

核心逻辑是捕获所有可能的退出信号并执行引脚复位,同时针对程序崩溃的极端情况,用系统服务做兜底处理,确保23号引脚不会意外保持高电平烧毁FPGA。

一、代码层面处理常规退出场景(Ctrl+C、终端关闭、正常终止)

不管你用Python还是C,都可以通过注册信号处理函数,让程序收到退出信号时先拉低引脚再退出。

Python 示例(用RPi.GPIO)

import RPi.GPIO as GPIO
import signal
import sys

PIN_23 = 23
CONTROL_PIN = 18  # 替换成你的控制引脚编号

def cleanup_pin(signum, frame):
    GPIO.output(PIN_23, GPIO.LOW)
    GPIO.cleanup()
    sys.exit(0)

# 注册需要处理的信号:Ctrl+C(SIGINT)、终端关闭(SIGHUP)、强制终止(SIGTERM)
signal.signal(signal.SIGINT, cleanup_pin)
signal.signal(signal.SIGHUP, cleanup_pin)
signal.signal(signal.SIGTERM, cleanup_pin)

# 初始化引脚:默认设为低电平,防止误触发
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN_23, GPIO.OUT, initial=GPIO.LOW)
GPIO.setup(CONTROL_PIN, GPIO.IN)

# 等待控制引脚变高后,再拉高23号引脚
while not GPIO.input(CONTROL_PIN):
    pass
GPIO.output(PIN_23, GPIO.HIGH)

# 这里写你的主程序逻辑
try:
    while True:
        # 替换成你的业务代码
        pass
except Exception:
    # 捕获其他异常也执行清理
    cleanup_pin(None, None)

C语言示例(用wiringPi)

#include <wiringPi.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

#define PIN_23 4  // wiringPi编号对应BCM23
#define CONTROL_PIN 1  // wiringPi编号对应BCM18

void cleanup_pin(int sig) {
    digitalWrite(PIN_23, LOW);
    pinMode(PIN_23, INPUT);  // 可选:设为输入避免误操作
    exit(0);
}

int main(void) {
    if (wiringPiSetup() == -1) {
        printf("WiringPi初始化失败\n");
        return 1;
    }

    // 注册退出信号
    signal(SIGINT, cleanup_pin);
    signal(SIGHUP, cleanup_pin);
    signal(SIGTERM, cleanup_pin);

    pinMode(CONTROL_PIN, INPUT);
    pinMode(PIN_23, OUTPUT);
    digitalWrite(PIN_23, LOW);

    // 等控制引脚高电平再操作
    while (digitalRead(CONTROL_PIN) == LOW);
    digitalWrite(PIN_23, HIGH);

    // 主程序循环
    while (1);

    return 0;
}

二、极端情况兜底:用systemd服务确保引脚复位

如果程序崩溃到连信号都没机会处理(比如段错误),可以把程序做成systemd服务,配置停止后自动执行复位脚本:

  1. 写一个复位脚本reset_pin.sh:
#!/bin/bash
# 用gpioset工具(树莓派默认预装libgpiod)
gpioset gpiochip0 23=0

给脚本加执行权限:chmod +x reset_pin.sh

  1. 创建systemd服务文件/etc/systemd/system/fpga-control.service:
[Unit]
Description=FPGA控制服务
After=multi-user.target

[Service]
Type=simple
ExecStart=/path/to/your/program  # 替换成你的程序路径
ExecStopPost=/path/to/reset_pin.sh  # 服务停止后自动执行复位
Restart=no  # 按需设置是否自动重启

[Install]
WantedBy=multi-user.target
  1. 启用并启动服务:
sudo systemctl daemon-reload
sudo systemctl enable fpga-control.service
sudo systemctl start fpga-control.service

这样不管程序是崩溃、被kill还是正常退出,systemd都会在服务停止后拉低23号引脚。

三、额外注意事项

  • 程序启动时必须默认把23号引脚设为低电平,防止一开始就误触发烧FPGA。
  • 不要用root权限跑程序,给普通用户加GPIO权限:sudo usermod -aG gpio your_username,重启后生效。
  • 极端情况(比如突然断电)可以给23号引脚加下拉电阻,硬件层面兜底防止高电平残留。

内容的提问来源于stack exchange,提问作者John Barton

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 02:05:37