问题描述
我想创建一个使用fork的简单程序,并创建一个子进程,使用暂停来等待它.我希望这个子进程在从父进程收到特定信号后启动.我写的代码:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t c = fork();
if (c == 0) {
pause();
printf("signal was given");
}
if (c > 0)
kill(c, SIGINT);
return 0;
}
我认为kill给具有pid c(child)的进程一个特定的信号,我认为暂停只是在等待一个取消暂停该进程的信号.但是,在这种情况下,运行该程序没有任何结果.我还尝试使用signal(SIGINT, handler)
向子级添加信号捕获功能,并创建一个打印所需结果的处理程序功能,但该功能仍无法正常工作.有什么想法吗?
如果将默认配置为杀死该进程的SIGINT
发送给既不阻塞也不处理的进程,该进程将死亡. /p>
如果您想让信号中断像pause()
这样的阻塞调用,则需要有一个处理程序.
但是简单地安装一个处理程序就会引入竞争条件:
if (c == 0 ){
//< if the signal arrives here the child dies
signal(SIGINT, handler);
//< if the signal arrives here then nothing happens except the handler is run
pause(); //< if the handler arrives here then pause gets interrupted
printf("signal was given\n");
exit(0);
}
要消除比赛条件,您需要
- 阻止父母中的信号,以便孩子从被阻止的信号开始
- 在子代中安装处理程序
- 以一个原子步骤取消对信号和
pause()
的阻止
要一步一步实现3.,您需要sigsuspend()
而不是pause()
.
#include <stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
void handler(int Sig){}
int main()
{
sigset_t sigint, oldmask; sigemptyset(&sigint); sigaddset(&sigint, SIGINT);
sigprocmask(SIG_BLOCK, &sigint, &oldmask);
pid_t c=fork();
if(0>c) return perror(0),1;
if (c==0){
signal(SIGINT, handler);
sigdelset(&oldmask,SIGINT); /*in (the unlikely) case the process started with SIGINT blocked*/
sigsuspend(&oldmask);
printf("signal was given\n");
exit(0);
}
kill(c,SIGINT);
wait(0);
return 0;
}
或者,您可以使用sigwait()
并完全不需要处理程序:
#include <stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
int main()
{
sigset_t sigint, oldmask; sigemptyset(&sigint); sigaddset(&sigint, SIGINT);
sigprocmask(SIG_BLOCK, &sigint, &oldmask);
pid_t c=fork();
if(0>c) return perror(0),1;
if (c==0){
int sig; sigwait(&sigint,&sig);
printf("signal was given\n");
exit(0);
}
kill(c,SIGINT);
wait(0);
return 0;
}
I want to create a simple program that uses fork and creates a child process which with the use of pause is waiting. I want this child process to start after it gets a specific signal from father process. Code I've written:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t c = fork();
if (c == 0) {
pause();
printf("signal was given");
}
if (c > 0)
kill(c, SIGINT);
return 0;
}
I think kill gives a specific signal to a process with pid c(child) and I thought that pause just waits for a signal to unpause that process. However in this case running this program has no results. I have also tried adding a signal catching function to the child using signal(SIGINT, handler)
and creating a handler function that prints the desired result but it is still not working. Any ideas?
If you send SIGINT
, whose default disposition is to kill the process, to a process that neither blocks it nor handles it, the process will die.
If you want the signal to interrupt blocking calls like pause()
, it needs to have a handler.
But simply installing a handler introduces race conditions:
if (c == 0 ){
//< if the signal arrives here the child dies
signal(SIGINT, handler);
//< if the signal arrives here then nothing happens except the handler is run
pause(); //< if the handler arrives here then pause gets interrupted
printf("signal was given\n");
exit(0);
}
To eliminate the race conditions, you need to
- block the signal in the parent so that the child starts with the signal blocked
- install the handler in the child
- unblock the signal and
pause()
in one atomic step
To achieve 3. in one step, you need sigsuspend()
instead of pause()
.
#include <stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
void handler(int Sig){}
int main()
{
sigset_t sigint, oldmask; sigemptyset(&sigint); sigaddset(&sigint, SIGINT);
sigprocmask(SIG_BLOCK, &sigint, &oldmask);
pid_t c=fork();
if(0>c) return perror(0),1;
if (c==0){
signal(SIGINT, handler);
sigdelset(&oldmask,SIGINT); /*in (the unlikely) case the process started with SIGINT blocked*/
sigsuspend(&oldmask);
printf("signal was given\n");
exit(0);
}
kill(c,SIGINT);
wait(0);
return 0;
}
Alternatively, you can use sigwait()
and drop the need for a handler altogether:
#include <stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<signal.h>
int main()
{
sigset_t sigint, oldmask; sigemptyset(&sigint); sigaddset(&sigint, SIGINT);
sigprocmask(SIG_BLOCK, &sigint, &oldmask);
pid_t c=fork();
if(0>c) return perror(0),1;
if (c==0){
int sig; sigwait(&sigint,&sig);
printf("signal was given\n");
exit(0);
}
kill(c,SIGINT);
wait(0);
return 0;
}
这篇关于在子进程中使用信号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!