gpt4 book ai didi

c - 运行 GeeksforGeeks 示例信号代码时仅接收父 printf

转载 作者:行者123 更新时间:2023-11-30 16:15:56 24 4
gpt4 key购买 nike

我试图将我的注意力集中在信号上,所以我首先在 GeeksforGeeks 信号页面上运行代码。在他们的页面上,它显示了来自父级和子级的输出,但是当我在 CLion 中运行时,9/10 次我只接收来自父级的输出,而子级不打印任何内容。 child 每隔一段时间就会打印一次,但我不知道为什么或如何让它持续打印。

https://www.geeksforgeeks.org/signals-c-set-2/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

void sighup();
void sigint();
void sigquit();

void main() {

int pid;

if ((pid = fork()) < 0) {

perror("fork");
exit(1);

}

if (pid == 0) {

signal(SIGHUP, sighup);
signal(SIGINT, sigint);
signal(SIGQUIT, sigquit);
for(;;)
;

}

else {

printf("\nPARENT: sending SIGUP\n\n");
kill(pid, SIGHUP);

sleep(3);
printf("\nPARENT: sending SIGINT\n\n");
kill(pid, SIGINT);

sleep(3);
printf("\nPARENT: sending SIGQUIT\n\n");
kill(pid, SIGQUIT);
sleep(3);

}

void sighup() {

signal(SIGHUP, sighup);
printf("CHILD: I have received a SIGHUP\n");

}

void sigint() {

signal(SIGINT, sigint);
printf("CHILD: I have received a SIGINT\n");

}

void sigquit() {

printf("My parent has killed me");
exit(0);

}

最佳答案

该代码充满了错误。您应该首先在编译器上启用警告。在 GCC 和 clang 上,这是通过传递标志 -pedantic 和警告级别来完成的。我建议使用 -Wall -Wextra -Werror — 这会给出相当严格的警告,而不会造成妨碍。

正如推荐中所述,前两个错误是原型(prototype)声明错误,以及 main 函数签名错误。

第二个错误是您无法在信号处理程序中安全地调用 printf(您会在代码中遇到这种情况,但这是错误的)。事实上,您可以在信号处理程序中安全执行的一组操作受到严格限制 - read the documentation carefully .

第三,代码重置处理程序的尝试失败了(至少是不必要的)。 如果您想重置处理程序,则需要传递SIG_DFL作为第二个参数,而不是自定义回调。文档中也对此进行了解释。

最后,不能保证子进程中的代码先于父进程中的代码执行,特别是不能保证信号处理程序会被设置。在我的测试中,尽管父代码中有 sleep 语句,但子代码最终从未被执行。这可能看起来很奇怪,但这是完全合法的,并且需要预料到。

将这些部分放在一起,我们得到以下内容,您可能会注意到它比您尝试过的非工作代码复杂得多。

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

static volatile sig_atomic_t child_signal;
static volatile sig_atomic_t setup_done = 0;

void child_signal_handler(int);
void parent_signal_handler(int);

int main() {
const int parent_pid = getpid();
int pid;

// Set up BEFORE calling `fork`
signal(SIGCHLD, parent_signal_handler);

if ((pid = fork()) < 0) {
perror("fork");
exit(1);
}

if (pid == 0) {
signal(SIGHUP, child_signal_handler);
signal(SIGINT, child_signal_handler);
signal(SIGQUIT, child_signal_handler);
kill(parent_pid, SIGCHLD);

for (;;) {
if (child_signal != 0) {
switch ((int) child_signal) {
case SIGHUP:
fprintf(stderr, "CHILD: I have received a SIGHUP\n");
break;
case SIGINT:
fprintf(stderr, "CHILD: I have received a SIGINT\n");
break;
case SIGQUIT:
fprintf(stderr, "My parent has killed me");
exit(1);
}
child_signal = 0;
}
}
} else {
while (! setup_done) { sleep(1); }

printf("\nPARENT: sending SIGUP\n");
kill(pid, SIGHUP);

sleep(1);
printf("\nPARENT: sending SIGINT\n");
kill(pid, SIGINT);

sleep(1);
printf("\nPARENT: sending SIGQUIT\n");
kill(pid, SIGQUIT);
}
}

void child_signal_handler(int signo) {
child_signal = signo;
}

void parent_signal_handler(int signo) {
if (signo == SIGCHLD) setup_done = 1;
}

关于c - 运行 GeeksforGeeks 示例信号代码时仅接收父 printf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56915207/

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