信号和信号处理

信号和中断的统一处理

“中断”是从I/O设备或协处理器发送CPU的外部请求,它将CPU从正常执行转移到中断处理
(1)一个“进程”就是一些列活动
(2)“中断” 是发送给“进程”的事件
(3)中断:
1. 人员中断
2. 进程中断
3. 硬件中断
(4)进程的陷阱错误:进程可能会自己造成中断

UNIX/LINUX信号示例

"Ctrl+C"组合键生成一个键盘硬件中断,导致当前运行的进程终止。
使用nohup a.out 命令在后台运行一个程序,用户退出后会继续运行
用户使用 kill pid (or kill -s 9 pid)杀死该进程

信号的来源

  1. 硬件信号
  2. 异常信号
  3. 其他进程信号

信号在Unix/Linux中的常见用法

Unix/Linux中的信号处理

  1. 信号类型
    UNIX/Linux支持31种不同的信号,都在signal.h文件中有定义

    硬件中断的信号
    来自异常的信号
    来自其他进程的信号
  2. 信号向量
  3. 信号掩码位
    进程PROC结构体
    向量:每个进程PROC都有一个32位向量,用来记录发送给进程的信号
    信号处理函数:每个进程PROC都有一个信号处理数组int sig[]。sig[32]数组的每个条目都指定了如何处理相信的信号。0代表默认,1代表忽略。

    安装信号捕捉器来处理程序异常
    使用系统调用
    int r = signal(int signal1_number, void *handler);
  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);
};

sigaction()的使用实例

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
void handler(int sig, siginfo_t *siginfo, void *context)
{
printf("handler: sig=%d from PID=%d UID=%d\n",
sig, siginfo->si_pid, siginfo->si_uid);
}
int main(int argc, char *argv[])
{
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_sigaction = &handler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGTERM, &act, NULL);
printf("proc PID=%d looping\n”);
printf(“enter kill PIDto send SIGTERM signal to it\n", getpid());
while(1)
sleep(10);
}
}


程序报错:

  1. 在printf语句中使用了中文引号,应该使用英文引号。
  2. 缺少头文件#include <string.h>以定义memset函数。
    修改后正常运行

信号处理步骤

  1. 内核模式,检查信号并处理未完成的信号
  2. 重置用户安装的信号捕捉函数:
  3. 信号和唤醒

信号与异常

当进程遇到异常时,它会陷入内核模式,将陷阱原因转换为信号编号,并将信号发送给自己。如果在内核模式下遇到异常,内核只打印一条PANIC错误消息,然后就停止。

信号用作进程间通信(IPC)机制的适用性

实现一个消息IPC



苏格拉底挑战: