MST

星途 面试题库

面试题:C语言中signal和sigaction函数的区别

在Linux C语言信号处理中,signal和sigaction函数都用于设置信号处理方式,请阐述它们之间的主要区别,包括函数原型、信号处理语义、可移植性等方面。
27.1万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

函数原型

  • signal函数原型
#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);
  • signum:指定信号编号,如SIGINTSIGTERM等。
  • handler:是一个函数指针,指向信号处理函数,信号处理函数只有一个int类型参数,用于接收信号编号。返回值也是一个函数指针,指向旧的信号处理函数。
  • sigaction函数原型
#include <signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
  • signum:同样指定信号编号。
  • act:指向一个struct sigaction结构体,用于设置新的信号处理方式。
  • oldact:指向一个struct sigaction结构体,用于保存旧的信号处理方式,可以为NULLstruct sigaction结构体定义如下:
struct sigaction {
    void     (*sa_handler)(int);
    void     (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t   sa_mask;
    int        sa_flags;
    void     (*sa_restorer)(void);
};
  • sa_handler:与signal函数中的handler类似,是一个指向信号处理函数的指针。
  • sa_sigaction:另一种信号处理函数指针,适用于需要更多信号信息的情况,其参数比sa_handler指向的函数多了siginfo_t *void *
  • sa_mask:在信号处理函数执行期间要阻塞的信号集。
  • sa_flags:用于设置信号处理的一些选项,如SA_RESTARTSA_SIGINFO等。

信号处理语义

  • signal
  • 简单易用,主要用于基本的信号处理。当信号发生时,系统会跳转到handler指定的函数执行,执行完毕后通常恢复到信号发生前的执行点继续执行。但是在某些系统上,使用signal设置信号处理函数后,信号处理函数执行一次后,信号处理方式可能会被重置为默认行为(如在早期的UNIX系统),现在大多数系统已改进此行为,但这仍带来一定不确定性。
  • 信号处理函数只能接收信号编号作为参数,无法获取信号的其他详细信息。
  • sigaction
  • 功能更强大和灵活。可以通过sa_mask指定在信号处理函数执行期间要阻塞的其他信号,防止在处理一个信号时又被其他信号打断,影响处理流程。
  • sa_flags提供了丰富的选项,如SA_RESTART可使被信号中断的系统调用自动重启;SA_SIGINFO使得可以使用sa_sigaction指定的信号处理函数,从而获取关于信号的详细信息,如信号发送进程ID、发送信号的用户ID等。

可移植性

  • signal:虽然signal函数在POSIX标准中定义,但由于历史原因,不同UNIX系统对signal的实现存在差异,尤其是关于信号处理函数执行一次后是否重置为默认行为方面。因此,signal的可移植性相对较差,在编写跨平台代码时需要格外小心。
  • sigactionsigaction是POSIX标准推荐使用的函数,其行为在不同POSIX兼容系统上表现一致,具有良好的可移植性,更适合编写可移植的代码。在现代的UNIX和Linux系统开发中,sigaction被广泛使用。