学习笔记9(信号和信号处理)
一、知识点梳理
(一)Linux信号示例
在Linux系统中,信号是用来通知进程发生了某个事件的一种机制。以下是一些常见的Linux信号及其示例:
-
SIGINT (2) - 中断信号
- 示例:通过在终端按下Ctrl+C,可以发送SIGINT信号给前台进程,通常用于中断运行中的程序。
-
SIGTERM (15) - 终止信号
- 示例:使用
kill命令发送SIGTERM信号,如kill -15 PID,用于请求进程正常终止。
- 示例:使用
-
SIGKILL (9) - 强制终止信号
- 示例:使用
kill命令发送SIGKILL信号,如kill -9 PID,强制终止进程。
- 示例:使用
-
SIGCHLD (17) - 子进程状态改变信号
- 示例:父进程可以通过捕捉SIGCHLD信号来处理子进程的退出状态。
-
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)其他进程: 一个进程可以通过系统调用如 kill 或 killpg 向另一个进程发送信号。这种机制可以用于进程间的通信和控制。例如,通过kill命令可以向指定进程发送不同的信号。
(4)硬件异常: 一些信号可以由硬件异常触发,例如:
- SIGSEGV(段错误信号):当程序访问无效的内存地址时触发。
- SIGFPE(浮点异常信号):当浮点运算错误发生时触发。
- 其他硬件错误引起的信号。
3.信号处理函数
在Linux中,signal 函数和 sigaction 函数都是用于处理信号的函数,但它们在实现上有一些不同。
(1)signal 函数:
signal 函数是比较早期的信号处理函数,它的原型如下:
#include <signal.h>
void (*signal(int signum, void (*handler)(int)))(int);
- signum: 表示要处理的信号的编号,例如
SIGINT、SIGTERM等。 - 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); // 用于实现一些特殊行为的恢复函数
};
(三)信号处理步骤
-
注册信号处理函数: 进程需要注册一个信号处理函数,以便在接收到信号时执行相应的处理逻辑。可以使用
signal函数或sigaction函数来注册信号处理函数。 -
发送信号: 信号可以由多种来源产生,例如用户输入、操作系统事件、其他进程或硬件异常。当信号产生时,操作系统会将信号发送给接收进程。
-
中断当前操作: 当进程接收到信号时,它会中断当前的操作,并跳转到信号处理函数执行相应的处理逻辑。
-
执行信号处理函数: 进程会执行注册的信号处理函数,以处理接收到的信号。在信号处理函数中,可以执行相应的处理逻辑,例如关闭文件、释放资源等。
-
恢复操作: 当信号处理函数执行完毕后,进程会恢复之前的操作,并继续执行。如果信号处理函数终止了进程,那么进程将会退出。
(四)信号用作IPC
在Linux中,信号也可以用作进程间通信(IPC)的一种方式。虽然信号不是专门为IPC设计的,但它可以用于在进程之间传递简单的信息和通知。使用信号进行IPC通常包括以下步骤:
-
发送信号: 发送进程使用
kill函数向接收进程发送信号。可以使用SIGUSR1和SIGUSR2信号来进行自定义通信。 -
注册信号处理函数: 接收进程需要注册一个信号处理函数,以便在接收到信号时执行相应的处理逻辑。可以使用
signal函数或sigaction函数来注册信号处理函数。 -
处理信号: 当接收进程接收到信号时,它会中断当前的操作,并跳转到信号处理函数执行相应的处理逻辑。在信号处理函数中,可以执行相应的处理逻辑,例如更新共享内存、发送信号给其他进程等。
二、自主学习
(一)苏格拉底挑战




(二)实战演练



浙公网安备 33010602011771号