har*_*ari 57 c signals signal-handling
我可以向信号处理程序提供/传递任何参数吗?
/* Signal handling */
struct sigaction act;
act.sa_handler = signal_handler;
/* some more settings */
Run Code Online (Sandbox Code Playgroud)
现在,处理程序看起来像这样:
void signal_handler(int signo) {
/* some code */
}
Run Code Online (Sandbox Code Playgroud)
如果我想做一些特殊的事情,即删除临时文件,我可以将这些文件作为参数提供给这个处理程序吗?
编辑0:谢谢你的回答.我们通常避免/不鼓励使用全局变量.在这种情况下,如果你有一个庞大的程序,在不同的地方可能会出现问题,你可能需要进行大量的清理工作.为什么API以这种方式设计?
Hen*_*olm 53
您不能将自己的数据作为参数传递给信号处理程序.相反,您必须将参数存储在全局变量中.(如果您在安装信号处理程序后需要更改这些数据,那真的非常小心).
回复编辑0:历史原因.信号是一个非常古老而且非常低级的设计.基本上你只是给内核一个地址一些机器代码,并要求它去这个特定的地址,如果发生这种情况.我们回到了这里的"便携式汇编程序"思维模式,其中内核提供了简单的基本服务,无论用户进程能够合理地预期为什么,它都必须自己完成.
此外,反对全局变量的通常参数在这里并不真正适用.信号处理程序本身是一个全局设置,因此没有相关的可能性为它提供几组不同的用户指定参数.(嗯,实际上它不是完全全局的,而只是线程全局的.但是线程API将包含一些线程局部存储机制,这正是你在这种情况下所需要的).
R..*_*R.. 16
信号处理程序注册已经是一个等同于全局变量的全局状态.因此,使用全局变量将参数传递给它并不是更大的冒犯.然而,这是一个巨大的错误(几乎肯定是未定义的行为,除非你是专家!)无论如何都要从信号处理程序做任何事情.如果您只是阻止信号并从主程序循环中轮询它们,则可以避免所有这些问题.
绝对地。您可以使用 sigqueue() 而不是通常的 kill() 将整数和指针传递给信号处理程序。
http://man7.org/linux/man-pages/man2/sigqueue.2.html
这是一个非常老的问题,但我想我可以向您展示一个很好的技巧,它可以解决您的问题。无需使用sigqueue或其他任何工具。
我还不喜欢使用globals变量,因此在我的情况下,我不得不寻找一种巧妙的方法来发送一个无效的ptr(您可以稍后将其转换为适合您需要的任何内容)。
实际上,您可以这样做:
signal(SIGWHATEVER, (void (*)(int))sighandler); // Yes it works ! Even with -Wall -Wextra -Werror using gcc
Run Code Online (Sandbox Code Playgroud)
然后您的信号处理程序将如下所示:
int sighandler(const int signal, void *ptr) // Actually void can be replaced with anything you want , MAGIC !
Run Code Online (Sandbox Code Playgroud)
您可能会问:那么如何获取* ptr?
方法如下: 初始化时
signal(SIGWHATEVER, (void (*)(int))sighandler)
sighandler(FAKE_SIGNAL, your_ptr);
Run Code Online (Sandbox Code Playgroud)
在您的sighandler函数中 :
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);
}
Run Code Online (Sandbox Code Playgroud)