信号的概念
信号是操作系统正常运行一个必不可少的工具。正如我们生活中负责协调交通的红绿灯一样,若没有了红绿灯信号,那岂不是一幅人间大乱的场景。
每个信号都有一个名字,并且大写的英文字母,开头都是“SIG”。我们在Linux系统下可以调用
kill -l
指令来查看所有信号。
注意上图,所有信号的编号是从1到64,但是没有32,33。所以信号共有62个,我们将前31个信号称为普通信号,后31个称为实时信号。我们使用这些信号的时候可以直接使用这些编号,也可以使用这些宏。本篇博客讨论的仅限于前31个普通信号。
其实我们在Linux下编程用到信号的地方很多。当我们想让一个正在执行的进程停下的时候会键入Ctrl+C,这时候终端驱动程序就将Ctrl+C解释成了一个SIGINT信号即编号为2的信号(或者说发送SIGINT信号给了当前进程),该信号会记录在进程的PCB当中。经一系列操作,当前进程停止运行。(细节会在下文讲出)
信号的产生
信号的产生有多种方式:
当用户在终端键入某些键时,引发终端产生信号。如Linux系统下的Ctrl+c,产生SIGINT信号,停止一个进程。Ctrl+\发送SIGQUIT信号,异常终止进程并且Core Dump。
硬件异常。如除0操作或者内存引用失效等。这些条件通常由硬件检测到,并通知内核,然后由内核为该条件发生时正在运行的进程产生适当的信号。
- 通过调用kill函数或在shell命令行下执行kill命令将信号发送给其他进程。
kill函数:
#include<signal.h>
int kill(pid_t pid, int sig);
参数pid为指定进程的进程ID,sig为指定的信号。
kill命令:
kill -信号 指定进程的进程ID
如:
kill -2 4085
//kill -SIGINT 4058
raise函数可以给当前进程发送指定的信号,终止自己(自己给自己发信号)。
#include<signal.h>
int raise(int signo)
函数abort可以用于进程异常终止,使当前进程接受到SIGQUIT信号。
#include<stdlib.h>
void abort(void)
- 当检测到某种软件条件已经发生,将其通知给有关进程时也要产生信号。如管道产生的信号SIGPIPE。还有alarm函数产生的信号SIGALRM。
alarm是闹钟函数,告诉内核在seconds秒之后给当前进程发送SIGALRM信号。该信号的默认处理动作是终止当前进程。返回值为0或者上次闹钟剩下的秒数。
#include<unistd.h>
unsignde int alarm(unsigned int seconds);
信号是异步产生的,信号的产生与进程的运行互不干扰,并且产生信号对进程而言是随机的。当进程收到一个信号时,必须告诉内核做好相应的处理工作。就如我们再看到红灯时就停下,绿灯时就前进一样。
补充:Core dump
这里要说一些扩展的知识,当一个进程异常终止时,一般会进程Core Dump。c