我在使用C语言。我试图抓住并处理两个不同的信号:
默认INT信号操作设置为 action1 。
在我的代码中, switchaction 函数很好地由QUIT信号触发,但对INT信号动作没有影响:s
#include <signal.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
typedef void (*sighandler_t)(int);
sighandler_t prev_handler;
void action1(int n){
printf("First message\n");
}
void action2(int n){
printf("Second message\n");
}
void switchaction(int n){
printf("Switch action\n");
prev_handler=action2;
}
int main() {
prev_handler = action1;
printf("PID: %d\n", getpid());
prev_handler= signal(SIGINT,prev_handler);
signal(SIGQUIT,switchaction);
travail(); //This function never ends
}
您是否知道我的代码中出了什么问题?
谢谢,
晏
答案 0 :(得分:2)
您的系统调用
prev_handler= signal(SIGINT,prev_handler);
在执行prev_handler
系统调用时将信号处理程序设置为signal
变量的值。更改{之后)prev_handler
的值不会更改SIGINT
信号的处理。换句话说,signal
(和大多数C调用)具有call by value语义。如果你拨打signal
一次,内核会保留相同的处理程序(直到你用相同的信号号码再次呼叫signal
,或直到你拨打sigaction(2)等等......)。
仔细阅读(假设您使用的是Linux)signal(7)和signal(2)手册页。
我会改为定义
volatile sig_atomic_t howhandle;
void switchaction(int n __attribute__((unused))) {
if (howhandle)
howhandle = 0;
else
howhandle = 1;
}
void handleint (int n) {
if (howhandle) action1(n); else action2(n);
}
并安装
signal(SIGINT, handleint);
signal(SIGQUIT, switchaction);
另请注意,处理程序中调用printf
不正确(因为printf
不是异步信号安全函数,但是你在action1
中调用它,由handleint
调用...)。再读一遍signal(7)
您应该在volatile sig_atomic_t
工作函数内的适当位置使用其他travail
变量并测试(并清除它们),但只能在信号处理程序中设置它们。设置volatile sig_atomic_t
变量几乎是你在信号处理程序中可靠地做的唯一事情。
如果您接受Linux特定解决方案,请详细了解signalfd(2)(并同时使用poll(2) ...)。另请阅读Advanced Linux Programming。