Linux 信号

对Linux信号进行了简单总结
涉及
signal
kill
raise
参考资料

1. 信号概念

1.1 什么是信号

信号即为软中断,用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据

信号来源

  • 来自硬件中断的信号:间隔定时器(可以发出信号14、信号26、信号27)、ctrl+c组合键、其他硬件错误等
  • 来自其他进程的信号:kill系统调用,子进程死亡等
  • 来自异常的信号(自己发给自己的信号):用户模式下的进程遇到异常时会陷入内核模式,生成一个信号并发送给自己。如除0、无效地址等

1.2 Linux处理信号方式

当一个信号到来的时候收到这个信号的进程会根据信号的具体情况提供一下三种不同的处理方式:

  • 对于需要处理的信号,指定处理函数,由该函数来处理。

  • 忽略某个信号,对该信号不做任何处理。

  • 对该信号的处理保留系统的默认值,这种默认操作大多数使得进程终止,进程通过系统调用signal函数来指定进程对某个信号的处理行为。

1.3 可靠信号与不可靠信号

可以通过kill -l查看所有信号

xtark@xtark-vmpc:~$ kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	

上图中编号为1~31的信号为早期Linux所支持的信号,是不可靠信号(非实时的),编号为34-63的信号时后来扩充的,称为可靠信号(实时信号)。

不可靠信号与可靠信号的区别在于前者不支持排队(相同的信号多次到来会合并为一个,造成后来的信号丢失),可能会造成信号丢失,而后者不会丢失

1.4 信号说明

1-31的信号说明见链接

2. signal系统调用

安装信号捕捉函数,当进程收到指定信号时会调用该信号处理函数。

该函数可以用来修改指定信号的处理函数(除了SIGKILL(9)和SIGSTOP(19)以外,它们的信号处理函数不能修改)

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
  • 参数signum:指定的信号

  • 参数handler:

    一个函数指针,且该函数是void (*)(int)类型。该函数int参数即为信号number

    可以传递该参数为SIG_IGN宏,来忽略该信号;也可以传递该参数为SIG_DFL使用该信号的默认处理函数

示例:通过信号处理函数捕获SIGINT(2)

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
//信号处理函数
void func(int sig){
    printf("\nreceive sig %d\n",sig);
    exit(EXIT_SUCCESS);//成功终止进程
}
int main(){
    signal(SIGINT,func);//注册信号处理函数
    while(1);
}

运行结果:在进程运行过程中键入ctrl+c可以看出该进程成功捕获到信号2(SIGINT)并调用信号处理函数。

xtark@xtark-vmpc:~/桌面/linux_study/section8$ gcc test5.c 
xtark@xtark-vmpc:~/桌面/linux_study/section8$ ./a.out 
^C
receive sig 2

3. kill系统调用

向任何进程组或进程发送任何信号

#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
  • 参数pid:进程识别号pid。

    pid大于0:信号sig将被发送到pid指定的进程

    pid等于0:sig被发送到调用进程的进程组中的每个进程

    pid等于-1:sig被发送到调用进程有权限发送信号的每个进程,除了进程1(init进程)

    pid小于-1:sig被发送给进程组中ID为-pid的每个进程

  • 参数sig:要发送的信号。

    如果sig为0,则不发送信号,但仍会进行错误检查;这可以用来检查是否存在进程ID或进程组ID存在。

  • 返回值:成功时(至少有一个信号被发送)返回0。 错误时返回-1,并设置errno。

4. raise函数

向调用进程(自己)发送信号,与kill(getpid(), sig);等价

#include <signal.h>
int raise(int sig);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值