这个程序已经用C编写并在ubuntu上编译。 我的脚本创建了两个孩子。 第一个记录他的pid在静态变量。 创建第二个孩子并向父母发送信号。
父母接收信号并在此回合向第一个孩子发送信号。 但是第一个孩子没有收到这个信号。函数sig_handlerr永远不会被调用。
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <time.h>
# include <signal.h>
# include <sys/mman.h>
static pid_t* pidt;
// handler signal père
void sig_handler(int signo)
{
if (signo == SIGUSR1) {
printf("SIG HANDLER received SIGUSR1 by process %d\n", getpid());
printf("-> Envoie du signal SIGUSR1 au fils %d\n", pidt[0]);
// le père envoie un signal au premier fils
kill(pidt[0], SIGUSR1);
}
}
// handler signal fils
void sig_handlerr(int signo)
{
if (signo == SIGUSR1) {
printf("SIG HANDLER2 received SIGUSR1 by process %d\n", getpid());
}
}
int main(int argc, char* argv[]) {
printf("pid du processus père %d\n", getpid());
pidt = mmap(NULL, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (fork()==0) {
printf("1 processus fils %d\n", getpid());
pidt[0]=getpid();
printf("pid enregistré= %d\n", pidt[0]);
signal(SIGUSR1, sig_handlerr);
exit(0);
}
wait(NULL);
signal(SIGUSR1, sig_handler);
if (fork()==0) {
printf("2 processus fils %d", getpid());
// il envoie un signal SIGUSR1 au processsu père
printf("-> envoie SIGUSR1 au père %d\n", getppid());
kill(getppid(), SIGUSR1); // envoie un signal SIGUSR1 au processus père
exit(0);
}
wait(NULL);
printf("\n\n------ Fin du programme -------");
return EXIT_SUCCESS;
}
你可以解释一下为什么请你?
答案 0 :(得分:6)
你有很多错误,其中最重要的是:
您的第一个子进程在调用signal
后立即退出,并且父进程在开始第二个进程之前等待它。这意味着,当父母到处向第一个孩子发送信号时,第一个孩子不再在那里接收它。使用sigsuspend
使父母和第一个孩子一直睡到信号到达,并且只有在完成所有其他工作后才在父母中调用wait
。
在信号处理程序中调用printf
通常是不安全的。但是,如果程序在信号到达时在sigsuspend
内休眠,那么它就可以了。使用sigprocmask
确保SIGUSR1
只能在sigsuspend
来电期间投放。 (您可以在Linux signal-safety(7)
联机帮助页中找到可在信号处理程序中安全调用的函数列表。)
父级应该只保存fork
返回给它的子PID,而不是使用共享内存段做聪明的事情。
您应该使用sigaction
,而不是signal
。
您没有检查是否有任何错误。
您没有检查子进程是否已成功退出。
答案 1 :(得分:0)
好吧,父母程序在第一个孩子结束之后很久才发送任何信号(因此没有机会代表他们行事)。它只是创建一个子进程,将其pid注册到数组pidt[0]
中(在与其子进程共享的内存段中为此数组)并为SIGUSR1
信号安装信号处理程序(没有用,如它exit()
就在那之后(它几乎没有时间接收信号,但是阅读更多,它不能)。然后,父 wait()
是第一个孩子的死者(这是错的)......发生了......所以之后只有一个过程。
父进程然后安装信号处理程序并创建第二个子进程。子进程是kill()
,一旦执行就从信号处理程序的输出中看到它。由于没有第一个孩子活着,因此没有机会接收到信号,也没有机会看到预期的输出(你不会说这个输出是预期的,但我猜到了:))
$ a.out
pid du processus père 3095
1 processus fils 3097
pid enregistré= 3097
pid du processus père 3095
2 processus fils 3098-> envoie SIGUSR1 au père 3095
pid du processus père 3095
SIG HANDLER received SIGUSR1 by process 3095
-> Envoie du signal SIGUSR1 au fils 3097
------ Fin du programme -------$ _
(看,在最后一条消息的末尾没有\n
,所以你会立即得到提示)
父母最终杀死孩子可以使父母用来等待第二个孩子被中断的wait()
系统调用(你不要检查孩子的返回值)因此,最终的printf()
可以在第二个孩子的实际退出之前执行(孩子除了exit()
之外什么都不做,所以在最后退出之后什么也看不到孩子,但你也要检查这个。)
关于在父信号处理程序中发送的信号....三思:你已经启动了第二个孩子(这是向父母发送第一个信号的孩子)在第一个孩子{{1>之后} ,因此它无法接收信号。您不会检查exit(2)
系统调用的结果代码,因为它会告诉您TARGET进程不存在。
以下代码修复损坏的部分......首先,父母不能等待孩子死亡。在安装信号处理程序后,孩子必须活着并等待信号(这是kill(2)
所做的,等待信号到达):
pause(2)
您将获得以下输出:
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <time.h>
# include <signal.h>
# include <sys/mman.h>
static pid_t* pidt;
// handler signal père
void sig_handler(int signo)
{
if (signo == SIGUSR1) {
printf("SIG HANDLER received SIGUSR1 by process %d\n", getpid());
printf("-> Envoie du signal SIGUSR1 au fils %d\n", pidt[0]);
// le père envoie un signal au premier fils
kill(pidt[0], SIGUSR1);
}
}
// handler signal fils
void sig_handlerr(int signo)
{
if (signo == SIGUSR1) {
printf("SIG HANDLER2 received SIGUSR1 by process %d\n", getpid());
}
}
int main(int argc, char* argv[]) {
printf("pid du processus père %d\n", getpid());
pidt = mmap(NULL, sizeof(pid_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
if (fork()==0) {
printf("1 processus fils %d\n", getpid());
pidt[0]=getpid();
printf("pid enregistré= %d\n", pidt[0]);
signal(SIGUSR1, sig_handlerr);
pause();
exit(0);
}
signal(SIGUSR1, sig_handler);
if (fork()==0) {
printf("2 processus fils %d", getpid());
// il envoie un signal SIGUSR1 au processsu père
printf("-> envoie SIGUSR1 au père %d\n", getppid());
kill(getppid(), SIGUSR1); // envoie un signal SIGUSR1 au processus père
exit(0);
}
wait(NULL);
printf("\n\n------ Fin du programme -------");
return EXIT_SUCCESS;
}
(再次,在最后一条消息之后的提示:))
您的代码和我的代码之间存在差异,请注意差异:
$ a.out
pid du processus père 3301
2 processus fils 3304-> envoie SIGUSR1 au père 3301
pid du processus père 3301
1 processus fils 3303
pid enregistré= 3303
SIG HANDLER2 received SIGUSR1 by process 3303
pid du processus père 3301
SIG HANDLER received SIGUSR1 by process 3301
-> Envoie du signal SIGUSR1 au fils 3303
------ Fin du programme -------$ _