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服务,配置停止后自动执行复位脚本:
- 写一个复位脚本
reset_pin.sh:
#!/bin/bash # 用gpioset工具(树莓派默认预装libgpiod) gpioset gpiochip0 23=0
给脚本加执行权限:chmod +x reset_pin.sh
- 创建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
- 启用并启动服务:
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
相关产品推荐
相关产品推荐

