准确处理所有进入 parent 进程的 SIGUSR1 类型的信号。 C
Handle exactly all signals of type SIGUSR1 that come to parent process. C
我想编写一个程序,使用 fork() 函数创建 N children。每个 child 将等待 0 到 3 秒,然后它会发送 parent 恰好一个信号 SIGUSR1。 Parent 处理所有这些信号。
问题是我的程序并不总是处理来自 children 的所有信号。如何修复?
第二个问题:我知道我不应该在处理程序中使用 printf,因为可能会发生一些不好的事情。我该如何替换这条指令?
main.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void error(char *s){
printf("%s\n",s);
perror("Program execution failed.");
exit(EXIT_FAILURE);
}
volatile int N=8; //final number of children
volatile int k=0; //number of received SIGUSR1 signals
void childRequestHandler(int signo, siginfo_t* info, void* context){
k++;
printf("%d,Father received request from child: %d\n",k,info->si_pid);
}
int main() {
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = childRequestHandler;
if(sigaction(SIGUSR1,&act,NULL) == -1) printf("ERROR OCCURED");
for(int i=0;i<N;i++){
pid_t pid = fork();
if(pid == 0) {
execl("./child", "./child", NULL);
error("Fork error happened\n");
}
}
while (1){
sleep(1);
}
}
child.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
int main() {
time_t t;
srand((unsigned int) getpid()+ time(NULL));
int length_of_sleeping = rand() % 4 ;
printf("I live: %d, sleeps %ds \n",getpid(),length_of_sleeping);
sleep(length_of_sleeping);
kill(getppid(),SIGUSR1);
while(1){
}
}
输出:
I live: 4195, sleeps 3s
I live: 4196, sleeps 3s
I live: 4197, sleeps 1s
I live: 4202, sleeps 3s
I live: 4198, sleeps 0s
I live: 4201, sleeps 2s
I live: 4199, sleeps 0s
I live: 4200, sleeps 3s
1,Father received request from child: 4198
2,Father received request from child: 4197
3,Father received request from child: 4201
4,Father received request from child: 4195
当信号处理程序正在执行时,信号被阻塞。在此期间收到的所有 SIGUSR1
个信号将不会被注意到。
您可以在建立信号时使用 SA_NODEFER
标志,有关标志的信息请参阅 the sigaction
manual page。
但是,如果您使用 SA_NODEFER
,请不要使用 printf
!它不是 async-signal-safe 函数。参见例如this manual page about signal safety 获取更多信息。
来自 the POSIX sigaction
reference:
When a signal is caught by a signal-catching function installed by sigaction()
, a new signal mask is calculated and installed for the duration of the signal-catching function.... This mask is formed by taking the union of the current signal mask and the value of the sa_mask
for the signal being delivered, and unless SA_NODEFER
or SA_RESETHAND
is set, then including the signal being delivered. If and when the user's signal handler returns normally, the original signal mask is restored.
[强调我的]
我想编写一个程序,使用 fork() 函数创建 N children。每个 child 将等待 0 到 3 秒,然后它会发送 parent 恰好一个信号 SIGUSR1。 Parent 处理所有这些信号。
问题是我的程序并不总是处理来自 children 的所有信号。如何修复?
第二个问题:我知道我不应该在处理程序中使用 printf,因为可能会发生一些不好的事情。我该如何替换这条指令?
main.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void error(char *s){
printf("%s\n",s);
perror("Program execution failed.");
exit(EXIT_FAILURE);
}
volatile int N=8; //final number of children
volatile int k=0; //number of received SIGUSR1 signals
void childRequestHandler(int signo, siginfo_t* info, void* context){
k++;
printf("%d,Father received request from child: %d\n",k,info->si_pid);
}
int main() {
struct sigaction act;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = childRequestHandler;
if(sigaction(SIGUSR1,&act,NULL) == -1) printf("ERROR OCCURED");
for(int i=0;i<N;i++){
pid_t pid = fork();
if(pid == 0) {
execl("./child", "./child", NULL);
error("Fork error happened\n");
}
}
while (1){
sleep(1);
}
}
child.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
int main() {
time_t t;
srand((unsigned int) getpid()+ time(NULL));
int length_of_sleeping = rand() % 4 ;
printf("I live: %d, sleeps %ds \n",getpid(),length_of_sleeping);
sleep(length_of_sleeping);
kill(getppid(),SIGUSR1);
while(1){
}
}
输出:
I live: 4195, sleeps 3s
I live: 4196, sleeps 3s
I live: 4197, sleeps 1s
I live: 4202, sleeps 3s
I live: 4198, sleeps 0s
I live: 4201, sleeps 2s
I live: 4199, sleeps 0s
I live: 4200, sleeps 3s
1,Father received request from child: 4198
2,Father received request from child: 4197
3,Father received request from child: 4201
4,Father received request from child: 4195
当信号处理程序正在执行时,信号被阻塞。在此期间收到的所有 SIGUSR1
个信号将不会被注意到。
您可以在建立信号时使用 SA_NODEFER
标志,有关标志的信息请参阅 the sigaction
manual page。
但是,如果您使用 SA_NODEFER
,请不要使用 printf
!它不是 async-signal-safe 函数。参见例如this manual page about signal safety 获取更多信息。
来自 the POSIX sigaction
reference:
When a signal is caught by a signal-catching function installed by
sigaction()
, a new signal mask is calculated and installed for the duration of the signal-catching function.... This mask is formed by taking the union of the current signal mask and the value of thesa_mask
for the signal being delivered, and unlessSA_NODEFER
orSA_RESETHAND
is set, then including the signal being delivered. If and when the user's signal handler returns normally, the original signal mask is restored.
[强调我的]