gpt4 book ai didi

c - 信号处理程序在到达双 SIGINT 时终止主程序和所有分支

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

我真的不明白信号处理程序如何工作,尤其是与 fork 一起工作。所以我需要做这个练习,但我无法让它正常工作。

我的主程序创建了 5 个 fork,每个 fork 仅打印 10 条消息及其 pid。因此,程序的目的是,当我通过键盘(Ctrl-c)发送 SIGINT 信号时,它应该打印“单个 SIGINT 到达”,如果在一秒之间到达两个 SIGINT,它应该打印“双 SIGINT 到达”并应该终止整个节目。因此,当我启动程序时,它处理前两个 SIGINT(我在第一个 SIGINT 之后发送第二个 SIGINT 超过 1 秒),但它不处理单个 SIGINT,也不处理双 SIGINT。

所以我对信号非常困惑。 fork 继续标记消息。我将相同的处理程序加载到主进程和 fork 中,但是当到达双 SIGINT 时我应该怎么做才能终止所有 fork ?我应该在处理程序中调用killl 或其他函数来终止它们吗?

主要功能

 /* libraries... */

volatile sig_atomic_t double_sigint = 0;
int64_t time_diff = 0;

int main()
{
int i;
int pid;

sigset_t set;
struct sigaction sa;


/* mask all signals */
/*H*/ if(sigfillset(&set) == -1 )
/*A*/ {perror("sigfillset"); exit(errno);}
/*N*/
/*D*/ if(sigprocmask(SIG_SETMASK,&set,NULL) == -1)
/*L*/ {perror("sigfillset"); exit(errno);}
/*E*/
/*R*/ memset(&sa,0,sizeof(sa));
/*B*/
/*L*/ sa.sa_handler = handler;
/*O*/
/*C*/ if(sigaction(SIGINT, &sa, NULL) == -1)
/*K*/ {perror("sigaction"); exit(errno);}
/**/
/**/ /* unmask all signals */
/**/ if( sigemptyset(&set) == -1 )
/**/ {perror("sigepmtyset"); exit(errno);}
/**/
/**/ if(sigprocmask(SIG_SETMASK,&set,NULL) == -1 )
/**/ {perror("sigprocmask"); exit(errno);}



for(i=0;i<5;++i)
{
if((pid = fork()) == -1)
{ perror("rec:fork"); exit(errno); }

if(pid == 0)/* figlio */
{

/* SAME HANDLER BLOCK IS HERE */

foo(i);

return;

}
sleep(1);
}

return 0;
}

foo函数

 void foo(int i)
{
int k;

for(k=0; k<10; ++k)
{
printf("%d. fork %d. print\n", i, k);
sleep(1);
}
}

信号处理程序

  void handler (int signum) {

struct timespec sig1;
struct timespec sig2;

if(double_sigint == 0)
{
if(clock_gettime(CLOCK_REALTIME, &sig1))
{ perror("failed to get sig1 time"); exit(errno); }

write(1,"Received single SIGINT\n",18);

double_sigint = 1;

}
else if(double_sigint == 1)
{
if(clock_gettime(CLOCK_REALTIME, &sig2))
{ perror("failed to get sig2 time"); exit(errno); }

time_diff = (sig2.tv_sec - sig1.tv_sec) + (sig2.tv_nsec - sig1.tv_nsec)/1000000000;

if(time_diff < 1)
{
double_sigint = 2;
write(1,"Received double SIGINT\n",18);
_exit(EXIT_FAILURE);

}
else
{
sig1.tv_sec = sig2.tv_sec;
sig1.tv_nsec = sig2.tv_nsec;

write(1,"Received single SIGINT\n",18);

}

}

}

最佳答案

当您收到双 SIGINT 时,您仅使用 _exit(EXIT_FAILURE); 行终止父进程。您之前创建的 fork 不会被终止并继续运行,它们的父进程现在是 init 进程。

如果您希望所有子进程终止,则必须手动杀死它们。也许这篇文章会有所帮助:How to make child process die after parent exits

编辑:这不是问题,因为 Ctrl+C 向所有子级发送 SIGINT(请参阅评论)。对我有用的是:

  • 正如 William Pursell 的评论中所述,创建 sig1 和 sig2 全局变量。
  • 使父进程始终运行(只需在 return 语句前添加一个 while (1); 即可),因为一旦父进程终止,某些信号就不会被考虑在内。

关于c - 信号处理程序在到达双 SIGINT 时终止主程序和所有分支,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24840473/

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