【问题标题】:Stop a While (True) with a signal用信号停止一段时间(真)
【发布时间】:2015-03-09 20:43:10
【问题描述】:

我在 c 中使用并发,我有一个进程池。为此,我将每个孩子都放在一个 While (True) 循环中。杀死孩子我正在使用全局变量和信号处理程序来修改它打破循环。

问题是,孩子们使用分配的内存,我想释放它。因此,使用来自父级的简单 SIGTERM 是行不通的。

全球:

int sigusr1_count = 0;

void SenalTerminacion() {
    ++sigusr1_count;
}

signal(SIGUSR1, SenalTerminacion);

孩子:

While (1) {
    if (sigusr1_count != 0) {
        break;
    }
    /* some calculations */
}
print("Hola Stack Overflow\n");
/* freeing memory */ 
exit(0);

父亲:

kill(pidChild, SIGUSR1);
wait(NULL);

如果我用 wait 注释掉该行,代码将起作用并显示消息。但如果我离开等待程序挂起。我可以想象孩子不会因为我不知道信号和等待的奇怪东西而结束。我有 n 个孩子。 先感谢您!

【问题讨论】:

  • 是否需要使用信号?您可以使用其他 IPC,例如管道或 unix 域套接字。
  • “分配的内存”是什么意思?只是malloc()free()?如果是这样,您可以使用SIGTERM,因为当操作系统清理进程时,所有内存都会自动释放。
  • 我正在这样做,而 valgrind 正在识别内存泄漏

标签: c signals wait


【解决方案1】:

sigusr1_count 可能被您的子/父进程缓存(在寄存器文件中 - 编译器这样做),而不是从内存中读取(或在子进程中完全编译为不变量)。将其标记为 volatile 以防止两者兼有:

volatile int sigusr1_count=0;

更好:考虑将信号量用于进程间信号,而不是使用繁忙的 while(1) 循环。

【讨论】:

  • 您是否尝试过使用信号量而不是繁忙循环在进程之间发出信号?如果您想要一个繁忙的循环,请尝试原子操作,否则我很难预测编译器将如何处理您对全局的引用。
【解决方案2】:

您的信号处理函数有错误的签名。它必须接受一个int 类型的参数,在该参数中它将接收调用它来处理的信号编号。它不需要使用这样提供的值,但它确实需要声明参数。

正如最初发布的那样,您的信号处理函数实现也是错误的。它执行了exit(0),这本身是可以的,但它会阻止您的子进程在处理信号后进行任何清理,退出处理函数除外。特别是,他们永远无法接通print() 电话。

当您尝试终止进程的子进程时,我无法准确解释发生了什么,但我最好的猜测是他们没有收到信号,因此当父进程尝试 wait() 时,它会无限期挂起等待子进程退出这永远不会发生。

在调用处理程序时,具有错误签名的信号处理程序可能会导致意外行为。无论如何,由于使用不兼容的参数调用 signal() 函数,整个程序会表现出未定义的行为。

无论如何,如果您仅在注释掉wait() 调用时才打印出一条消息,那么它可能是由父进程生成的。

【讨论】:

  • 我在信号中有一个打印,其中的代码正在被执行。
猜你喜欢
  • 1970-01-01
  • 2011-09-15
  • 2023-03-23
  • 2020-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-19
相关资源
最近更新 更多