当前位置:首页>Linux>浅谈 Linux 信号:如何让程序响应事件和控制进程

浅谈 Linux 信号:如何让程序响应事件和控制进程

  • 2026-10-11 08:38:06
浅谈 Linux 信号:如何让程序响应事件和控制进程
大家好!我是大虫子🐛!
之前小编总结过一篇关于 Linux 进程间通讯的几种方式,其中有一个是关于 signal(信号)的,总结得有点太笼统了,主要目的是想简单介绍下 Linux 中进程间通讯的方式。感兴趣的小伙伴可以去看下,文章链接放在文章末尾了哈~
开始今天的正题~小编将在本文详细介绍下信号~
在 Linux 中,signal(信号)是一种用于进程间通信的机制,用于通知进程发生了某些事件。信号可以由操作系统内核、其他进程或自身发送,并且可以用于控制进程的行为。以下是对 Linux 信号的一个简要概述,包括信号的类型、用法、处理和示例。
1、信号的基本概念
signal 信号是进程之间相互传递消息的一种方法,信号全称为软中断信号,也有人称作软中断。软中断信号(signal,又简称为信号)用来通知进程发生了异步事件。进程之间可以互相通过系统调用kill发送软中断信号。内核也可以因为内部事件而给进程发送信号,通知进程发生了某个事件。注意,信号只是用来通知某进程发生了什么事件,并不给该进程传递任何数据。
2、常见信号
使用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

暂停,不可捕获/忽略

3、信号发送
信号可以通过多种方式发送:
  • 由操作系统内核发送:如当进程发生除零错误时。
  • 由其他进程发送:使用 kill 命令或 kill() 系统调用。
  • 由自身发送:使用 raise() 函数。
示例:
kill -signal pid
signal 是要传递的信号的数字或名称,pid  是信号应该发送到的进程 ID。
例如,如果要向一个进程发送kill信号,可以使用以下命令
kill -9 1231
kill -9代表的信号是 SIGKILL,表示进程被终止,需要立即退出。进程 ID为1231进程将退出。
4、信号的处理
进程可以选择如何处理接收到的信号。主要的处理方式有三种:
  • 默认处理:每个信号都有一个默认的处理方式,例如 SIGKILL 会强制终止进程。
  • 捕获信号:进程可以注册一个信号处理函数,执行自定义逻辑。例如,当接收到 SIGINT 时,可以选择清理资源后退出。
  • 忽略信号:进程可以选择不处理某些信号,例如忽略 SIGPIPE。
程序中怎么使用,举个示例:
#include<stdio.h>#include<stdlib.h>#include<signal.h>#include<unistd.h>voidsignal_handler(int signum){    printf("Received signal %d\n", signum);    exit(0);}intmain(){    // 注册 SIGINT 信号的处理函数    signal(SIGINT, signal_handler);    while (1) {        printf("Running... Press Ctrl+C to stop.\n");        sleep(1);    }    return 0;}
上面的程序在终端中运行,键盘按Ctrl+c,程序就终端,注册函数打印。
5、信号的阻塞与解除阻塞
进程可以选择屏蔽某些信号,以防止在特定代码段中被打断。可以使用 sigprocmask() 函数来实现信号的阻塞和解除阻塞。
代码示例:
#include<stdio.h>#include<signal.h>#include<unistd.h>voidsignal_handler(int signum){    printf("Received signal %d\n", signum);}intmain(){    // 注册信号处理函数    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 进程通信头疼!Linux 开发者必备:进程间通信(IPC)》

最新文章

随机文章