我有一项任务 - 检查我是否可以编写一个接收所有信号的程序。我知道我不能,但是当我想写一个程序时,它不能正常工作。可以使用fork()在一个.c文件中完成吗?尽管"Unknown signal 32"
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void signalReceiver(int number) {
printf("There it is - %d\n", number);
}
int main(void) {
int mypid = getpid();
for(int i = 1; i <= 64; ++i) {
signal(i, signalReceiver);
}
int pid = fork();
if(pid == 0) {
for(int i = 1; i <= 64; ++i) {
//SKIP the signals which interrupt the state of the program
if( i != 9 && i != 19) {
kill(mypid, i);
}
}
} else {
wait(NULL);
}
getchar();
return 0; }
答案 0 :(得分:3)
虽然操作系统不允许您注册SIGKILL
(9)和SIGSTOP
(19)的处理程序,但您的libc不会让您注册保留信号32
的处理程序和33
(这些用于实现多线程)。
简单的错误检查会检测到这一点:
if(SIG_ERR==signal(i, signalReceiver))
{ fprintf(stderr, "no sighandler for %d: %m\n", i); }
稍后在输出中:
no sighandler for 9: Invalid argument
no sighandler for 19: Invalid argument
no sighandler for 32: Invalid argument
no sighandler for 33: Invalid argument
现在你得到32以下的信号,但是在处理程序设法输出输出之前32会设法杀死你的父进程(BTW,printf
在信号处理程序中使用是不安全的 - 你应该sprintf到缓冲区并直接write
。您收到的Unknown signal 32
消息来自您的shell,该shell检测到其子节点已被信号32终止。
如果你将杀戮空间化(例如,使用usleep(1000)
以便处理程序有机会完成)或者如果你在同一个过程中运行杀戮,那么你应该能够获得32以下信号的消息(在在kill
函数返回之前,每个处理程序将完成的情况。
如果您希望该进程存活,请不要发送它未成功注册处理程序的信号。
此外,wait
和getchar
无法保证不间断通过信号收据。您应该已准备好重新启动wait
,例如:
again: if(0>wait(NULL))
if(EINTR==errno) goto again; else perror("wait");
完整修改后的来源:
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void signalReceiver(int number) {
char buf[256] = {0};
sprintf(buf, "There it is - %d\n", number);
write(1,buf,strlen(buf));
}
int main(void) {
int mypid = getpid();
for(int i = 1; i <= 64; ++i) {
if(SIG_ERR==signal(i, signalReceiver))
{ fprintf(stderr, "no sighandler for %d: %m\n", i); }
}
int pid = fork();
if(0>pid){ perror("fork"); exit(1); }
if(pid == 0) {
for(int i = 1; i <= 64; ++i) {
//SKIP the signals which interrupt the state of the program
if( i != 9 && i != 19 && i!=32 && i!=33) {
kill(mypid, i);
}
}
_exit(0);
} else {
again: if(0>wait(NULL))
if(EINTR==errno) goto again; else perror("wait");
}
return 0;
}