如何解决如何在 C 中使用用户定义的信号处理程序而不是 SIGCONT 恢复停止的进程?
我正在尝试使用 2 个进程和 2 个用户定义的信号处理程序来玩“乒乓”。
问题是由于某种原因,在我raise(SIGSTOP)
子进程为了让父进程启动之后,我无法继续子进程的运行,即使我发送了一个{{ 1}} 在我看来,应该再次重新运行该过程。
这里有什么问题?
kill(getppid(),SIGUSR1
这段代码的输出是:
void handle_siguser1(int signal_id);
void handle_siguser2(int signal_id);
enum {CHILD = 0,PARENT = 1};
/************************* Functions Implementations *************************/
int main()
{
/* create a child process */
pid_t pid = fork();
while (1)
{
/* returned to the newly created child process. */
if (CHILD == pid)
{
printf("Child registers its signal handler\n");
signal(SIGUSR1,handle_siguser1);
printf("Child stops to return the control to the parent\n");
raise(SIGSTOP);
}
/* returned to parent */
else
{
printf("Parent process started running\n");
printf("Parent stops to let child to register signal\n");
sleep(1);
printf("Parent registers its signal handler\n");
signal(SIGUSR2,handle_siguser2);
printf("Parent waits child to be stopped\n");
waitpid(getpid(),NULL,WUNTRACED);
printf("Parent starts child process\n");
kill(getpid(),SIGUSR1);
}
}
return 0;
}
/******************************************************************************/
void handle_siguser1(int signum)
{
printf("PONG\n");
sleep(2);
kill(getppid(),SIGUSR2);
}
/******************************************************************************/
void handle_siguser2(int signum)
{
printf("PING\n");
sleep(2);
kill(getpid(),SIGCONT);
}
/******************************************************************************/
谢谢。
解决方法
你有各种各样的问题。忽略 you should not use printf()
in a signal handler 的问题,事实证明使用 SIGUSR1 和 SIGUSR2 是不必要的和令人困惑的,尤其是因为错误的进程被发出信号。显示信号处理后,您需要将 pid
变量设为全局变量,并向其发送信号,而不是 getpid()
或 getppid()
(尤其是 getppid()
会返回启动程序的进程)。
事实上,SIGUSR1 和 SIGUSR2 是无关紧要的。这是一些工作代码。它使用我在 GitHub 上的 SOQ(堆栈溢出问题)存储库中提供的一些代码作为 src/libsoq 子目录中的文件 stderr.c
和 stderr.h
。我使用了 err_setlogopts()
以便通过 err_remark()
和 err_sysrem()
写入消息的进程识别 PID 以及调用时以毫秒为单位的时间。这非常有帮助。它向我展示的一件事是从未调用过信号处理程序。
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include "stderr.h"
enum {CHILD = 0,PARENT = 1};
static pid_t pid;
int main(void)
{
err_setarg0("sigcont43");
err_setlogopts(ERR_PID|ERR_MILLI);
pid = fork();
for (int i = 0; i < 3; i++)
{
if (CHILD == pid)
{
err_remark("Child stops to return the control to the parent\n");
err_remark("Child about to invoke raise(SIGSTOP)\n");
raise(SIGSTOP);
err_remark("Child back from raise(SIGSTOP)\n");
}
else
{
err_remark("Parent process started running\n");
err_remark("Parent stops to let child to register signal\n");
sleep(1);
err_remark("Parent returns from sleep(1)\n");
err_remark("Parent waits child to be stopped\n");
int status = 0;
int corpse = waitpid(pid,&status,WUNTRACED);
err_remark("Parent collects stopped child: corpse = %d,status = 0x%.4X\n",corpse,status);
err_remark("Parent starts child process\n");
err_remark("Parent sends SIGCONT to PID %d\n",pid);
errno = 0;
int rc = kill(pid,SIGCONT);
err_sysrem("Parent sent SIGCONT to PID %d (rc = %d): ",pid,rc);
}
}
return 0;
}
代码保留了与信号处理程序无关的原始消息(因为不再有任何信号处理程序),但添加了更多信息性消息。它还捕获并报告许多系统函数的返回值。这有助于诊断一些问题。我还将无限 while
循环更改为 3 次迭代 for
循环。
示例输出(测试程序名称sigcont43
):
$ sigcont43
sigcont43: 2021-06-28 11:40:03.305 - pid=83078: Parent process started running
sigcont43: 2021-06-28 11:40:03.306 - pid=83078: Parent stops to let child to register signal
sigcont43: 2021-06-28 11:40:03.305 - pid=83079: Child stops to return the control to the parent
sigcont43: 2021-06-28 11:40:03.306 - pid=83079: Child about to invoke raise(SIGSTOP)
sigcont43: 2021-06-28 11:40:04.306 - pid=83078: Parent returns from sleep(1)
sigcont43: 2021-06-28 11:40:04.306 - pid=83078: Parent waits child to be stopped
sigcont43: 2021-06-28 11:40:04.306 - pid=83078: Parent collects stopped child: corpse = 83079,status = 0x117F
sigcont43: 2021-06-28 11:40:04.306 - pid=83078: Parent starts child process
sigcont43: 2021-06-28 11:40:04.306 - pid=83078: Parent sends SIGCONT to PID 83079
sigcont43: 2021-06-28 11:40:04.307 - pid=83079: Child back from raise(SIGSTOP)
sigcont43: 2021-06-28 11:40:04.307 - pid=83079: Child stops to return the control to the parent
sigcont43: 2021-06-28 11:40:04.307 - pid=83078: Parent sent SIGCONT to PID 83079 (rc = 0): error (0) Undefined error: 0
sigcont43: 2021-06-28 11:40:04.307 - pid=83078: Parent process started running
sigcont43: 2021-06-28 11:40:04.307 - pid=83078: Parent stops to let child to register signal
sigcont43: 2021-06-28 11:40:04.307 - pid=83079: Child about to invoke raise(SIGSTOP)
sigcont43: 2021-06-28 11:40:05.309 - pid=83078: Parent returns from sleep(1)
sigcont43: 2021-06-28 11:40:05.309 - pid=83078: Parent waits child to be stopped
sigcont43: 2021-06-28 11:40:05.309 - pid=83078: Parent collects stopped child: corpse = 83079,status = 0x117F
sigcont43: 2021-06-28 11:40:05.309 - pid=83078: Parent starts child process
sigcont43: 2021-06-28 11:40:05.309 - pid=83078: Parent sends SIGCONT to PID 83079
sigcont43: 2021-06-28 11:40:05.309 - pid=83079: Child back from raise(SIGSTOP)
sigcont43: 2021-06-28 11:40:05.309 - pid=83078: Parent sent SIGCONT to PID 83079 (rc = 0): error (0) Undefined error: 0
sigcont43: 2021-06-28 11:40:05.309 - pid=83079: Child stops to return the control to the parent
sigcont43: 2021-06-28 11:40:05.309 - pid=83078: Parent process started running
sigcont43: 2021-06-28 11:40:05.309 - pid=83079: Child about to invoke raise(SIGSTOP)
sigcont43: 2021-06-28 11:40:05.309 - pid=83078: Parent stops to let child to register signal
sigcont43: 2021-06-28 11:40:06.309 - pid=83078: Parent returns from sleep(1)
sigcont43: 2021-06-28 11:40:06.309 - pid=83078: Parent waits child to be stopped
sigcont43: 2021-06-28 11:40:06.309 - pid=83078: Parent collects stopped child: corpse = 83079,status = 0x117F
sigcont43: 2021-06-28 11:40:06.309 - pid=83078: Parent starts child process
sigcont43: 2021-06-28 11:40:06.309 - pid=83078: Parent sends SIGCONT to PID 83079
sigcont43: 2021-06-28 11:40:06.309 - pid=83078: Parent sent SIGCONT to PID 83079 (rc = 0): error (0) Undefined error: 0
sigcont43: 2021-06-28 11:40:06.309 - pid=83079: Child back from raise(SIGSTOP)
$
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。