插件窝 干货文章 Linux进程间通信机制:信号如何传递

Linux进程间通信机制:信号如何传递

信号 进程 信号处理 int 310    来源:    2025-05-07

Linux进程间通信:信号传递机制详解

信号(Signal)是Linux系统中一种重要的进程间通信(IPC)机制,用于通知进程发生了某种事件。下面我将详细介绍Linux中信号的传递机制。

信号的基本概念

信号是Linux系统中一种异步通知机制,用于: - 通知进程发生了某个事件 - 强制进程执行信号处理函数 - 用于简单的进程间通信

信号的传递方式

1. 内核发送信号

内核在以下情况下会向进程发送信号: - 硬件异常(如除零错误、段错误等) - 终端特殊按键(如Ctrl+C发送SIGINT) - 子进程状态改变(如子进程终止) - 定时器到期

2. 进程间发送信号

进程可以使用以下系统调用向其他进程发送信号: - kill(): 向指定PID的进程发送信号 - killpg(): 向指定进程组发送信号 - raise(): 向自身发送信号 - sigqueue(): 发送带附加信息的实时信号

信号的传递过程

  1. 信号生成:由内核、其他进程或自身生成信号事件
  2. 信号递送:内核将信号放入目标进程的待处理信号队列
  3. 信号处理:目标进程在合适时机(通常是返回用户态前)检查并处理信号

信号处理方式

进程可以通过以下方式处理信号: 1. 默认处理:执行系统预定义的动作(终止、忽略、暂停等) 2. 忽略信号:通过signal(SIGxxx, SIG_IGN)sigaction()忽略信号 3. 自定义处理:通过注册信号处理函数处理信号

重要系统调用

// 发送信号
int kill(pid_t pid, int sig);

// 设置信号处理
void (*signal(int sig, void (*func)(int)))(int);
int sigaction(int sig, const struct sigaction *act, struct sigaction *oldact);

// 信号集操作
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 sigprocmask(int how, const sigset_t *set, sigset_t *oldset);

// 等待信号
int pause(void);
int sigsuspend(const sigset_t *mask);

信号阻塞与未决

  • 阻塞信号:进程可以阻塞某些信号,被阻塞的信号不会立即递送
  • 未决信号:已生成但尚未递送的信号称为未决信号

实时信号与非实时信号

  • 非实时信号(1-31): 不可靠信号,可能丢失
  • 实时信号(34-64): 可靠信号,支持排队,不会丢失

实际应用示例

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void handler(int sig) {
    printf("Received signal %d\n", sig);
}

int main() {
    // 设置信号处理函数
    struct sigaction sa;
    sa.sa_handler = handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    sigaction(SIGINT, &sa, NULL);

    printf("Waiting for signal...\n");
    pause(); // 等待信号

    return 0;
}

注意事项

  1. 信号处理函数应尽量简单,避免使用不可重入函数
  2. 多线程程序中,信号处理更加复杂,建议使用sigwait()替代信号处理函数
  3. 某些信号(如SIGKILL)不能被捕获或忽略
  4. 信号传递是异步的,不能保证实时性

信号机制虽然简单,但在Linux系统编程中非常重要,合理使用可以构建健壮的应用程序。