Linux进程信号

  • 目录

    概念

    信号种类

    信号生命周期

    信号的处理

    信号的清除


    概念

    • 进程信号是一种异步通信机制,用于进程间传递事件通知。它可以强制进程中断当前操作,转而执行预设的信号处理动作,是系统管理和进程控制的重要手段

    • 本质:信号是一个整数编号代表不同类型事件

  • 信号种类

    • 可靠信号
      • 保证传递(支持队列)
      • 可携带参数(通过siginfo_t结构体)
      • 需要显示设置sa_flags=SA_SIGINFO
    • 不可靠信号
      • 可能丢失(如短时间内多次发送同一信号)
      • 不支持参数传递
      • 处理时会自动阻塞自身(复制递归触发)
    • 使用kill -l命令可以进行查看
  • 信号生命周期

    • 信号的产生
      • 硬件异常触发:除0错误,非法内存访问
      • 终端输入触发
      • 系统调用
      • 软件条件
      • 内核机制触发
      • 外部命令触发
    • 信号的传递:信号从产生到被进程感知需经过内核态传递过程
      • 内核信号队列维护
        • 非实时信号
          • 不支持排队,同一信号多次发生时仅保存最后一次
          • 存储于进程描述法task_struct的pending位图中
        • 实时信号
          • 支持FIFO排队,按照发送顺序处理
          • 存储于rt_sig_pending链表,每个信号包含参数信息
      • 信号阻塞检查
        • 进程通过sigprocmask()设置阻塞掩码(blocked位图)
        • 被阻塞的信号暂存于pending队列,不立即处理
        • 例外情况
          • SIGKILL(9)和SIGSTOP(19)无法阻塞
          • 实时信号阻塞时会记录排队次数
      • 进程调度上下文切换
        • 信号检测时机:
          • 进程从内核返回用户态时
          • 进程被唤醒准备投入运行时
          • 调用sigwait()等主动等待信号的系统调用
        • 内核检测函数:do_signal()负责pending信号
    • 信号的处理

      • 概念:进程在接收到信号后,根据预设策略执行对应操作
      • 处理策略判断
        • 默认处理(SIG_DFL):由内核定义的行为
        • 忽略处理(SIG_IGN):进程不响应信号
        • 自定义处理( typedef void(*sighanler)(int signo) ):通过信号处理函数响应
      • 处理函数调用机制
        • 非实时信号处理
          • 调用处理函数前自动阻塞当前信号(防止递归)
          • 处理完成后信号恢复掩码
        • 实时信号处理
          • 支持sa_sigaction带参数处理函数
          • 通过siginfo_t结构体传递发生者PID、信号值等信息
      • 处理函数的安全限制
        • 异步信号安全函数
          • 仅调用_POSIX_SIGsafe_FUNCS列表中的函数(如write(),_exit())
          • 避免调用可能导致死锁的函数(如malloc()、printf())
    • 信号的清除

      • 概念:信号处理完成后,内核会执行清除操作,不同类型信号清除机制不同
      • 非实时信号的清除
        • 清除时机:处理函数返回后自动清除pending队列中的该信号
        • 若信号被阻塞,则处理后仍保留在pending队列,直到解除阻塞
      • 实时信号的清除
        • 队列式清除
          • 每次处理一个实时信号后,从队列中移除该实例
          • 若有多个相同实时信号排队,按顺序逐个处理
      • 特殊信号的清除规则
        • SIGKILL/SIGSTOP
          • 处理后立即清除,不进入pending队列
          • 无法通过编程方式修改其处理行为
    • 信号生命周期中的关键数据结构
      struct task_struct {
          sigset_t blocked;       // 阻塞信号掩码
          sigset_t pending;       // 待处理信号
          struct sigaction *sig;  // 信号处理函数数组(大小为64)
          struct sigpending pending_rt; // 实时信号队列
      };
      struct sigaction {
          union {
              void (*sa_handler)(int);         // 处理函数(简易版)
              void (*sa_sigaction)(int, siginfo_t *, void *); // 带参数处理函数
          };
          sigset_t sa_mask;        // 处理时阻塞的信号
          int sa_flags;            // 标志位(如SA_RESTART)
      };
      struct siginfo {
          int si_signo;       // 信号编号
          int si_code;        // 信号来源代码
          pid_t si_pid;       // 发送进程PID
          uid_t si_uid;       // 发送进程UID
          union { ... };      // 信号值(int或指针)
      };

你可能感兴趣的:(C++,linux,运维,服务器,c++)