信号捕捉
信号捕捉是进程从内核态返回用户态时会对信号进行检测处理。
捕捉信号用sigaction和signal函数进行对信号进行捕捉处理,而在调用捕捉之后进程pending位图对应比特位编号会由1变为0,它是说明时候由1变为0,是在信号捕捉之前
结构体中包含对信号的处理方法,以及对信号的屏蔽设置。
将sa_handler赋值为常数SIG_IGN传给sigaction表示忽略信号,赋值为常数SIG_DFL表示执行系统默认动
作,赋值为一个函数指针表示用自定义函数捕捉信号,或者说向内核注册了一个信号处理函 数,该函数返回
值为void,可以带一个int参数,通过参数可以得知当前信号的编号,这样就可以用同一个函数处理多种信
号。显然,这也是一个回调函数,不是被main函数调用,而是被系统所调用。sa_handler为处理对应信号的处理动作。
sa_mask是对信号集做屏蔽的字段就对应进程内核中的block表。
运行一个进程然后让他对2号信号进行捕捉
#include <iostream>
#include <cstring>
#include <ctime>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
using namespace std;
void PrintPending()
{
sigset_t set;
sigpending(&set);
for (int signo = 1; signo <= 31; signo++)
{
if (sigismember(&set, signo))
cout << "1";
else
cout << "0";
}
cout << "\n";
}
void handler(int signo)
{
cout << "catch a signal, signal number : " << signo << endl;
while (true)
{
PrintPending();
sleep(1);
}
}
int main()
{
struct sigaction act, oact;
memset(&act, 0, sizeof(act));
memset(&oact, 0, sizeof(oact));
sigemptyset(&act.sa_mask);
act.sa_handler = handler;
sigaction(2, &act, &oact);
while (true)
{
cout << "I am a process: " << getpid() << endl;
sleep(1);
}
return 0;
}
当某个信号的处理函数被调用时,内核自动将当前信号加入进程的信号屏蔽字,当信号处理函数返回时自动恢复原来的信号屏蔽字,这样就保证了在处理某个信号时,如果这种信号再次产生,那么 它会被阻塞到当前处理结束为止。 如果在调用信号处理函数时,除了当前信号被自动屏蔽之外,还希望自动屏蔽另外一些信号,则用sa_mask字段说明这些需要额外屏蔽的信号,当信号处理函数返回时自动恢复原来的信号屏蔽字。 对信号的捕捉可以使其对其他信号不做出响应。