20211301 学习笔记9
学习笔记9
教材知识点总结
6.1 信号和中断
- “中断”是从1/0设备或协处理器发送到CPU的外部请求,它将CPU从正常执行转移 到中断处理。与发送给CPU的中断请求一样,“信号”是发送给进程的请求,将进程从正常执行转移到中断处理
- 人员中断
- 进程中断
- 硬件中断
- 进程的陷阱错误:CPU识别为异常
6.2 Unix/Linux信号示例
- “ctrl+c”可以终止进程:键盘硬件中断
- 后台运行程序,退出后,进程仍在进行,发送sighup信号,后台进程收到这一信号,忽略它继续运行
- 使用sh命令杀死该进程
6.3 Unix/Linux中的信号处理
-
信号类型
Unix/Linux支持31种不同的信号,每种信号在signal.h文件中都有定义。
-
信号的来源:
- 来自硬件中断的信号
- 来自异常的信号
- 来自其他进程的信号
-
信号处理函数:每个进程都有一个PROC信号处理数组
-
安装信号捕捉函数:进程可使用系统调用:
int r = signal(int signal_numberr void *handler);
-
进程可使用信号调用
int r = kill(pid, signal_number);
-
向pid标识的另一个进程发送信号。Sh命令
kill -s signal_number pid
-
使用kill系统调用
-
信号处理步骤:
- (1)当某进程处于内核模式时,会检査信号并处理未完成的信号,如果某信号有用户安装的捕捉函数,该进程会先清除信号,获取捕捉函数地址,对于大多数陷阱信号,则将已安装的捕捉函数重置为DEFault,然后,它会在用户模式下返回,以执行捕捉函数,以这种方式篡改返回路径当捕捉函数结束时。它会返间到最初的中断点,即它最后进入内核模式的地方因此,该进程会先迂回执行捕捉函数,然后再恢复正常执行。
- (2)重置用户安装的信号捕捉函数:用户安装的陷阱相关信号捕捉函数用于处理用户代 码中的陷阱错误。由于捕捉函数也在用户模式下执行,因此可能会再次出现同样的错误如 果是这样,该进程最终会陷入无限循环,一直在用户模式和内核模式之间跳跃:为了防止这种情况,Unix内核通常会在允许进程执行捕捉函数之前先将处理函数重置为DEFault这意 味着用户安装的捕捉函数只对首次出现的信号有效若要捕捉再次出现的同-信号,则必须 重新安装捕捉函数°但是,用户安装的信号捕捉函数的处理方法并不都一样,在不同Unix 版本中会有所不同.例如,在BSD Unix中,信号处理函数不会被重置.但是该信号在执行信号捕捉函数时会被阻塞,感兴趣的读者可参考关于Linux信号和sigaction函数的手册页,以了解更多详细信息。
- (3)信号和唤醒:在Unix/Linux内核中有两种SLEEP进程;深度休眠进程和浅度休 眠进程。前一种进程不可中断,而后一种进程可由信号中断。如果某进程处于不可中断的 SLEEP状态,到达的信号(必须来自硬件中断或其他进程)不会唤醒进程一如果它处于可中 断的SLEEP状态,到达的信号将会唤醒它:例如,当某进程等待终端输入时,它会以低优 先级休眠.这种休眠是可中断的.S1G1NT这类信号即可唤醒它。
6.5 信号与异常
- Unix信号最初设计用于:作为进程异常的统一处理方法;让进程通过预先安装的信号捕捉函数处理用户模式下的程序错误;在特殊情况下,它会让某个进程通过信号杀死另一个进程
6.6 信号用作IPC
-
不可靠
-
竞态条件
-
预定义的含义
-
避免出现这种情况
6.7Linux中的IPC
- IPC是指用于进程间通信的机制。在Linux中,IPC包含以下组成部分。
- 管道和FIFO
- 信号
- System V IPC
- POSIX消息队列
- 线程同步机制
- 套接字
代码实现
- 排序实现
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 快速排序算法
void quickSort(int arr[], int low, int high) {
if (low < high) {
int pivot = arr[high];
int i = low - 1;
for (int j = low; j < high; j++) {
if (arr[j] < pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
int pi = i + 1;
quickSort(arr, low, pi - 1);
quickSort(arr, pi + 1, high);
}
}
int main() {
int arr[11];
srand(time(0));
for (int i = 0; i < 10; i++) {
arr[i] = rand() % 1000 + 1;
}
arr[10] = 301;
quickSort(arr, 0, 10);
int found = 0;
for (int i = 0; i < 11; i++) {
if (arr[i] == 301) {
found = 1;
printf("%d",arr[i]);
break;
}
}
if (found) {
printf("数组中包含301\n");
} else {
printf("数组中不包含301\n");
}
return 0;
}
问题与解决方案
- 问题一:进程怎么进行系统调用
- 问题一解决方案:
苏格拉底挑战
-
信号
-
IPC