Linux 表示程序在每次执行时 return 没有相同的值
Linux signals program doesn't return the same value on each execution
我有这个代码:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
int cpt = 0;
void handler (int sig) {
cpt++ ;
}
int main() {
int i;
signal(SIGCHLD, handler);
for (i = 0; i < 5; i++) {
if (fork() == 0) {
exit(0);
}
}
while (wait(NULL) != -1) ;
printf("cpt = %d\n", cpt);
return 0;
}
根据我的理解,这个程序应该总是打印 cpt = 5
但是当我 运行 它在我的机器上时它 returns 不同的值 (3,4,5) 这是为什么?
SIGCHLD
信号有点滑稽,并不像您预期的那样工作:我们认为 我们应该每个 child 得到一个信号死亡,但事实并非如此。
相反,它是一种 level-triggered 东西,如果有 any un-waited-for child,它会以未知的间隔发送信号任.
在您提供的贯穿 wait()
的循环中,此循环在信号处理程序绕过它之前消耗了多个 children,因此通过处理程序的次数较少。
其他人指出您应该使用 volatile sig_atomic_t
变量,虽然这是个好主意,但这并不是您看到此行为的原因。
我相信获得保证 one-signal-per-child 的唯一方法是实际等待信号处理程序中的 child - 这使它看起来更像一个 edge-triggered 信号。
当然,您在信号处理程序中可以做的事情非常有限,所以如果您的应用程序已经有一个很好的等待 child 进程的方案,您可能不需要 SIGCHLD
处理程序。
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
static volatile sig_atomic_t cpt = 0;
static void handler(int sig) {
cpt++;
wait(NULL); // ADD ME
}
int main() {
int i;
signal(SIGCHLD, handler);
for (i = 0; i < 5; i++) {
if (fork() == 0) {
exit(0);
}
}
while (wait(NULL) != -1) ;
printf("cpt=%d\n", cpt);
return 0;
}
作为替代方案,如果 while()
循环不是那么紧密并且有其他处理(甚至是显式延迟),则不会出现竞争条件,您会看到所有五个 SIGCHLD
交付。
我有这个代码:
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
int cpt = 0;
void handler (int sig) {
cpt++ ;
}
int main() {
int i;
signal(SIGCHLD, handler);
for (i = 0; i < 5; i++) {
if (fork() == 0) {
exit(0);
}
}
while (wait(NULL) != -1) ;
printf("cpt = %d\n", cpt);
return 0;
}
根据我的理解,这个程序应该总是打印 cpt = 5
但是当我 运行 它在我的机器上时它 returns 不同的值 (3,4,5) 这是为什么?
SIGCHLD
信号有点滑稽,并不像您预期的那样工作:我们认为 我们应该每个 child 得到一个信号死亡,但事实并非如此。
相反,它是一种 level-triggered 东西,如果有 any un-waited-for child,它会以未知的间隔发送信号任.
在您提供的贯穿 wait()
的循环中,此循环在信号处理程序绕过它之前消耗了多个 children,因此通过处理程序的次数较少。
其他人指出您应该使用 volatile sig_atomic_t
变量,虽然这是个好主意,但这并不是您看到此行为的原因。
我相信获得保证 one-signal-per-child 的唯一方法是实际等待信号处理程序中的 child - 这使它看起来更像一个 edge-triggered 信号。
当然,您在信号处理程序中可以做的事情非常有限,所以如果您的应用程序已经有一个很好的等待 child 进程的方案,您可能不需要 SIGCHLD
处理程序。
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <stdlib.h>
static volatile sig_atomic_t cpt = 0;
static void handler(int sig) {
cpt++;
wait(NULL); // ADD ME
}
int main() {
int i;
signal(SIGCHLD, handler);
for (i = 0; i < 5; i++) {
if (fork() == 0) {
exit(0);
}
}
while (wait(NULL) != -1) ;
printf("cpt=%d\n", cpt);
return 0;
}
作为替代方案,如果 while()
循环不是那么紧密并且有其他处理(甚至是显式延迟),则不会出现竞争条件,您会看到所有五个 SIGCHLD
交付。