首页 > 解决方案 > 编写 10 秒后关闭的 C 程序

问题描述

我想编写一个运行指定秒数的 C 程序,
比如 10 秒然后退出。代码应该设置一个中断,
在指定的时间过去后关闭。

这是我的尝试。但我不确定 SIGALRM 是否是正确的方法。
SIGALRM 可以称为中断吗?

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

void handler()
{
    _exit(0);
}
int main()
{
    signal(SIGALRM, handler);
    alarm(10);
    for (;;);  /* You can assume that for(;;); is just a dummy code. The main idea is to insert something into code. Whatever code it may be so that it stops after 10 seconds –  */
        return 0;
}

有什么建议/替代方案/更好的方法来实现这一目标吗?

标签: csignalsinterrupt

解决方案


“信号”与“中断”的措辞并不完全清楚。信号可以中断系统调用,所以信号在这个意义上就是中断。但是信号不是硬件中断。当您使用操作系统时,普通程序通常无法直接访问硬件中断。

_exit如果您的程序需要完成任务或清理某些内容,从信号处理程序调用可能会出现问题。

我建议通过设置一个标志来实现一个优雅的结束。此外,我建议使用sigaction而不是,因为使用此函数设置signal的语义和信号处理程序是依赖于实现的。signal

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

static volatile sig_atomic_t timeout = 0;

void handler(int sig)
{
    (void) sig;
    timeout = 1;
}

int main(void)
{
    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = handler;
    if(sigaction(SIGALRM, act, NULL) < 0)
    {
        // handle error
    }
    alarm(10);
    while(!timeout /* and maybe other conditions */)
    {
        // do something, handle error return codes and errno (EINTR)
        // check terminate flag as necessary
    }

    // clean up if necessary

    return 0;
}

解释(根据评论中的要求)

static volatile sig_atomic_t timeout = 0;

sig_atomic_t是一种即使在信号产生异步中断的情况下也能保证原子访问的类型。这意味着对变量的访问不能在两者之间中断,即软件永远不会看到部分修改的值。(见https://en.cppreference.com/w/c/program/sig_atomic_t

volatile通知编译器不要优化对变量的访问。这是必要的,因为信号处理程序可能会在主函数运行旨在检查标志的循环时修改值。否则,编译器可能会优化循环条件外的访问,并且只在循环之前执行一次,因为在循环内永远不会修改变量。(见https://en.cppreference.com/w/c/language/volatile


推荐阅读