父进程定时器回调函数中fork,子进程execl,子进程无法接收到SIGALRM信号
父进程代码
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int execTime = 0;
void signalFunc()
{
printf("test_time\n");
if (!execTime++)
{
int pid = fork();
if (!pid)
{
alarm(0);
execl("/home/fic091/code/test_child", "/home/fic091/code/test_child", NULL);
}
}
alarm(10);
}
int main()
{
printf("father pid: %d\n", getpid());
signal(SIGALRM, signalFunc);
alarm(2);
while(1)
{
pause();
}
return 0;
}
子进程代码
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int execTime = 0;
void signalFunc()
{
printf("test_child\n");
alarm(2);
}
int main()
{
printf("child pid: %d\n", getpid());
signal(SIGALRM, signalFunc);
alarm(10);
while(1)
{
// sleep(2);
// signalFunc();
pause();
}
return 0;
}
子进程一直pause,通过命令行kill发送SIGALRM信号,STRACE监控,子进程没有接收到信号
在你的程序中,子进程无法接收到SIGALRM
信号的主要原因是与UNIX/Linux的信号处理和进程隔离机制有关。当你从父进程的定时器回调函数中调用fork()
创建一个子进程时,子进程会继承父进程的各种状态,包括信号处理设置(handler),但是关于信号的阻塞状态(blocked signals)和挂起信号(pending signals)则遵循不同的规则。
具体来说,子进程继承父进程的信号处理器(signal handler),但不会继承父进程的挂起信号(即那些在父进程中已经发出但尚未处理的信号)。SIGALRM
信号是在父进程中发出的,用于触发定时器回调,并且在该回调函数中调用了fork()
。在fork()
调用时,父进程中的SIGALRM
信号已经是挂起状态(如果回调在信号到来时已经被触发),但这个挂起状态不会被传递给子进程。
因此,即使子进程设置了与SIGALRM
相关联的信号处理器,由于该信号没有在子进程中挂起,子进程永远不会因为这个信号而被唤醒。当你通过命令行使用kill
命令向子进程发送SIGALRM
信号时,如果子进程已经正确设置了信号处理器,那么它会收到并处理这个信号。
解决或验证的方法:
kill
命令手动发送信号:如你所做的,使用kill -SIGALRM <子进程PID>
来测试子进程是否能响应SIGALRM
信号。这应该能看到子进程的处理函数被调用。main
函数开始时,添加一些代码来确认信号处理器确实已经被设置。strace
或gdb
来跟踪信号处理和fork()
调用的行为。最后,如果你的目标是让子进程定时执行某些操作,你可能需要重新考虑设计,因为基于信号和fork()
的组合可能会导致复杂的同步和竞态条件问题。你可以考虑使用其他同步机制(如管道、消息队列、条件变量等)或者使用专门的定时器API(如POSIX定时器)来简化你的程序。
#include <stdio.h> #include <stdlib.h> int main(void) { pid_t pid; pid = fork(); if (pid < 0) { exit(1); } else if (pid > 0) { printf("Parent\n");
问题内容: 我知道fork()对于子进程和父进程返回的结果有所不同,但是我无法找到有关此情况的信息。子进程如何从fork接收返回值0?在调用堆栈方面有什么区别?据我了解,对于父母来说,是这样的: 父进程-调用fork-> system_call-调用fork-> fork执行-返回-> system_call-返回->父进程。 在子进程中会发生什么? 问题答案: %人叉 返回值 indi- cat
问题内容: 我有一个使用Qt Framework的简单程序。它使用QProcess执行RAR并压缩一些文件。在我的程序中,我正在捕获并在发生代码时做一些事情: 当发生时,我检查RAR进程是否完成,如果不是,我将等待它……问题是(我认为)RAR进程也得到了我的程序所需要的,并且在压缩之前退出了所有的文件。 有没有一种方法可以运行RAR进程,以便在程序接收到它时不接收它? 谢谢 问题答案: 如果要在U
我必须分叉两个子进程,其中SIGINT命令被阻塞,但其中一个在接收到SIGTERM信号时应该解除阻塞,而另一个子进程和父进程都会打印它们的PID,作为相同SIGTERM信号的结果。第二个子进程应立即终止,但父进程应等待其子进程结束,然后停止。 我刚开始在Linux中学习C编程,但我并不真正理解分叉和信号是如何工作的。据我所知,我编写的这段代码将派生一个进程,子进程将阻止Ctrl-C命令,整个过程将
我尝试使用C语言中的< code>fork()函数处理Linux中的多个进程,这是我的代码: 现在让我们假设父进程ID为100,两个子进程(p1, p2)ID为101 相反,我看到了一些不同的东西,两个子进程具有相同的PPID,但第一个进程具有与之不同的PID。这是我得到的示例输出: 我的问题是,两个子进程的父PID不应该是3383吗?希望有人能解释这一切在这里是如何运作的,以及我做错了什么(或想
问题内容: 是否可以从Shell脚本中的父进程ID获取子进程ID? 我有一个要使用Shell脚本执行的文件,这会导致一个新进程 process1 (父进程)。这个 过程1 已经分叉的另一个进程 过程2 (子进程)。使用脚本,我可以使用以下命令获取 process1 的pid : 但我无法获取子进程的pid。 问题答案: 只需使用: