我正在练习使用unix信号编程,我是新手, 所以我写了以下程序:http://wklej.org/id/2253905/,我正按照以下方式进行编译:gcc -Wall -o signals signals.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
void child_work(int l);
void create_children(int n, int l);
void parent_work(int k, int p);
int sethandler( void (*f)(int), int sigNo);
void child_handler(int sig);
void parent_handler(int sig);
void sigchld_handler(int sig);
void usage(void);
volatile sig_atomic_t last_signal = 0;
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)
{
printf("[%d] No more children parent quits.",getpid());
exit(EXIT_SUCCESS);
}
perror("waitpid:");
exit(EXIT_FAILURE);
}
}
}
void child_handler(int sig)
{
printf("[%d] received signal %d\n", getpid(), sig);
last_signal = sig;
if(last_signal==SIGUSR1)
if(0==kill(0,SIGUSR2))
printf("[%d] SENDING signal %d\n", getpid(), SIGUSR2);
else
perror("kill:");
}
void parent_handler(int sig) {
printf("[%d] received signal %d\n", getpid(), sig);
last_signal = sig;
}
void child_work(int t)
{
int s;
srand(getpid());
s=rand()%(t-1)+2;
struct timespec tt, tn = {s,0};
for(tt=tn;nanosleep(&tt,&tt);)
if(EINTR!=errno)
perror("nanosleep:");
printf("[%d] dies",getpid());
exit(EXIT_SUCCESS);
}
void create_children(int n, int t)
{
while (n-->0)
{
switch (fork())
{
case 0:
if(sethandler(child_handler,SIGUSR1))
{
perror("Seting child SIGUSR1:");
exit(EXIT_FAILURE);
}
if(sethandler(child_handler,SIGUSR2))
{
perror("Seting child SIGUSR2:");
exit(EXIT_FAILURE);
}
child_work(t);
exit(EXIT_SUCCESS);
case -1:
perror("Fork:");
exit(EXIT_FAILURE);
}
}
}
void usage(void){
fprintf(stderr,"USAGE: signals n t\n");
fprintf(stderr,"n - number of children > 0\n");
fprintf(stderr,"t - max lifetime of child process\n");
}
int main(int argc, char** argv)
{
int n,t;
//int childcount;
if(argc!=3)
{
usage();
return EXIT_FAILURE;
}
n = atoi(argv[1]);
t = atoi(argv[2]);
if (n<=0 || t<=1) {
usage();
return EXIT_FAILURE;
}
if(sethandler(SIG_IGN,SIGUSR1))
{
perror("Seting parent SIGUSR1:");
exit(EXIT_FAILURE);
}
if(sethandler(parent_handler,SIGUSR2))
{
perror("Seting parent SIGUSR2:");
exit(EXIT_FAILURE);
}
if(sethandler(sigchld_handler,SIGCHLD))
{
perror("Seting parent SIGCHLD:");
exit(EXIT_FAILURE);
}
create_children(n, t);
struct timespec tt, tn = {1,0};
while(1)
{
for(tt=tn;nanosleep(&tt,&tt);)
if(EINTR!=errno) perror("nanosleep:");
if(0==kill(0,SIGUSR1))
printf("[%d] SENDING signal %d\n", getpid(), SIGUSR1);
else
perror("kill:");
}
return EXIT_SUCCESS;
}
当我运行它./program 3 3(它产生3个孩子)我得到奇怪的输出,如:
[2835] dies[2836] dies[2834] dies[2836] dies[2836] received signal 10
[2836] received signal 12
[2836] SENDING signal 12
[2835] dies
你可以看到[2835]和[2836]死2次,我只是想知道它为什么会这样?提前感谢您的帮助。
答案 0 :(得分:1)
在信号处理函数中使用printf()
会导致未定义的行为。
我无法使用Debian 8.3虚拟机重现您的错误。行为取决于操作系统。