【Linux操作系统】Linux系统编程中信号捕捉的实现

在Linux系统编程中,信号是一种重要的机制,用于实现进程间通信和控制。当某个事件发生时,如用户按下Ctrl+C键,操作系统会向进程发送一个信号,进程可以捕获并相应地处理该信号。本篇博客将介绍信号的分类、捕获与处理方式,以及信号的默认操作。希望通过本篇博客,你能够更好地理解Linux系统编程中信号的概念与应用。

文章目录

    • [1. 什么是信号?](#1. 什么是信号? "#1__7")
    • [2. 信号的分类](#2. 信号的分类 "#2__14")
    • [3. 信号的处理方式](#3. 信号的处理方式 "#3__23")
    • [4. 信号的捕获与处理](#4. 信号的捕获与处理 "#4__34")
      • [4.1 `signal`](#4.1 signal "#41_signal_35")
      • [4.2 `sigaction`](#4.2 sigaction "#42_sigaction_83")
    • [5. 信号的默认操作](#5. 信号的默认操作 "#5__139")
    • 总结

1. 什么是信号?

在Linux系统中,信号是一种用于进程间通信和控制的机制。当某个事件发生时,内核会向进程发送一个信号,进程可以选择捕获并处理这个信号,或者使用默认的处理方式。

信号可以由多种事件触发,例如用户按下Ctrl+C键、进程发生错误、子进程退出等。每个信号都有一个唯一的编号,以及一个预定义的默认行为。


2. 信号的分类

  1. 标准信号(Standard Signals) :这些信号的编号在1到31之间,是POSIX标准中定义的。例如,SIGINT信号(编号为2)是由用户按下Ctrl+C键触发的,SIGTERM信号(编号为15)是用于终止进程的信号。
  2. 实时信号(Real-time Signals) :这些信号的编号在32到63之间,也是POSIX标准中定义的。实时信号提供了更高的优先级和更精确的触发时间。
  3. 自定义信号(User-defined Signals) :这些信号可以由用户自定义,其编号大于64。

3. 信号的处理方式

  1. 忽略(Ignore) :进程可以选择忽略某个特定的信号,这样当该信号发生时,进程不会做任何处理。但是,某些信号是不能被忽略的,例如SIGKILL和SIGSTOP。
  2. 捕获(Catch) :进程可以通过注册信号处理函数来捕获某个信号。当信号发生时,内核会调用注册的信号处理函数来处理该信号。
  3. 执行默认操作(Default Action) :每个信号都有一个预定义的默认行为,例如终止进程、终止进程并生成核心转储文件等。

4. 信号的捕获与处理

4.1 signal

作用signal函数用于捕获和处理信号。

原型

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

void (*signal(int signum, void (*handler)(int)))(int);

参数

  • signum:要捕获的信号编号。
  • handler:信号处理函数的指针。

返回值 :返回之前对该信号的处理函数的指针。如果出错,则返回SIG_ERR

示例 :下面是一个示例,演示如何使用signal函数来捕获和处理SIGINT信号(用户按下Ctrl+C键)。

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

void sigint_handler(int signum) {
    printf("Received SIGINT signal\n");
}

int main() {
    // 注册SIGINT信号的处理函数
    signal(SIGINT, sigint_handler);

    printf("Press Ctrl+C to send SIGINT signal\n");

    while (1) {
        // 无限循环,等待信号的发生
    }

    return 0;
}

示例解释

  • 在上面的示例中,我们定义了一个名为sigint_handler的信号处理函数。当接收到SIGINT信号时,该函数会被调用,并打印一条消息。
  • main函数中,我们使用signal函数来注册sigint_handler函数作为SIGINT信号的处理函数。这样,当用户按下Ctrl+C键时,操作系统会发送SIGINT信号给进程,并调用sigint_handler函数来处理该信号。
  • main函数的无限循环中,我们等待信号的发生。这样,进程会一直运行,直到接收到SIGINT信号或其他终止信号为止。
  • 当我们按下Ctrl+C键时,会触发SIGINT信号,进程会调用sigint_handler函数,并打印一条消息。

4.2 sigaction

作用sigaction函数是另一种捕获和处理信号的方法,相比于signal函数,它提供了更多的灵活性和可靠性。

原型

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

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);

参数

  • signum:要捕获的信号编号。
  • act:一个指向struct sigaction结构的指针,用于指定新的信号处理方式。
  • oldact:一个指向struct sigaction结构的指针,用于保存之前的信号处理方式。

返回值:若成功,返回0;若出错,返回-1。

示例 :下面是一个示例,演示如何使用sigaction函数来捕获和处理SIGINT信号(用户按下Ctrl+C键)。

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

void sigint_handler(int signum) {
    printf("Received SIGINT signal\n");
}

int main() {
    struct sigaction sa;
    sa.sa_handler = sigint_handler;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    // 注册SIGINT信号的处理函数
    sigaction(SIGINT, &sa, NULL);

    printf("Press Ctrl+C to send SIGINT signal\n");

    while (1) {
        // 无限循环,等待信号的发生
    }

    return 0;
}

示例解释

  • 在上面的示例中,我们定义了一个名为sigint_handler的信号处理函数。当接收到SIGINT信号时,该函数会被调用,并打印一条消息。
  • 我们创建了一个struct sigaction结构sa,并将sigint_handler函数指定为信号处理函数。
  • 使用sigemptyset函数初始化了sa.sa_mask,表示在处理SIGINT信号时不需要阻塞其他信号。
  • sa.sa_flags设置为0,表示不需要特殊的标志。
  • 使用sigaction函数将sa结构注册为SIGINT信号的处理方式。
  • main函数的无限循环中,我们等待信号的发生。这样,进程会一直运行,直到接收到SIGINT信号或其他终止信号为止。
  • 当我们按下Ctrl+C键时,会触发SIGINT信号,进程会调用sigint_handler函数,并打印一条消息。

5. 信号的默认操作

如果不捕获某个信号或者捕获的信号处理函数返回,进程会执行该信号的默认操作。

例如,当接收到SIGTERM信号时,进程会默认终止。下面是一个示例,演示了SIGTERM信号的默认操作:

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

void sigterm_handler(int signum) {
    printf("Received SIGTERM signal\n");
}

int main() {
    // 注册SIGTERM信号的处理函数
    signal(SIGTERM, sigterm_handler);

    printf("Press Ctrl+C to send SIGTERM signal\n");

    while (1) {
        // 无限循环,等待信号的发生
    }

    return 0;
}

在上面的示例中,我们捕获了SIGTERM信号并注册了sigterm_handler函数作为处理函数。当接收到SIGTERM信号时,该函数会被调用,并打印一条消息。


总结

信号是Linux系统中用于进程间通信和控制的机制。我们可以通过捕获信号并注册处理函数来实现对信号的处理。在处理信号时,我们可以选择忽略、捕获或执行默认操作。

相关推荐
JaneZJW6 小时前
江科大STM32入门——UART通信笔记总结
笔记·stm32·单片机·嵌入式
YunB西风英7 小时前
(STM32笔记)十二、DMA的基础知识与用法 第三部分
笔记·stm32·单片机·嵌入式硬件·dma·嵌入式
JaneZJW1 天前
江科大STM32入门——IIC通信笔记总结
c语言·笔记·stm32·单片机·嵌入式硬件·嵌入式·iic
JaneZJW1 天前
江科大STM32入门——SPI通信笔记总结
笔记·stm32·单片机·嵌入式硬件·嵌入式·spi
网易独家音乐人Mike Zhou2 天前
【TI毫米波雷达】DCA1000不使用mmWave Studio的数据采集方法,以及自动化实时数据采集
c语言·单片机·mcu·物联网·嵌入式·iot·毫米波雷达
pandyele2 天前
单片机死机问题处理
单片机·嵌入式
小仇学长2 天前
嵌入式SD/TF卡通用协议-SDIO协议
嵌入式·sd卡·sdio
JaneZJW3 天前
嵌入式岗位面试八股文(篇三 操作系统(下))
linux·stm32·面试·嵌入式·c
JaneZJW3 天前
嵌入式岗位面试八股文(篇三 操作系统(上))
linux·单片机·面试·操作系统·嵌入式
Bull-man4 天前
LS1046 XFI网口接近10Gbps
linux·arm开发·嵌入式