目录
1. 信号概念
在 Linux 系统中,信号是一种用于进程间通信 (IPC) 的机制,可以用来通知进程发生了某些事件。信号是由内核或进程发送的,目标是终止、暂停、恢复或触发特定行为。
- 信号 (Signal) 是一种软件中断,用于通知进程需要执行某种特定的处理。
- 信号的来源可以是用户、内核或者其他进程。
- 每个信号都有一个唯一的编号和对应的符号名称(例如,
SIGKILL
对应编号为 9)。
以下是一张信号表,可用 kill -l 命令查看:
2. 信号的产生
在讲信号的产生前,首先看一个信号的例子:
以下程序是一个捕捉信号 SIGINT (编号9),并执行对应的信号处理方法的程序,代码如下:
#include <stdio.h>
#include <signal.h>
//信号处理方法
void sigcb(int signum)
{
printf("signum is %d\n",signum);
}
int main()
{
//设置要捕捉的信号,和信号处理方法
signal(SIGINT,sigcb);
while(1)
{}
return 0;
}
我们都知道 按住 ctrl + c可用终止一个进程的运行,实际上ctrl + c的原理就是向进程发送SIGINT信号,该信号的默认处理方式就是终止程序,而我们设置了信号处理方法后,不再用默认方式处理信号,于是现象如下:
可以看到,对应进程在接收到SIGINT后,执行了我们设置的处理方法,其中ctrl + c就是一种产生信号的方式,接下来在看看其他方式。
kill命令:
kill [选项] 信号 [PID...]
- 信号:可以是信号的名称(如
SIGTERM
)、编号(如15
),或前缀省略的简写(如TERM
)。 - PID:目标进程的 ID(进程号),也可以是多个 PID。
例如:
# 向进程1234发信号SIGKILL信号的不同方式:
kill -SIGKILL 1234 # 使用信号名称
kill -9 1234 # 使用信号编号
kill -KILL 1234 # 使用简写
现象示例:
3. 信号处理
对于一个信号的处理,有三种方式:
1. 忽略此信号
#include <iostream>
#include <unistd.h>
#include <signal.h>
void handler(int signumber)
{
std::cout << "我是: " << getpid() << ", 我获得了⼀个信号: " << signumber
<< std::endl;
} i
nt main()
{
std::cout << "我是进程: " << getpid() << std::endl;
signal(SIGINT/*2*/, SIG_IGN); // 设置忽略信号的宏
while(true){
std::cout << "I am a process, I am waiting signal!" << std::endl;
sleep(1);
}
}
$ g++ sig.cc -o sig
$ ./sig
// 现象:
// 我是进程: 212681
// I am a process, I am waiting signal!
// I am a process, I am waiting signal!
// ^C^C^C^C^C^CI am a process, I am waiting signal! // 输⼊ctrl+c毫⽆反应
// I am a process, I am waiting signal!
2. 执行该信号的默认处理动作
#include <iostream>
#include <unistd.h>
#include <signal.h>
void handler(int signumber)
{
std::cout << "我是: " << getpid() << ", 我获得了⼀个信号: " << signumber<< std::endl;
}
int main()
{
std::cout << "我是进程: " << getpid() << std::endl;
signal(SIGINT/*2*/, SIG_DFL);
while(true){
std::cout << "I am a process, I am waiting signal!" << std::endl;
sleep(1);
}
}
$ g++ sig.cc -o sig
$ ./sig
// 我是进程: 212791
// I am a process, I am waiting signal!
// I am