基本概念
软中断信号(signal,简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。
收到信号的进程对各种信号有不同的处理方法,处理方法可以分为三类:
捕捉信号:类似中断的处理程序,对于需要处理的信号,进程可以指定处理函数,由该函数来处理。
忽略信号:忽略某个信号,对该信号不做任何处理,就象未发生过一样(sigkill和sigstop不能被忽略)。
系统默认动作:对该信号的处理保留系统的默认值,对大部分的信号的缺省操作是使得进程终止。此方法为缺省操作。进程通过系统调用signal来指定进程对某个信号的处理行为。
信号类型
按发出信号的原因分类:
(1)与进程终止相关的信号。当进程退出,或者子进程终止时,发出这类信号。
(2)与进程例外事件相关的信号。如进程越界,或企图写一个只读的内存区域(如程序正文区),或执行一个特权指令及其他各种硬件错误。
(3)与在系统调用期间遇到不可恢复条件相关的信号。如执行系统调用exec时,原有资源已经释放,而目前系统资源又已经耗尽。
(4)与执行系统调用时遇到非预测错误条件相关的信号。如执行一个并不存在的系统调用。
(5)在用户态下的进程发出的信号。如进程调用系统调用kill向其他进程发送信号。
(6)与终端交互相关的信号。如用户关闭一个终端,或按下break键等情况。
(7)跟踪进程执行的信号。
终端输入kill -l查看信号
31号前为不可靠信号,34号以后为可靠信号。不可靠信号连续发送有可能会造成信号丢失。可靠信号连续发送不会造成信号的丢失。
kill函数
int kill(pid_t pid, int sig);
sig:不推荐直接使用数字,应使用宏名,因为不同操作系统信号编号可能不同,但名称一致。
pid > 0: 发送信号给指定的进程。
pid = 0: 发送信号给与调用kill函数进程属于同一进程组的所有进程。
pid < -1: 发送信号给以-pid为组标识的进程
pid = -1:发送给进程有权限发送的系统中所有进程。
返回值:
成功返回0;失败返回-1
signal函数
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
typedef void (*sighandler_t)(int)为信号的自定义处理函数:参数列表仅有一个int类型,表示接收的信号
参数signum为指定信号(kill -l可查看)
参数handler为要设置的指定信号的处理方式(是系统默认还是忽略还是捕获):
-
SIG_IGN :忽略
-
SIG_DFL:系统默认执行方式
-
函数指针:用户自定义处理函数
代码实现ctrl+c杀不死进程
#include <stdio.h>
#include <signal.h>//包含头文件
void handler(int signum)
{
printf("signum = %d\n",signum);//打印信号值
}
int main()
{
signal(SIGINT,handler);//当收到SIGINI(ctrl+c)信号时 调用handler函数
while(1);
return 0;
}
运行结果如下(参数handler改为SIG_IGN也可忽略),每次ctrl+c都会调用handler打印信号值
代码实现利用kill函数发送信号
signaldemo1.c
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
void handler(int signum)
{
printf("signum = %d\n",signum);
printf("mypid=%d\n",getpid());//让受害者自己输出自己的pid 省事
}
int main()
{
signal(SIGINT,handler);
while(1);
return 0;
}
killdemo.c
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
int pid;
int signum;
char cmd[48] = {0};
signum = atoi(argv[1]);
pid = atoi(argv[2]);
printf("pid = %d\n",pid);
printf("signum = %d\n",signum);
sprintf(cmd,"kill -%d %d",signum,pid);
system(cmd);
//kill(pid,signum);
return 0;
}
运行结果