Raspberry Pi 在 C 中按 CTRL+C 清除退出

Raspberry Pi clean exit on CTRL+C in C

首先,让我道歉,因为我看到类似的问题在过去已经发布了很多次。但是,由于我对C非常陌生,我需要帮助确认这一点。

如果我用 CTRL+C 中断我的程序,我试图确保它留下一个干净的 gpio。在 python 或 java 中很容易完成,但事实证明 C 对我来说更难破解,因为我被引导相信 C 中不存在 try-catch-finally。谷歌搜索,我发现我认为可能是解决方案,但我没有经验,我不确定它是否正确完成。这是我的代码:

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

void CleanGPIO() {
    pinMode(1,INPUT);
}
int main()
{

    wiringPiSetup();

    signal(SIGINT, CleanGPIO);
    pinMode(1, PWM_OUTPUT);

    for (int i = 0; i < 1024; ++i) {
        pwmWrite(1, i);
        delay(1);
    }
    for (int i = 1023; i >= 0; --i) {
        pwmWrite(1, i);
        delay(1);
    }
    pinMode(1,INPUT);
    return 0;
}

我已经对其进行了测试并且它按预期工作(在我用 CTRL+C 中断它之后,引脚 1 被设置为 IN),但我担心这是否是安全的方法,如果有有更好的解决方案。

您的解决方案几乎是正确的。您还应该调用 exit 以强制程序终止(假设您想立即终止)。 exit 调用带有一个参数,该参数是调用者 return 的退出状态(例如 shell)。对于异常终止,这应该是非零的。

所以,应该是:

void CleanGPIO() {
    pinMode(1,INPUT);
    exit(1);
}

如果您不想从处理程序中退出,而是想以更可控的方式从 main 中退出,您可以改为设置标志并检查循环内的标志值。

从信号处理程序调用任何未指定为信号安全的函数是未定义的行为。我想关于 pinMode.

没有这样的保证

正确的方法是设置一个 volatile int 标志,您可以在主循环中定期检查。

volatile int terminating = 0;

void terminate(int sign) {
  signal(SIGINT, SIG_DFL);
  terminating = 1;
}


int main() {

  for (...) {
    if (terminating) {
       // cleanup
       exit(1);
    }

  }

}

处理程序内部对 signal 的调用是为了允许使用第二个 ctrl+c 强制终止程序,以防适当的清理花费太长时间或因任何原因卡住。