信号的概念
宽泛的信号:信号是消息的物理载体,是运载消息的工具;
Linux中的信号:信号是由用户、系统或者进程发送给目标进程的信息,以通知目标进程某个状态的改变或系统异常;
系统中定义的信号列表
kill - l
其中编号34以上的属于实时信号,本文只讨论关于编号34以下的信号;
注意:无论信号各自在什么条件下产生,默认的处理动作是什么,在 signal(7) 中都有详细说明;
man 7 signal
信号的产生(终端按键)
最常见的按键产生信号 ctrl + c,给前台进程发宋 SIGINT信号,中止该进程。
SIGINT 的默认处理动作是终止进程,SIGQUIT 的默认处理动作是终止进程并且Core Dump。
Core Dump(核心转储)
当一个进程要异常终止的时候,可以选择把进程的用户空间内存数据全部保存到磁盘上,文件名通常是core(文件的命名方式为 core.pid),这叫做Core Dump。
进程异常终止通常是因为有Bug,事后可以实用调试器检查 core文件以查清除错误所在,这叫做Post-mortem Debug;
一个进程可以产生多大的core文件取决于进程中的Resoure Limit(PCB中)。默认情况下是不允许产生core 文件的,因为core 文件中可能会有用户密码等等,不安全。
在开发调试阶段可以用 ulimit 命令来该变这个限制,运行产生core 文件。
ulimit -a 查看
ulimit -c 设置 core 文件中最大大小 单位是 kb
信号的产生(调用系统函数)
1、给 PID为 pid 的进程发送 sig 信号
#include<sys/types.h>
#include<signal.h>
int kill(pid_t pid,int sig);
2、给调用进程发送 sig 信号
#include<signal.h>
int raise(int sig);
3、给调用进程发送 SIGABRT 信号(进程调用 abort 函数时产生的信号)
#include<stdlib.h>
void abort(void);
4、seconds 后,给调用进程发送一个 SIGALRM 信号
#include<unistd.h>
unsigned int alarm(unsigned int seconds);
5、给 pid 进程 sig 信号,并且附加数据 value
#include<signal.h>
int sigqueue(pid_t pid,int sig,const union sigval value);
信号的注册(进程中)
信号的注销
信号的处理
目标进程在收到信号后,需要定义一个接收函数来处理之。信号函数的原型:
#include<signal.h>
typedef void (*__sighander_t) ( int );
信号处理函数只带有一个整形参数,该参数用来指示信号类型。信号处理函数应该是可重入的,否则很容易引发一些竞态条件。所以在信号处理函数中严禁调用一些不安全的函数。
signal 系统调用
#include<signal.h>
_sighander_t signale(int sigsum,_sighander_t _handler);
sigsum:信号编号
handler:信号的处理方式 (SIG_IGN:忽略处理方式、SIG_FEL:默认处理方式)
sigaction 系统调用
#include<signal.h>
int sigaction(int sigsum,const struct sigaction* act,struct sigaction* oldact);
sigsum:信号编号
act:信号新的处理动作
oldact:保持信号原有的处理动作