[英]process communication with signls
我正在尝试编写一个具有一些进程的C程序。 其中之一向所有其他进程发送SIGRTMIN和SIGRTMAX范围内的随机信号,但我希望该信号在主进程中被忽略。我使用全局变量让SIG_IGN忽略了随机信号。 它看起来无济于事,因为当想要忽略第一个随机信号时,主电源会以实时信号停止。
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
volatile sig_atomic_t disarming_signal = 0;
void disarming_handler (int sig) {
disarming_signal = sig;
fprintf(stderr,"signal %d is handeled", disarming_signal);
}
int rand_range(int min_n, int max_n){
int rand_n = rand() % (max_n - min_n) + min_n;
return rand_n;
}
int sethandler (void (*f)(int), int sigNo) {
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = f;
if (-1==sigaction(sigNo, &act, NULL))
return -1;
return 0;
}
void sigchld_handler(int sig){
pid_t pid;
for(;;){
pid=waitpid(0, NULL, WNOHANG);
if(pid==0) return;
if(pid<=0) {
if(errno==ECHILD) return;
perror("waitpid:");
exit(EXIT_FAILURE);
}
}
}
void usage(){
fprintf(stderr,"USAGE: sappartherroryst n\n");
fprintf(stderr,"n - number of Therrorysts\n");
}
void therroryst_work(){
int s,k,t;
srand(getpid());
s = rand_range(SIGRTMIN, SIGRTMAX);
t = rand_range(10, 20);
k = t;
if(sethandler(disarming_handler, s)){
perror("Seting therroryst handeler");
exit(EXIT_FAILURE);
}
fprintf(stderr, "[%d] I am therroryst. My disarming signal is [%d]. I will wait [%d] Sec.\n", getpid(), s, t);
while(k>0) {
k=sleep(k);
if(disarming_signal == s){
fprintf(stderr, "I got signal [%d]\n.",disarming_signal);
return ;
}
}
fprintf(stderr, "[%d] KABOOM\n",getpid());
exit(EXIT_SUCCESS);
}
void create_therrorysts(int n){
while(n-->0){
switch(fork()) {
case 0:
therroryst_work();
exit(EXIT_SUCCESS);
case -1:
perror("Fork():");
exit(EXIT_FAILURE);
}
}
}
void sapper_work(){
int sig_dis, i;
struct timespec t, tn = {1,0};
fprintf(stderr,"[%d] I am sapper.\n", getpid());
for(i=0;i<10;i++){
for(t=tn;nanosleep(&t,&t););
sig_dis = rand_range(SIGRTMIN, SIGRTMAX);
if(kill(0, sig_dis)<0){
perror("Disarming_send\n");
exit(EXIT_FAILURE);
}
fprintf(stderr,"I sended signal [%d].\n",sig_dis);
disarming_signal = sig_dis;
}
fprintf(stderr, "end of sending");
exit(EXIT_SUCCESS);
}
void create_sapper(){
switch(fork()) {
case 0:
sapper_work();
exit(EXIT_SUCCESS);
case -1:
perror("Fork():");
exit(EXIT_FAILURE);
}
}
int main(int argc, char** argv){
int n;
pid_t pid;
if(argc != 2){
usage();
return EXIT_FAILURE;
}
n = atoi(argv[1]);
if(n <= 0){
usage();
return EXIT_FAILURE;
}
if(sethandler(sigchld_handler, SIGCHLD)) {
perror("Seting parent SIGCHLD:");
exit(EXIT_FAILURE);
}
create_therrorysts(n);
create_sapper();
sleep(5);
for(;;) {
if(sethandler(SIG_IGN, disarming_signal)){
perror("Seting parent disarming111");
exit(EXIT_FAILURE);
}
}
for(;;){
pid=wait(NULL);
if(pid<0)
switch (errno){
case ECHILD:
return EXIT_SUCCESS;
case EINTR:
continue;
default:
perror("wait:");
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}
您在create_sapper之后和sethandler(IGN)之前有sleep(5)。 这意味着很有可能在您的主进程忽略该信号之前就已发送该信号。
编辑:从乔纳森·莱弗勒(Jonathan Leffler)添加评论到此答案中,因为它同等(或更重要)地很重要:
即使您将sleep()放在该循环之后,设置信号处理程序也存在问题-父项无法看到子项作为disarming_signal选择的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.