当前位置:首页 > 系统教程 > 正文

Linux进程信号核心拆解(深入理解pending/block/handler三张表与signal/alarm实战)

Linux进程信号核心拆解(深入理解pending/block/handler三张表与signal/alarm实战)

本文关键词:Linux进程信号、信号屏蔽字、信号处理函数、信号生命周期

一、什么是Linux进程信号?

在Linux操作系统中,Linux进程信号是一种异步通知机制。通俗地讲,它就像手机上的“应用消息通知”。当某个事件发生时(如按下Ctrl+C),系统会向进程发送一个信号,告诉进程该起床干活了或者准备自杀。

信号的整个生命周期可以概括为:信号产生 -> 信号在进程中注册/阻塞 -> 信号被处理。这就是完整的信号生命周期

二、核心:内核中的三张表(pending/block/handler)

每一个Linux进程在内核中都有三张关键的表来管理信号。理解了这三张表,你就掌握了信号的灵魂:

  • 1. Block表(信号屏蔽字): 这是一个位图。如果某一位被置为1,表示该信号被“屏蔽”了。注意,屏蔽不是丢弃,而是暂时“拦截”,直到解除屏蔽。
  • 2. Pending表(未决信号集): 这也是一个位图。当信号送达但还没被处理时,对应位置会被置为1。它记录了“有哪些信号正等着我去处理”。
  • 3. Handler表(信号处理表): 这是一个函数指针数组。它记录了当信号到来时,进程应该执行哪个信号处理函数。是忽略它?执行系统默认动作?还是执行我们自己写的函数?
Linux进程信号核心拆解(深入理解pending/block/handler三张表与signal/alarm实战) Linux进程信号  信号屏蔽字 信号处理函数 信号生命周期 第1张

三、实战:signal与alarm的使用

接下来我们通过代码来看看如何自定义信号的处理逻辑。

1. signal() 函数:修改Handler表

我们可以使用 signal() 函数来告诉进程:当收到某个信号时,不要按默认套路出牌,去执行我的函数。

#include <stdio.h>#include <signal.h>#include <unistd.h>void my_handler(int sig) {    printf("捕获到信号: %d,嘿,你杀不死我!\n", sig);}int main() {    // 将SIGINT(Ctrl+C)的处理函数改为my_handler    signal(SIGINT, my_handler);    while(1) {        printf("进程运行中...PID: %d\n", getpid());        sleep(1);    }    return 0;}

2. alarm() 函数:定时闹钟

alarm() 允许你在指定的秒数后向当前进程发送一个 SIGALRM 信号。

#include <stdio.h>#include <unistd.h>#include <signal.h>void timeout(int sig) {    printf("闹钟响了!时间到!\n");}int main() {    signal(SIGALRM, timeout);    alarm(3); // 3秒后发送信号    printf("等待闹钟中...\n");    pause();   // 挂起进程直到收到信号    return 0;}

四、总结

理解Linux信号的关键在于那“三张表”:信号屏蔽字决定能不能进,Pending记录谁进来了,信号处理函数决定进来后干什么。掌握了这套机制,你就能在多进程编程中游刃有余地处理各种突发状况。

© Linux进程信号核心教程 - 深入浅出系列