我可以向信号处理程序提供/传递任何参数吗?
/* Signal handling */
struct sigaction act;
act.sa_handler = signal_handler;
/* some more settings */
现在,处理程序看起来像这样:
void signal_handler(int signo) {
/* some code */
}
如果我想做一些特别的事情,比如删除临时文件,我可以将这些文件作为参数提供给这个处理程序吗?
编辑0:谢谢你的回答。我们通常避免/不鼓励使用全局变量。在这种情况下,如果你有一个庞大的程序,在不同的地方可能会出现问题,你可能需要进行大量的清理工作。为什么API以这种方式设计?
答案 0 :(得分:50)
您不能将自己的数据作为参数传递给信号处理程序。相反,您必须将参数存储在全局变量中。 (如果您在安装信号处理程序后需要更改这些数据,那么真的非常小心。)
回复编辑0:历史原因。信号是一个非常古老而且非常低级的设计。基本上你只是给内核一个地址一些机器代码,并要求它去这个特定的地址,如果发生这种情况。我们回到了这里的“便携式汇编程序”思维模式,其中内核提供了简洁的基线服务,无论用户进程可以合理地预期为什么,它都必须自己做。
此外,针对全局变量的通常参数并不适用于此处。信号处理程序本身是一个全局设置,因此没有相关的可能性为它提供几组不同的用户指定参数。 (嗯,实际上它不是完全全局的,只是线程全局的。但是线程API将包含一些线程局部存储机制,这正是你在这种情况下所需要的)。
答案 1 :(得分:16)
信号处理程序注册已经是一个等同于全局变量的全局状态。因此,使用全局变量将参数传递给它并不是更大的冒犯。然而,这是一个巨大的错误(几乎可以肯定未定义的行为,除非你是专家!)无论如何都要从信号处理程序做任何事情。如果您只是阻止信号并从主程序循环中轮询它们,则可以避免所有这些问题。
答案 2 :(得分:6)
这是一个非常古老的问题,但我想我可以向你展示一个可以解决问题的好方法。 不需要使用sigqueue或其他任何东西。
我也不喜欢使用全局变量,所以我必须找到一个聪明的方法,在我的情况下,发送一个void ptr(你可以随后投射到任何适合你需要的东西)。
实际上你可以这样做:
signal(SIGWHATEVER, (void (*)(int))sighandler); // Yes it works ! Even with -Wall -Wextra -Werror using gcc
然后你的sighandler看起来像这样:
int sighandler(const int signal, void *ptr) // Actually void can be replaced with anything you want , MAGIC !
你可能会问:如何获得* ptr呢?
在这里&#39>如何: 初始化
signal(SIGWHATEVER, (void (*)(int))sighandler)
sighandler(FAKE_SIGNAL, your_ptr);
在你的sighandler func中 :
int sighandler(const int signal, void *ptr)
{
static my_struct saved = NULL;
if (saved == NULL)
saved = ptr;
if (signal == SIGNALWHATEVER)
// DO YOUR STUFF OR FREE YOUR PTR
return (0);
}
答案 3 :(得分:4)
绝对。您可以使用sigqueue()而不是通常的kill()将整数和指针传递给信号处理程序。
答案 4 :(得分:1)
将文件名存储在全局变量中,然后从处理程序访问它。信号处理程序回调只会传递一个参数:导致问题的实际信号的ID(例如SIGINT,SIGTSTP)
编辑0:“必须有一个坚实的理由不允许处理程序的参数。” < - 有一个中断向量(基本上是一组跳转地址到每个可能信号的例程)。给定中断被触发的方式,基于中断向量,调用特定函数。不幸的是,不清楚与变量相关的内存将被调用的位置,并且取决于内存可能实际被破坏的中断。有一种方法可以解决它,但是你不能利用现有的int 0x80汇编指令(某些系统仍在使用)
答案 5 :(得分:1)
我认为您最好在sa_flags中使用SA_SIGINFO,这样处理程序将
void signal_handler(int sig, siginfo_t *info, void *secret)
在siginfo_t中,您可以提供参数。
Ty:快乐代码
答案 6 :(得分:0)
您可以使用信号处理程序,它是类的方法。然后该处理程序可以访问该类的成员数据。我不完全确定Python在C signal()调用周围做了什么,但它必须重新确定数据范围?
我很惊讶这有效,但确实如此。运行此命令,然后从另一个终端终止该进程。
import os, signal, time
class someclass:
def __init__(self):
self.myvalue = "something initialized not globally defined"
signal.signal(signal.SIGTERM, self.myHandler)
def myHandler(self, s, f):
# WTF u can do this?
print "HEY I CAUGHT IT, AND CHECK THIS OUT", self.myvalue
print "Making an object"
a = someclass()
while 1:
print "sleeping. Kill me now."
time.sleep(60)