一、信号的定义
信号是一个通讯方式,正在运行的进程可以收到各种信号,可以是终端发送的信号,可以是父子进程间发送结束信号,也可以是程序运行错误时发送的终止信号。
二、信号的种类
在linux终端下使用kill -l命令可以查看所有信号的种类,如下:
常用的信号有在中断使用ctrl+c而产生的的信号SIGINT,会使得程序终止;子进程结束回向父进程发送的信号SIGCHLD等。
三、信号的发送
发送信号一般是有用户、内核、进程和操作系统 等等来发送的:
用户可以在终端使用ctrl+c(SIGINT),ctrl+z(SIGTSTP)、kill+pid(SIGKILL)(杀死进程)等来向进程发送信号。
那么在进程中,c语言也向我们提供了可以手动向进程发送信号的函数,如下:
1.kill()
函数头文件 #include <sys/types.h>#include <signal.h>函数原型 int kill(pid_t pid, int sig);函数功能 向指定的进程发送一个信号函数参数 pid:进程的id;sig:信号的id;函数返回值 成功返回 0;失败返回 -1,并设置 errno;
2.raise()
函数头文件 #include <sys/types.h>#include <signal.h>函数原型 int raise(int sig);函数功能 向调用者发送一个信号;函数参数 sig:信号编号
上面这两个函数,kill()函数是一个可以向其他进程发送信号的函数,raise()函数是一个只能向当前进程发送信号。实际上raise是对kill函数的一个封装,使用起来的话kill函数是比较灵活,而raise函数通常是程序发生某些错误或事件,才会调用该函数,使用信号处理。
四、信号的处理
1.linux中信号有三种处理方式
- 默认
- 忽略
- 自定义函数处理
进程接收到信号后,会交给内核进行处理,内核会判定这个信号将使用哪种处理方式;在内核接收信号的处理中有一个task_struct的结构体,这个结构体会去判定信号的处理方式,这个结构体属于内核源码,保存管理进程的所有信息,内容非常多,这个结构体就不过多说明,下面一些进程的默认的处理方式:
- 进程退出 SIGALRM,SIGHUP,SIGINT,SIGKILL,SIGPIPE,SIGPOLL,SIGPROF,SIGSYS,SIGTERM,SIGUSR1,SIGUSR2,SIGVTALRM
- 进程忽略 SIGCHLD,SIGPWR,SIGURG,SIGWINCH
- 进程暂停 SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU