typedef void (*sighandler_t)(int);
extern sighandler_t signal(int signum, sighandler_t handler); // 1
extern void (*signal(int sig, void (*func) (int)))(int); // 2
1 和 2 是彼此的等价物。这个问题并不是从 或如何开始的。我从以下描述中很好地理解了它的声明及其作用。
一个带
int
的函数和一个指向函数的指针(int
返回void)并返回指向函数的指针(取int
并返回虚空)。
或
sighandler_t
是一个指向int
的函数的指针 参数并且什么都不返回signal
函数需要这样的 函数指针作为其第二个参数。它还返回一个函数 那种类型的指针。
为什么选择int
或void
或something else
的返回类型代替指向函数的指针(取int
并返回void
)与第二个参数相同?也就是说,我想知道是否有任何理由选择返回类型。
答案 0 :(得分:4)
为什么它的返回类型没有选择int或void或其他代替指向函数的指针(取int并返回void)与第二个参数相同?
signal()
返回该信号的上一个处理程序。因此,如果要在设置不同的处理程序后恢复信号的旧行为,这将非常有用。
对于sigaction()
,旧处理程序通过其第三个参数返回;因此它返回int
。
答案 1 :(得分:1)
来自the POSIX signal()
documentation:
返回值
如果请求得到遵守,
signal()
将返回值func
用于指定信号的signal()
最近一次调用sig
。否则,将返回SIG_ERR
并返回正值 应存储在errno
。
如@ P.P。的回答所述,这是该信号的先前信号处理程序,允许恢复旧处理程序以及链接信号处理程序调用的能力。
链接信号处理程序示例:
typedef void ( *sighandler_t )( int );
sighandler_t old_handler = NULL;
void new_handler( int sig )
{
switch ( sig )
{
case SIGTERM:
// do your own handling
.
.
.
// now call the old handler
if ( old_handler )
{
old_handler( sig );
}
break;
default:
break;
}
return;
}
int main( int argc, char **argv )
{
.
.
.
// save the old handler so it can also be called
old_handler = signal( SIGTERM, new_handler );
// make sure old_handler isn't a non-function
// (these can be extremely platform-specific)
if ( old_handler == SIG_ERR ||
old_handler == SIG_DFL ||
old_handler == SIG_IGN )
{
old_handler = NULL;
}
}
你必须要小心,不要把某些不能被召唤的东西联系起来。对于上面的示例,代码检查以确保signal()
的返回值不是信号处理程序的已知非可调用值之一。
链接还有其他问题。例如,如果您安装自己的SIGSEGV
处理程序并使用上面的代码,那么如果您的signal()
调用安装了一个持久性处理程序(一个不需要signal()
调用的实现重新安装自己的处理程序)或者如果您使用sigaction()
,并且原始SIGSEGV
处理程序是SIG_DFL
,则不会调用默认处理程序。如果取消引用SIGSEGV
指针,这将导致进程进入无限NULL
循环,因为在处理程序返回后将再次运行无效指令。