Linux 信号详解

目录

前言

一、什么是信号?

1.信号的特点

二、信号的基本概念

1.信号的生命周期

2.信号编号与名称

3.信号的来源

三、常见信号列表

1.标准信号(1-31)

2.重要信号详解

[(1)SIGINT (2) - 中断信号](#(1)SIGINT (2) - 中断信号)

[(2)SIGKILL (9) - 强制终止](#(2)SIGKILL (9) - 强制终止)

[(3)SIGTERM (15) - 正常终止](#(3)SIGTERM (15) - 正常终止)

[(4)SIGSEGV (11) - 段错误](#(4)SIGSEGV (11) - 段错误)

[(5)SIGCHLD (17) - 子进程状态改变](#(5)SIGCHLD (17) - 子进程状态改变)

四、信号的产生方式

[1. 终端按键产生](#1. 终端按键产生)

[2. 硬件异常产生](#2. 硬件异常产生)

[3. 系统调用产生](#3. 系统调用产生)

[(1)kill() 函数](#(1)kill() 函数)

[(2)raise() 函数](#(2)raise() 函数)

[(3)abort() 函数](#(3)abort() 函数)

[4. 软件条件产生](#4. 软件条件产生)

[(1)alarm() 函数](#(1)alarm() 函数)

[(2)setitimer() 函数](#(2)setitimer() 函数)

五、信号的处理方式

1.三种处理方式

[2.signal() 函数(传统方式)](#2.signal() 函数(传统方式))

[3.sigaction() 函数(推荐方式)](#3.sigaction() 函数(推荐方式))

[(1)sigaction 使用示例](#(1)sigaction 使用示例)

[(2)使用 SA_SIGINFO 获取详细信息](#(2)使用 SA_SIGINFO 获取详细信息)

六、信号集操作

1.信号集类型

2.信号集操作函数

3.信号集操作示例

七、信号的阻塞与未决

1.基本概念

2.信号阻塞相关函数

3.信号阻塞示例

4.信号处理流程图

八、实时信号

1.实时信号特点

2.实时信号操作

4.实时信号示例

九、信号处理的最佳实践

[1. 信号处理函数的安全要求](#1. 信号处理函数的安全要求)

[2. 使用自管道(Self-Pipe)技巧](#2. 使用自管道(Self-Pipe)技巧)

[3. 优雅的信号处理模式](#3. 优雅的信号处理模式)

[4. 子进程信号处理](#4. 子进程信号处理)

[5. 信号安全日志记录](#5. 信号安全日志记录)

九、常用命令参考

1.发送信号

2.查看信号信息

3.信号调试

十、总结


前言

信号是Linux/Unix系统中的异步事件通知机制,用于进程间通信和异常处理。

本文系统介绍了信号的基本概念、常见信号类型(如SIGINT、SIGKILL、SIGTERM等)、信号产生方式(终端按键、硬件异常、系统调用等)以及信号处理方法(signal/sigaction)。

重点阐述了信号阻塞、实时信号特性,并提供了信号处理的最佳实践,包括安全函数使用、自管道技巧和子进程处理方案。

文章还包含常用命令参考,可帮助开发者们正确使用信号机制进行进程管理和异常处理。


一、什么是信号?

信号(Signal) 是 Linux/Unix 系统中一种异步事件通知机制 ,用于通知进程发生了某个特定事件。信号是软件中断的一种形式,它提供了一种处理异步事件的方法。

1.信号的特点

  • 异步性:信号可以在任何时候发送给进程,进程无法预知信号何时到达
  • 简单性:信号携带的信息量很少,仅表示某种事件的发生
  • 优先级:信号的处理会打断进程的正常执行流程
  • 可处理性:进程可以选择捕获、忽略或执行默认操作

二、信号的基本概念

1.信号的生命周期

复制代码
信号产生 → 信号注册 → 信号处理

2.信号编号与名称

每个信号都有一个唯一的整数编号(1-31 为标准信号,34-64 为实时信号)和一个符号名称(如 SIGINTSIGKILL)。

3.信号的来源

来源类型 说明 示例
终端输入 用户通过键盘发送 Ctrl+C, Ctrl+\
硬件异常 硬件错误产生 除零错误、非法内存访问
系统调用 通过函数发送 kill(), raise(), alarm()
软件条件 特定软件条件 定时器到期、管道断开

三、常见信号列表

1.标准信号(1-31)

信号 编号 默认动作 说明
SIGHUP 1 终止 挂起信号,终端断开时发送
SIGINT 2 终止 中断信号,Ctrl+C 产生
SIGQUIT 3 终止+核心转储 退出信号,Ctrl+\ 产生
SIGILL 4 终止+核心转储 非法指令
SIGTRAP 5 终止+核心转储 跟踪/断点陷阱
SIGABRT 6 终止+核心转储 异常终止(abort)
SIGBUS 7 终止+核心转储 总线错误
SIGFPE 8 终止+核心转储 浮点运算异常
SIGKILL 9 终止 强制终止,不可捕获/忽略
SIGUSR1 10 终止 用户自定义信号1
SIGSEGV 11 终止+核心转储 段错误(非法内存访问)
SIGUSR2 12 终止 用户自定义信号2
SIGPIPE 13 终止 管道破裂(写入无读端管道)
SIGALRM 14 终止 定时器信号(alarm)
SIGTERM 15 终止 正常终止信号
SIGCHLD 17 忽略 子进程状态改变
SIGCONT 18 继续 继续执行暂停的进程
SIGSTOP 19 暂停 暂停进程,不可捕获/忽略
SIGTSTP 20 暂停 终端暂停信号,Ctrl+Z 产生
SIGTTIN 21 暂停 后台进程读终端
SIGTTOU 22 暂停 后台进程写终端

2.重要信号详解

(1)SIGINT (2) - 中断信号
复制代码
# 按 Ctrl+C 发送
# 默认行为:终止进程
# 常用于:优雅地终止前台进程
(2)SIGKILL (9) - 强制终止
复制代码
kill -9 <pid>
# 特点:
# - 无法被捕获、阻塞或忽略
# - 立即终止进程
# - 进程无法进行清理操作
# 建议:仅在无法正常终止时使用
(3)SIGTERM (15) - 正常终止
复制代码
kill <pid>        # 默认发送 SIGTERM
kill -15 <pid>
# 特点:
# - 可以被捕获和处理
# - 允许进程进行清理操作
# - 推荐的首选终止方式
(4)SIGSEGV (11) - 段错误
复制代码
// 常见原因:
// - 访问未分配的内存
// - 访问已释放的内存
// - 数组越界访问
// - 解引用空指针

int *p = NULL;
*p = 10;  // 触发 SIGSEGV
(5)SIGCHLD (17) - 子进程状态改变
复制代码
// 子进程终止或停止时发送给父进程
// 默认行为:忽略
// 常用于:防止僵尸进程

四、信号的产生方式

1. 终端按键产生

bash 复制代码
Ctrl+C  → SIGINT   (中断)
Ctrl+\  → SIGQUIT  (退出)
Ctrl+Z  → SIGTSTP  (暂停)

2. 硬件异常产生

bash 复制代码
// 除零错误 → SIGFPE
int a = 10 / 0;

// 非法内存访问 → SIGSEGV
int *p = (int *)0x12345;
*p = 100;

3. 系统调用产生

(1)kill() 函数
bash 复制代码
#include <signal.h>
#include <sys/types.h>

int kill(pid_t pid, int sig);
// 功能:向指定进程发送信号
// 参数:
//   pid > 0: 发送给指定进程
//   pid = 0: 发送给同组所有进程
//   pid = -1: 发送给所有有权限的进程
//   pid < -1: 发送给进程组 |pid| 中的所有进程
// 返回值:成功返回0,失败返回-1

// 示例
kill(1234, SIGTERM);   // 向PID为1234的进程发送SIGTERM
kill(0, SIGUSR1);      // 向同组所有进程发送SIGUSR1
(2)raise() 函数
bash 复制代码
#include <signal.h>

int raise(int sig);
// 功能:向当前进程自身发送信号
// 等价于:kill(getpid(), sig)

// 示例
raise(SIGTERM);  // 自我终止
(3)abort() 函数
bash 复制代码
#include <stdlib.h>

void abort(void);
// 功能:异常终止程序,产生 SIGABRT 信号
// 特点:会生成核心转储文件(如果允许)

4. 软件条件产生

(1)alarm() 函数
bash 复制代码
#include <unistd.h>

unsigned int alarm(unsigned int seconds);
// 功能:设置定时器,seconds秒后发送 SIGALRM 信号
// 返回值:返回上次定时器剩余时间,无上次定时器返回0
// 注意:每个进程只能有一个alarm定时器

// 示例
#include <stdio.h>
#include <unistd.h>
#include <signal.h>

void alarm_handler(int sig) {
    printf("定时器到期!\n");
}

int main() {
    signal(SIGALRM, alarm_handler);
    alarm(5);  // 5秒后发送SIGALRM
    
    printf("等待定时器...\n");
    pause();   // 等待信号
    
    return 0;
}
(2)setitimer() 函数
复制代码
#include <sys/time.h>

int setitimer(int which, const struct itimerval *new_value,
              struct itimerval *old_value);
// 功能:设置高精度定时器
// which参数:
//   ITIMER_REAL: 真实时间,发送 SIGALRM
//   ITIMER_VIRTUAL: 用户态CPU时间,发送 SIGVTALRM
//   ITIMER_PROF: 用户态+内核态CPU时间,发送 SIGPROF

struct itimerval {
    struct timeval it_interval;  // 间隔时间(周期性定时)
    struct timeval it_value;     // 首次到期时间
};

struct timeval {
    time_t tv_sec;      // 秒
    suseconds_t tv_usec; // 微秒
};

五、信号的处理方式

1.三种处理方式

  1. 默认动作(Default):执行系统预设的操作
  2. 忽略信号(Ignore):丢弃信号,不执行任何操作
  3. 捕获信号(Catch):执行自定义的信号处理函数

2.signal() 函数(传统方式)

bash 复制代码
#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);
// 参数:
//   signum: 信号编号
//   handler: 处理方式
//     SIG_DFL: 默认处理
//     SIG_IGN: 忽略信号
//     自定义函数指针: 捕获信号

// 示例代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

// 自定义信号处理函数
void sigint_handler(int sig) {
    printf("\n捕获到 SIGINT 信号(编号:%d)\n", sig);
    printf("正在执行清理工作...\n");
    // 执行清理操作
    _exit(0);  // 安全退出
}

int main() {
    // 设置 SIGINT 的处理方式
    if (signal(SIGINT, sigint_handler) == SIG_ERR) {
        perror("signal");
        return 1;
    }
    
    printf("按 Ctrl+C 测试信号处理(PID: %d)\n", getpid());
    
    while (1) {
        printf("工作中...\n");
        sleep(2);
    }
    
    return 0;
}

3.sigaction() 函数(推荐方式)

bash 复制代码
#include <signal.h>

int sigaction(int signum, const struct sigaction *act,
              struct sigaction *oldact);
// 功能:更强大的信号处理设置函数
// 参数:
//   signum: 信号编号
//   act: 新的处理方式(NULL表示不设置)
//   oldact: 保存旧的处理方式(NULL表示不保存)

struct sigaction {
    void (*sa_handler)(int);           // 信号处理函数
    void (*sa_sigaction)(int, siginfo_t *, void *); // 高级处理函数
    sigset_t sa_mask;                   // 信号屏蔽字
    int sa_flags;                       // 标志位
    void (*sa_restorer)(void);          // 已废弃
};

// sa_flags 常用标志
#define SA_RESTART      // 自动重启被中断的系统调用
#define SA_NODEFER      // 不自动阻塞该信号
#define SA_RESETHAND    // 执行后恢复默认处理
#define SA_SIGINFO      // 使用 sa_sigaction 处理函数
(1)sigaction 使用示例
bash 复制代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

void sigint_handler(int sig) {
    write(STDOUT_FILENO, "\n收到 SIGINT,优雅退出\n", 25);
    _exit(0);
}

int main() {
    struct sigaction sa;
    
    // 清空结构体
    memset(&sa, 0, sizeof(sa));
    
    // 设置处理函数
    sa.sa_handler = sigint_handler;
    
    // 设置标志:自动重启被中断的系统调用
    sa.sa_flags = SA_RESTART;
    
    // 清空信号屏蔽字
    sigemptyset(&sa.sa_mask);
    
    // 安装信号处理器
    if (sigaction(SIGINT, &sa, NULL) == -1) {
        perror("sigaction");
        return 1;
    }
    
    printf("按 Ctrl+C 退出(PID: %d)\n", getpid());
    
    while (1) {
        printf("运行中...\n");
        sleep(2);
    }
    
    return 0;
}
(2)使用 SA_SIGINFO 获取详细信息
bash 复制代码
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void advanced_handler(int sig, siginfo_t *info, void *context) {
    printf("\n=== 信号详细信息 ===\n");
    printf("信号编号: %d\n", sig);
    printf("发送进程PID: %d\n", info->si_pid);
    printf("发送进程UID: %d\n", info->si_uid);
    printf("信号值: %d\n", info->si_value.sival_int);
    printf("==================\n");
}

int main() {
    struct sigaction sa;
    
    sa.sa_sigaction = advanced_handler;
    sa.sa_flags = SA_SIGINFO;  // 使用三参数处理函数
    sigemptyset(&sa.sa_mask);
    
    sigaction(SIGUSR1, &sa, NULL);
    
    printf("等待 SIGUSR1 信号(PID: %d)\n", getpid());
    
    while (1) {
        pause();
    }
    
    return 0;
}

六、信号集操作

1.信号集类型

bash 复制代码
#include <signal.h>

typedef struct {
    unsigned long sig[(64 + 8 * sizeof(unsigned long) - 1) / 
                      (8 * sizeof(unsigned long))];
} sigset_t;
// 用于表示一组信号的位图结构

2.信号集操作函数

bash 复制代码
#include <signal.h>

// 清空信号集
int sigemptyset(sigset_t *set);

// 填充所有信号到信号集
int sigfillset(sigset_t *set);

// 添加单个信号到信号集
int sigaddset(sigset_t *set, int signum);

// 从信号集中删除单个信号
int sigdelset(sigset_t *set, int signum);

// 检查信号是否在信号集中
int sigismember(const sigset_t *set, int signum);

3.信号集操作示例

bash 复制代码
#include <stdio.h>
#include <signal.h>

int main() {
    sigset_t set;
    
    // 清空信号集
    sigemptyset(&set);
    
    // 添加 SIGINT 和 SIGTERM
    sigaddset(&set, SIGINT);
    sigaddset(&set, SIGTERM);
    
    // 检查 SIGINT 是否在集合中
    if (sigismember(&set, SIGINT)) {
        printf("SIGINT 在信号集中\n");
    }
    
    // 检查 SIGKILL 是否在集合中
    if (!sigismember(&set, SIGKILL)) {
        printf("SIGKILL 不在信号集中\n");
    }
    
    // 删除 SIGINT
    sigdelset(&set, SIGINT);
    
    // 填充所有信号
    sigfillset(&set);
    printf("信号集已填充所有信号\n");
    
    return 0;
}

七、信号的阻塞与未决

1.基本概念

  • 信号阻塞(Blocked) :信号被阻塞后,不会立即递达,而是保持未决状态
  • 信号未决(Pending):信号已产生但尚未被处理的状态
  • 信号递达(Delivered):信号被处理的时刻

2.信号阻塞相关函数

bash 复制代码
#include <signal.h>

// 检查或修改进程的信号屏蔽字
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
// how参数:
//   SIG_BLOCK: 将set中的信号添加到屏蔽字
//   SIG_UNBLOCK: 从屏蔽字中移除set中的信号
//   SIG_SETMASK: 将屏蔽字设置为set

// 获取当前未决信号集
int sigpending(sigset_t *set);

3.信号阻塞示例

bash 复制代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void handler(int sig) {
    printf("处理信号: %d\n", sig);
}

int main() {
    sigset_t block_set, pending_set;
    
    // 设置 SIGINT 处理函数
    signal(SIGINT, handler);
    
    // 创建要阻塞的信号集
    sigemptyset(&block_set);
    sigaddset(&block_set, SIGINT);
    
    printf("阻塞 SIGINT 5秒,请在这5秒内按 Ctrl+C\n");
    
    // 阻塞 SIGINT
    sigprocmask(SIG_BLOCK, &block_set, NULL);
    
    sleep(5);
    
    // 检查未决信号
    sigpending(&pending_set);
    if (sigismember(&pending_set, SIGINT)) {
        printf("SIGINT 处于未决状态\n");
    }
    
    printf("解除阻塞,信号将被处理\n");
    
    // 解除阻塞
    sigprocmask(SIG_UNBLOCK, &block_set, NULL);
    
    sleep(1);
    printf("程序结束\n");
    
    return 0;
}

4.信号处理流程图

复制代码
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│   信号产生   │ ──→ │   信号未决   │ ──→ │   信号递达   │
│  (Generated)│     │  (Pending)  │     │ (Delivered) │
└─────────────┘     └─────────────┘     └─────────────┘
                            ↑
                            │ 信号被阻塞
                      ┌─────────────┐
                      │   信号阻塞   │
                      │  (Blocked)  │
                      └─────────────┘

八、实时信号

1.实时信号特点

特性 标准信号 实时信号
编号范围 1-31 34-64
排队 不支持(相同信号只保留一个) 支持(多个相同信号排队)
携带数据 不能 可以(通过 sigqueue)
优先级 编号小的优先
用途 系统预定义 用户自定义

2.实时信号操作

bash 复制代码
#include <signal.h>
#include <unistd.h>

// 发送带数据的实时信号
int sigqueue(pid_t pid, int sig, const union sigval value);

union sigval {
    int sival_int;      // 整型数据
    void *sival_ptr;    // 指针数据(仅同一进程内有效)
};

4.实时信号示例

bash 复制代码
#define _GNU_SOURCE
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void rt_handler(int sig, siginfo_t *info, void *context) {
    printf("收到实时信号 %d,数据: %d\n", sig, info->si_value.sival_int);
}

int main() {
    struct sigaction sa;
    pid_t pid = getpid();
    
    sa.sa_sigaction = rt_handler;
    sa.sa_flags = SA_SIGINFO;
    sigemptyset(&sa.sa_mask);
    
    // 注册实时信号处理函数
    sigaction(SIGRTMIN, &sa, NULL);
    
    printf("进程 PID: %d\n", pid);
    printf("向自己发送3个实时信号...\n");
    
    // 发送带数据的实时信号
    union sigval value;
    for (int i = 1; i <= 3; i++) {
        value.sival_int = i * 100;
        sigqueue(pid, SIGRTMIN, value);
    }
    
    sleep(1);
    return 0;
}

九、信号处理的最佳实践

1. 信号处理函数的安全要求

信号处理函数中只能调用异步信号安全函数:

bash 复制代码
// ✅ 安全的函数
write(), _exit(), kill(), sigaction()
getpid(), getppid(), sleep()

// ❌ 不安全的函数(避免使用)
printf(), malloc(), free(), exit()
fopen(), fread(), fwrite()
pthread_mutex_lock(), 大部分库函数

2. 使用自管道(Self-Pipe)技巧

bash 复制代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>

static int pipefd[2];

void signal_handler(int sig) {
    // 只写入一个字节到管道
    write(pipefd[1], &sig, 1);
}

int main() {
    fd_set readfds;
    char sig;
    
    // 创建管道
    pipe(pipefd);
    fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
    fcntl(pipefd[1], F_SETFL, O_NONBLOCK);
    
    // 设置信号处理
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    printf("使用 select 等待信号(PID: %d)\n", getpid());
    
    while (1) {
        FD_ZERO(&readfds);
        FD_SET(pipefd[0], &readfds);
        
        select(pipefd[0] + 1, &readfds, NULL, NULL, NULL);
        
        if (FD_ISSET(pipefd[0], &readfds)) {
            read(pipefd[0], &sig, 1);
            printf("主循环中处理信号: %d\n", (int)sig);
            
            if (sig == SIGINT || sig == SIGTERM) {
                printf("退出程序\n");
                break;
            }
        }
    }
    
    close(pipefd[0]);
    close(pipefd[1]);
    return 0;
}

3. 优雅的信号处理模式

bash 复制代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdatomic.h>

// 使用原子变量作为信号标志
static atomic_int signal_received = 0;

void signal_handler(int sig) {
    // 只设置标志,不做复杂操作
    atomic_store(&signal_received, sig);
}

void process_work() {
    // 模拟工作
    static int counter = 0;
    printf("工作进行中... %d\n", ++counter);
    sleep(1);
}

void cleanup() {
    printf("执行清理操作...\n");
    // 关闭文件、释放资源等
}

int main() {
    struct sigaction sa;
    
    sa.sa_handler = signal_handler;
    sa.sa_flags = SA_RESTART;
    sigemptyset(&sa.sa_mask);
    
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
    
    printf("程序运行中(PID: %d)\n", getpid());
    
    while (1) {
        process_work();
        
        // 在主循环中检查信号
        int sig = atomic_load(&signal_received);
        if (sig != 0) {
            printf("\n收到信号 %d,准备退出\n", sig);
            cleanup();
            break;
        }
    }
    
    return 0;
}

4. 子进程信号处理

bash 复制代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>

void sigchld_handler(int sig) {
    int status;
    pid_t pid;
    
    // 使用 WNOHANG 非阻塞等待所有子进程
    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
        printf("子进程 %d 已退出\n", pid);
    }
}

int main() {
    struct sigaction sa;
    
    // 设置 SIGCHLD 处理函数,防止僵尸进程
    sa.sa_handler = sigchld_handler;
    sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
    sigemptyset(&sa.sa_mask);
    
    sigaction(SIGCHLD, &sa, NULL);
    
    // 创建子进程
    for (int i = 0; i < 3; i++) {
        pid_t pid = fork();
        if (pid == 0) {
            // 子进程
            printf("子进程 %d 启动\n", getpid());
            sleep(2 + i);
            printf("子进程 %d 退出\n", getpid());
            _exit(0);
        }
    }
    
    printf("父进程等待子进程...\n");
    
    // 父进程继续工作
    for (int i = 0; i < 10; i++) {
        printf("父进程工作中...\n");
        sleep(1);
    }
    
    return 0;
}

5. 信号安全日志记录

bash 复制代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>

// 信号安全的日志函数
void safe_log(const char *msg) {
    // 使用 write 而不是 printf
    write(STDOUT_FILENO, msg, strlen(msg));
    write(STDOUT_FILENO, "\n", 1);
}

void handler(int sig) {
    const char *msg;
    switch (sig) {
        case SIGINT:  msg = "收到 SIGINT"; break;
        case SIGTERM: msg = "收到 SIGTERM"; break;
        case SIGALRM: msg = "收到 SIGALRM"; break;
        default:      msg = "收到未知信号"; break;
    }
    safe_log(msg);
}

int main() {
    signal(SIGINT, handler);
    signal(SIGTERM, handler);
    signal(SIGALRM, handler);
    
    alarm(3);
    
    safe_log("程序启动,3秒后收到SIGALRM");
    
    while (1) {
        pause();
    }
    
    return 0;
}

九、常用命令参考

1.发送信号

bash 复制代码
# 发送 SIGTERM(默认)
kill <pid>

# 发送特定信号
kill -SIGINT <pid>
kill -2 <pid>        # 数字形式
kill -9 <pid>        # 强制终止

# 向进程组发送信号
kill -TERM -<pgid>

# 使用 pkill 按名称发送
pkill -INT process_name
pkill -f "pattern"

# 使用 killall
killall -TERM process_name

2.查看信号信息

bash 复制代码
# 列出所有信号
kill -l

# 查看信号编号对应的名称
kill -l 9    # 输出: KILL
kill -l 15   # 输出: TERM

# 查看信号帮助
man 7 signal
man sigaction

3.信号调试

bash 复制代码
# 使用 strace 跟踪信号
strace -e trace=signal ./program

# 查看进程挂起的信号
cat /proc/<pid>/status | grep Sig
# SigPnd: 线程组共享的未决信号
# SigBlk: 阻塞的信号
# SigIgn: 忽略的信号
# SigCgt: 捕获的信号

十、总结

要点 说明
信号本质 软件中断,异步事件通知机制
可靠信号 SIGKILL (9) 和 SIGSTOP (19) 不可捕获/忽略
推荐终止 优先使用 SIGTERM (15),允许进程清理
推荐API 使用 sigaction() 替代 signal()
处理安全 信号处理器中只使用异步信号安全函数
实时信号 支持排队和携带数据,用于应用自定义
相关推荐
A小辣椒10 小时前
TShark:Wireshark CLI 功能
linux
A小辣椒14 小时前
TShark:基础知识
linux
AlfredZhao16 小时前
OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G?
linux·oci
AlfredZhao1 天前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334662 天前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪2 天前
linux 拷贝文件或目录到指定的位置
linux
大树882 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠2 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质2 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
bush42 天前
嵌入式linux学习记录十四、术语
linux·嵌入式