信号和信号处理
信号和中断的统一处理
“中断”是从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)杀死该进程
信号的来源
- 硬件信号
- 异常信号
- 其他进程信号
信号在Unix/Linux中的常见用法
Unix/Linux中的信号处理
- 信号类型
UNIX/Linux支持31种不同的信号,都在signal.h文件中有定义
硬件中断的信号
来自异常的信号
来自其他进程的信号 - 信号向量
- 信号掩码位
进程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);
}
}
程序报错:
- 在printf语句中使用了中文引号,应该使用英文引号。
- 缺少头文件#include <string.h>以定义memset函数。
修改后正常运行
信号处理步骤
- 内核模式,检查信号并处理未完成的信号
- 重置用户安装的信号捕捉函数:
- 信号和唤醒
信号与异常
当进程遇到异常时,它会陷入内核模式,将陷阱原因转换为信号编号,并将信号发送给自己。如果在内核模式下遇到异常,内核只打印一条PANIC错误消息,然后就停止。
信号用作进程间通信(IPC)机制的适用性
实现一个消息IPC
苏格拉底挑战: