Head First C 第十章 进程间通信 捕捉信号
关于信号
信号是操作系统控制程序的方式,举个栗子,操作系统在看到用户输入了Ctrl+C时,就会向程序发送中断信号。 信号映射表
信号 | 处理函数 |
---|---|
SIGURG | 不做事情 |
SIGINT | 调用exit() |
捕捉信号然后运行自己的代码
有时候你希望别人打断你的程序时运行自己的代码。假设进程打开了一些文件或网络连接,你希望在退出之前把它们关闭,并且做一些清理工作。在这里引入sigaction
结构。
sigaction是一个函数包装器
sigaction是一个结构体,它有一个函数指针,siagction告诉操作系统进程收到某个信号时该调用哪个函数。
sigaction的创建方法如下
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flag = 0;
sigemptyset用于设置信号,在信号被使用前必须调用sigemptyset
或sigfillset
,sigemptyset
在man中的函数原型和解释是:
int sigemptyset(sigset_t *set);
The sigemptyset() function initializes a signal set to be empty.
将信号初始化设置为空。 处理器必须接收信号参数 信号是一个整型值,如果你创建了一个自定义处理函数,就需要接收一个整型参数:
void diediedie(int sig) {
puts("Goodbye cruel world...\n");
exit(1);
}
用sigaction()注册sigaction
创建sigaction以后,需要用sigaction()函数注册,使操作系统知道它的存在。
int sigaction(int sig, const struct sigaction *restrict act, struct sigaction *restrict oact);
sigaction()函数接收3个参数,信号,动作,旧动作(可以传NULL)。
将创建和初始化封装成一个函数
int catch_signal(int sig, void (*handler)(int)) {
struct sigaction action;
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
return sigaction(sig, &action, NULL);
}
这样只要把信号和处理器传给catch_signal()
函数,就可以设置信号处理器了。
给进程发送信号
用kill命令发送信号
运行程序后,可以使用Ctrl+C发送一个中断信号,如果想发送其他信号,可以用在终端下用kill命令,格式为kill -信号 进程号
kill -INT 1739
的效果和Ctrl+C一样,都是发送中断信号。
在进程内发送信号
在进程内可以使用raise()
函数向自己发送信号。
通常会在自定义的信号处理器中使用raise()
,这样程序就能在接收到低级别的信号时引发更高级别的信号,这叫做信号升级。
例程代码
来源:oschina
链接:https://my.oschina.net/u/2491285/blog/661439