深入探讨 Linux Signal 信号机制 (linux signall)
Linux Signal 信号机制是 Linux 操作系统的一项特性,用于进程间通信和异常处理。信号是当一个进程发生异常行为时发送给另一个进程的消息。在 Linux 中,信号被用于许多不同的目的,例如,当一个进程停止时,当一个进程遇到了一个致命错误时,当一个进程收到一个用户定义的中断时等等。本文将,包括信号的基本定义、信号的种类、信号的发送、处理和阻塞。
一、信号的基本定义
在 Linux 中,信号是由内核或进程发送给一个或多个进程的异步通知。信号是一种软件中断,可以中断进程的执行,让进程执行一个指定的操作。信号通常用于进程间通信和异常处理。Linux 定义了许多不同的信号,每个信号都有一个唯一的编号和名称。在应用程序中,可以通过信号处理程序来捕获和处理这些信号。
二、信号的种类
Linux 定义了 64 种不同的信号,每个信号都有一个唯一的编号和名称。以下是最常见的信号:
– SIGHUP:挂起进程
– SIGINT:中断进程
– SIGQUIT:收到终止进程信号
– SIGILL:指令不合法
– SIGTRAP:致命错误
– SIGABRT:请求紧急终止
– SIGBUS:总线错误
– SIGFPE:浮点异常
– SIGKILL:强制终止进程
– SIGUSR1 和 SIGUSR2:用户定义信号
– SIGSEGV:段错误
– SIGPIPE:管道破裂,取消进程之间的通信
– SIGALRM:实时时钟的定时器到期,向进程发送 SIGALRM
– SIGTERM:请求进程自行终止
– SIGCHLD:子进程状态发生改变
除了上述信号外,还有一些其他的信号。可以通过命令 “kill -l” 查看所有信号的列表。
三、信号的发送
Linux 中,信号可以由内核或进程发送给另一个进程。发送信号的方法有以下两种:
1. kill 命令:可以用来向指定的进程或进程组发送信号。语法如下:
“`bash
kill [-s ] pid
“`
-s 表示要发送的信号编号,pid 表示接收信号的进程 ID。如果省略 -s 参数,则默认为发送 SIGTERM 信号。可以使用命令 “kill -l” 查看所有信号编号。
2. 通过系统调用函数发送信号:在应用程序中,可以通过系统调用函数向另一个进程发送信号。Linux 中,常用的发送信号的系统调用函数有以下三个:
– kill(pid, sig):向进程 ID 为 pid 的进程发送信号 sig。
– rse(sig):向当前进程发送信号 sig。
– sigqueue(pid, sig, value):向进程 ID 为 pid 的进程发送一个带有初始值 value 的 sig 信号。
四、信号的处理
当进程接收到一个信号时,可以通过信号处理程序捕获和处理这个信号。Linux 中,通过 signal() 函数来绑定信号处理程序。该函数原型如下:
“`c
void (*signal(int signum, void (*handler)(int)))(int);
“`
其中,signum 表示要处理的信号编号,handler 表示要执行的信号处理程序。该函数返回一个函数指针,指向之前绑定的信号处理程序。信号处理程序一般有以下几种类型:
– 忽略信号:该信号将被忽略,不做任何处理。
– 执行默认操作:对于大多数信号,Linux 定义了默认操作。例如,收到 SIGTERM 信号时,进程将被终止。
– 执行用户定义的操作:可以自行编写信号处理程序,执行自定义操作。
在应用程序中,可以使用 sigaction() 函数来绑定信号处理程序,该函数比 signal() 函数更加灵活和可靠。该函数原型如下:
“`c
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
“`
其中,signum 表示要处理的信号编号,act 表示需要绑定的信号处理程序的地址,oldact 可选,表示之前的信号处理程序的地址。该函数返回 0 表示成功,-1 表示失败。
五、信号的阻塞
在某些情况下,我们可能希望暂时忽略某些信号,不让其中断当前进程的执行。这时,可以通过信号阻塞来达到这个目的。Linux 中,线程可以通过 sigprocmask() 函数来设置信号的阻塞和解除阻塞。该函数原型如下:
“`c
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
“`
其中,how 表示阻塞和解除阻塞的方式,set 表示需要阻塞的信号,oldset 可选,表示之前被阻塞的信号。有以下几种阻塞方式:
– SIG_BLOCK:将指定信号加入阻塞信号。
– SIG_UNBLOCK:将指定信号从阻塞信号中删除。
– SIG_SETMASK:将当前阻塞信号替换为指定信号。
可以使用 sigpending() 函数来获取等待阻塞的信号。该函数原型如下:
“`c
int sigpending(sigset_t *set);
“`
其中,set 表示需要获取的信号。该函数返回 0 表示成功,-1 表示失败。
六、