更健壮的信号接口
# 更健壮的信号接口
进程可以使用系统调用signal()
或者sigaction()
来安装信号处理函数来捕获特定的信号,sigaction()
是一个更健壮的信号接口。
# 更健壮的信号接口
UNIX规范提供了一个更加健壮的信号编程接口:sigaction
,声明如下:
#include <signal.h>
int sigaction(int sig, const struct sigaction* act, struct sigaction* oact);
1
2
2
sig
:接收到的信号act
:新结构体变量,指定接收到信号后的动作oact
:旧结构体变量,由sigaction
函数返回
# struct sigaction
结构
void (* sa_handler)(int)
:与sig
信号相连的动作,当收到sig
信号后执行此函数。该参数可以被设置为SIG_DFL
,或者SIG_IGN
。sigset_t sa_mask
:该字段指定了一个信号集,该信号集将被加入到进程的信号屏蔽字当中,这是一组将被阻塞且不会传递给该进程的信号。int sa_flags
:信号函数选项标识。如果希望信号处理重置为默认处理方式,可将其设置为RESETHAND
,如果希望设置为上一次设置的处理方式,可设置为RESTART。
# 使用sigaction
重写代码 (opens new window)
# 示例代码
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void sig_alarm(int sig)
{
printf("---the signal received is %d. \n", sig);
}
int main()
{
struct sigaction act;
act.sa_handler = sig_alarm;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESETHAND;
sigaction(SIGINT, &act, 0);
while(1)
{
printf("waiting here!\n");
sleep(1);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 输出
waiting here!
waiting here!
waiting here!
^C---the signal received is 2.
waiting here!
waiting here!
waiting here!
^C
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 分析
这段代码使用了struct sigaction
结构体来注册SIGINT
信号的处理函数,指定的处理函数是sig_alarm
。同时,使用了sigemptyset()
函数将信号集初始化为空集,这样在信号处理函数执行时不会阻塞任何其他信号。sa_flags
成员设置了SA_RESETHAND
标志,这意味着在处理完信号后,将信号处理函数重置为默认处理方式。
在主循环中,进程会不断输出waiting here!
并休眠1秒钟,直到收到SIGINT
信号。当信号被捕获后,程序会执行sig_alarm
函数,并输出被捕获的信号值,然后SA_RESETHAND
标志将会使得该信号的处理函数被重置为默认处理方式,这将导致下一次信号到来时使用系统默认的处理方式而不是之前设置的处理函数。接着,主循环会继续执行,等待下一个信号的到来。
# sigaction
函数的优点
sigaction
相对于signal
函数的优点主要有以下几点:
- 更加灵活:
sigaction
可以对信号的处理进行更加精细的控制,可以指定信号处理函数的地址、控制信号的信号集、设置处理信号的选项等。相比之下,signal
函数仅能指定信号处理函数的地址。 - 可重入性:
sigaction
在设置信号处理函数时可以使用SA_RESTART
选项来保证系统调用在收到信号后能够自动恢复,避免了可能的竞争条件,从而保证了程序的可重入性。
一般来说,在编写需要对信号进行处理的程序时,建议使用sigaction
函数而不是signal
函数。
编辑 (opens new window)
上次更新: 2023/02/19, 10:48:02
- 01
- Linux系统移植(五)--- 制作、烧录镜像并启动Linux02-05
- 03
- Linux系统移植(三)--- Linux kernel移植02-05