gpt4 book ai didi

c - SIGALRM 警报仅跳过 getchar 一次

转载 作者:行者123 更新时间:2023-11-30 16:58:03 25 4
gpt4 key购买 nike

我只是使用函数alarm来跳过getchar,但有些事情进展不顺利,因为它只跳过一次,而我想要无限期地跳过。

示例:

#include <signal.h>

int duration = 2;

main() {
cicleProgram();
}

void cicleProgram(){

while(opcion != 'q' && opcion != 'Q'){

signal(SIGALRM, (void*)cicleProgram);
alarm(duration);

opcion = getchar();
}
}

我做错了什么?

最佳答案

您正在使用 cicleProgram() 作为信号处理程序(尽管它的类型错误 - 它应该采用 int 参数)。这意味着您永远不会从信号处理程序返回,直到您输入 qQ,并且系统可能会阻塞信号,直到第一个信号处理程序返回。所以,你永远不会收到第二个信号——它被阻止了。

使用单独的信号处理函数。另请参阅What is the difference between sigaction() and signal()?并优先使用 sigaction() 而不是 signal()

并使用int main(void)——至少有返回类型。即使是旧版(C99)标准也有这样的要求,更不用说当前的(C11)标准了。我们已经进入21世纪;不要用 20 世纪的 C 语言编写代码!

另请参阅How to avoid using printf() in a signal handler?有关在信号处理程序中可以执行哪些操作的信息。

<小时/>

Could I add some control in that "while" in order to evaluate the signal alarm and avoid the deadlock?

原始代码存在多个问题,并没有诊断出所有可能的问题。另一个问题是,如果警报触发,则无法再次设置警报,因此程序会陷入等待状态,直到您键入一个字符。

这是您使用的一些实验代码:

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

static int duration = 2;
static volatile sig_atomic_t alarm_fired = 0;

static void alarm_handler(int signum)
{
//signal(SIGALRM, alarm_handler);
write(STDOUT_FILENO, "Signalled!\n", 11);
alarm_fired = signum;
alarm(duration);
}

static void cicleProgram(void)
{
int opcion = 0;
while (opcion != 'q' && opcion != 'Q')
{
signal(SIGALRM, alarm_handler);
alarm(duration);
if ((opcion = getchar()) == EOF)
clearerr(stdin);
if (alarm_fired)
{
alarm_fired = 0;
printf("Alarm!\n");
}
printf("c = %d\n", opcion);
}
}

static void actionProgram(void)
{
struct sigaction sa = { 0 };
sa.sa_handler = alarm_handler;
sa.sa_flags = 0;
sigfillset(&sa.sa_mask);
sigaction(SIGALRM, &sa, 0);

int opcion = 0;
while (opcion != 'q' && opcion != 'Q')
{
alarm(duration);
if ((opcion = getchar()) == EOF)
clearerr(stdin);
if (alarm_fired)
{
alarm_fired = 0;
printf("Alarm!\n");
}
printf("c = %d\n", opcion);
}
}

int main(void)
{
printf("Using signal (q to quit):\n");
cicleProgram();
printf("Using sigaction (q to quit):\n");
actionProgram();
return 0;
}

有两个事件函数,每个函数都有一个循环。第一个基于您原来的 cicleProgram() 但该函数已被修改;它不再是信号处理程序。我在 Mac OS X(基于 BSD)上运行,这些系统不需要您在信号处理函数中重置 signal() 处理程序。第二个函数 actionProgram() 使用 sigaction() 而不是 signal()。它可能没有必要,但它给了你一些东西可以看。 sa.sa_flags 元素中缺少 SA_RESTART 意味着 read() 系统调用报告每次信号消失时它都被中断。 signal_handler() 中的代码不使用不允许的函数调用。

示例输出(程序名称al97):

$ ./al97
Using signal (q to quit):
Signalled!
Signalled!
Signalled!
Signalled!
WonderfulSignalled!

Alarm!
c = 87
c = 111
c = 110
c = 100
c = 101
c = 114
c = 102
c = 117
c = 108
c = 10
Signalled!
Signalled!
q
Alarm!
c = 113
Using sigaction (q to quit):
c = 10
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
Signalled!
Alarm!
c = -1
ASignalled!
Alarm!
c = -1
lso workingSignalled!
Alarm!
c = -1

c = 65
c = 108
c = 115
c = 111
c = 32
c = 119
c = 111
c = 114
c = 107
c = 105
c = 110
c = 103
c = 10
qSignalled!
Alarm!
c = -1

c = 113
$

运行过程中有一些相当长的暂停,但您可以在您的计算机上进行实验。您可能需要在 cicleProgram()alarm_handler() 函数中重新包含 signal() 并使用不同的处理程序(这不会影响使用 signal(),就像现在一样)用于 actionProgram()

关于c - SIGALRM 警报仅跳过 getchar 一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39114334/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com