Linux 信号是怎么让程序响应事件和控制进程

在 Linux 中,signal(信号)是一种用于进程间通信的机制,用于通知进程发生了某些事件。信号可以由操作系统内核、其他进程或自身发送,并且可以用于控制进程的行为。以下是对 Linux 信号的一个简要概述,包括信号的类型、用法、处理和示例。
一、信号的基本概念
signal 信号是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断。软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用 kill 发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。
二、常见信号
使用kill -l命令就可以查看所有的信号,常见信号如下表:
| 信号名 | 信号编号 | 产生原因 | 默认处理方式 |
| SIGHUP | 1 | 关闭终端 | 终止 |
| SIGINT | 2 | ctrl + c | 终止 |
| SIGQUIT | 3 | ctrl + \ | 终止+产生 1 个转储文件 |
| SIGABRT | 6 | abort()函数 | 终止+转储 |
| SIGPE | 8 | 算术错误 | 终止 |
| SIGKILL | 9 | kill -9 pid | 终止,不可捕获/忽略 |
| SIGUSR1 | 10 | 自定义 | 忽略 |
| SIGSEGV | 11 | 段错误 | 终止+产生 1 个转储文件 |
| SIGUSR2 | 12 | 自定义 | 忽略 |
| SIGALRM | 14 | alarm()函数 | 终止 |
| SIGTERM | 15 | kill pid | 终止(可以被忽略) |
| SIGCHLD | 17 | 子状态变化 | 忽略 |
| SIGSTOP | 19 | ctrl + z | 暂停,不可捕获/忽略 |
三、信号发送
信号可以通过多种方式发送:
- 由操作系统内核发送:如当进程发生除零错误时。
- 由其他进程发送:使用 kill 命令或 kill() 系统调用。
- 由自身发送:使用 raise() 函数。
示例:
kill -signal pid
signal 是要传递的信号的数字或名称,pid 是信号应该发送到的进程 ID。
例如,如果要向一个进程发送 kill 信号,可以使用以下命令
kill -9 1231
kill -9 代表的信号是 SIGKILL,表示进程被终止,需要立即退出。进程 ID 为 1231 进程将退出。
四、信号的处理
进程可以选择如何处理接收到的信号。主要的处理方式有三种:
- 默认处理:每个信号都有一个默认的处理方式,例如 SIGKILL 会强制终止进程。
- 捕获信号:进程可以注册一个信号处理函数,执行自定义逻辑。例如,当接收到 SIGINT 时,可以选择清理资源后退出。
- 忽略信号:进程可以选择不处理某些信号,例如忽略 SIGPIPE。
程序中怎么使用,举个示例:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void signal_handler(int signum) {
printf("Received signal %d\n", signum);
exit(0);
}
int main() {
// 注册 SIGINT 信号的处理函数
signal(SIGINT, signal_handler);
while (1) {
printf("Running... Press Ctrl+C to stop.\n");
sleep(1);
}
return 0;
}
上面的程序在终端中运行,键盘按 Ctrl+c,程序就终端,注册函数打印。
五、信号的阻塞与解除阻塞
进程可以选择屏蔽某些信号,以防止在特定代码段中被打断。可以使用 sigprocmask() 函数来实现信号的阻塞和解除阻塞。
代码示例:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void signal_handler(int signum) {
printf("Received signal %d\n", signum);
}
int main() {
// 注册信号处理函数
signal(SIGINT, signal_handler);
// 阻塞 SIGINT 信号
sigset_t newset, oldset;
sigemptyset(&newset);
sigaddset(&newset, SIGINT);
sigprocmask(SIG_BLOCK, &newset, &oldset);
printf("SIGINT is blocked. Press Ctrl+C.\n");
sleep(5); // 等待 5 秒
// 解除阻塞
sigprocmask(SIG_UNBLOCK, &newset, NULL);
printf("SIGINT is unblocked. Press Ctrl+C.\n");
while (1) {
sleep(1);
}
return 0;
}
学习 Linux ,了解信号是非常重要的,从事开发的小伙伴在编写多进程或需要实时响应的应用程序时,理解和掌握信号的使用是必不可少的。
以上关于Linux 信号是怎么让程序响应事件和控制进程的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
重要:如软件存在付费、会员、充值等,均属软件开发者或所属公司行为,与本站无关,网友需自行判断
码云笔记 » Linux 信号是怎么让程序响应事件和控制进程
微信
支付宝