学习笔记9(信号和信号处理)

一、知识点梳理

(一)Linux信号示例
在Linux系统中,信号是用来通知进程发生了某个事件的一种机制。以下是一些常见的Linux信号及其示例:

  1. SIGINT (2) - 中断信号

    • 示例:通过在终端按下Ctrl+C,可以发送SIGINT信号给前台进程,通常用于中断运行中的程序。
  2. SIGTERM (15) - 终止信号

    • 示例:使用kill命令发送SIGTERM信号,如kill -15 PID,用于请求进程正常终止。
  3. SIGKILL (9) - 强制终止信号

    • 示例:使用kill命令发送SIGKILL信号,如kill -9 PID,强制终止进程。
  4. SIGCHLD (17) - 子进程状态改变信号

    • 示例:父进程可以通过捕捉SIGCHLD信号来处理子进程的退出状态。
  5. SIGALRM (14) - 定时器信号

    • 示例:通过设置定时器,可以在一定时间后发送SIGALRM信号。

(二)Linux信号处理

1.信号类型

(1) SIGKILL (9) - 强制终止信号
(2) SIGALRM (14) - 定时器信号
(3) SIGSTOP (19) - 停止信号
(4) SIGVTALRM (26) - 虚拟定时器信号
(5) SIGPROF (27) - 以及定时器信号

2.信号来源

(1) 用户输入: 用户可以通过在终端中执行特定的键盘操作来生成信号。例如,按下Ctrl+C键盘组合键会发送SIGINT信号给前台运行的进程,通常用于中断正在执行的程序。

(2)操作系统事件: 操作系统本身可以生成信号来通知进程发生了特定事件。例如,当一个子进程退出时,操作系统会向其父进程发送SIGCHLD信号,以通知父进程子进程的状态改变。

(3)其他进程: 一个进程可以通过系统调用如 killkillpg 向另一个进程发送信号。这种机制可以用于进程间的通信和控制。例如,通过kill命令可以向指定进程发送不同的信号。

(4)硬件异常: 一些信号可以由硬件异常触发,例如:

  • SIGSEGV(段错误信号):当程序访问无效的内存地址时触发。
  • SIGFPE(浮点异常信号):当浮点运算错误发生时触发。
  • 其他硬件错误引起的信号。

3.信号处理函数

在Linux中,signal 函数和 sigaction 函数都是用于处理信号的函数,但它们在实现上有一些不同。

(1)signal 函数:

signal 函数是比较早期的信号处理函数,它的原型如下:

#include <signal.h>

void (*signal(int signum, void (*handler)(int)))(int);
  • signum: 表示要处理的信号的编号,例如 SIGINTSIGTERM 等。
  • handler: 是一个函数指针,指向处理信号的函数。可以是预定义的处理函数,也可以是用户自定义的函数。

(2) sigaction 函数:

sigaction 函数是相对较新的信号处理函数,提供了更为灵活和可靠的信号处理机制。它的原型如下:

#include <signal.h>

int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
  • signum: 表示要处理的信号的编号。
  • act: 是一个指向 struct sigaction 结构的指针,用于设置信号处理的行为。
  • oldact: 是一个指向 struct sigaction 结构的指针,用于获取之前的信号处理行为。

struct sigaction 结构定义如下:

struct sigaction {
    void (*sa_handler)(int);  // 处理函数
    void (*sa_sigaction)(int, siginfo_t *, void *);  // 用于带有附加信息的信号处理
    sigset_t sa_mask;  // 信号掩码
    int sa_flags;  // 标志
    void (*sa_restorer)(void);  // 用于实现一些特殊行为的恢复函数
};

(三)信号处理步骤

  1. 注册信号处理函数: 进程需要注册一个信号处理函数,以便在接收到信号时执行相应的处理逻辑。可以使用 signal 函数或 sigaction 函数来注册信号处理函数。

  2. 发送信号: 信号可以由多种来源产生,例如用户输入、操作系统事件、其他进程或硬件异常。当信号产生时,操作系统会将信号发送给接收进程。

  3. 中断当前操作: 当进程接收到信号时,它会中断当前的操作,并跳转到信号处理函数执行相应的处理逻辑。

  4. 执行信号处理函数: 进程会执行注册的信号处理函数,以处理接收到的信号。在信号处理函数中,可以执行相应的处理逻辑,例如关闭文件、释放资源等。

  5. 恢复操作: 当信号处理函数执行完毕后,进程会恢复之前的操作,并继续执行。如果信号处理函数终止了进程,那么进程将会退出。

(四)信号用作IPC

在Linux中,信号也可以用作进程间通信(IPC)的一种方式。虽然信号不是专门为IPC设计的,但它可以用于在进程之间传递简单的信息和通知。使用信号进行IPC通常包括以下步骤:

  1. 发送信号: 发送进程使用 kill 函数向接收进程发送信号。可以使用 SIGUSR1SIGUSR2 信号来进行自定义通信。

  2. 注册信号处理函数: 接收进程需要注册一个信号处理函数,以便在接收到信号时执行相应的处理逻辑。可以使用 signal 函数或 sigaction 函数来注册信号处理函数。

  3. 处理信号: 当接收进程接收到信号时,它会中断当前的操作,并跳转到信号处理函数执行相应的处理逻辑。在信号处理函数中,可以执行相应的处理逻辑,例如更新共享内存、发送信号给其他进程等。

二、自主学习

(一)苏格拉底挑战




(二)实战演练



posted @ 2023-11-12 14:40  梁小轩  阅读(59)  评论(0)    收藏  举报