一、知识点归纳
1. 信号和中断
1.1 进程概念
进程是计算机中的基本执行单位,可以看作是一系列活动的集合。这些活动包括从事日常事务的人、在用户模式或内核模式下运行的Unix/Linux进程,以及执行机器指令的CPU。
1.2 中断
中断是一种事件,用于通知进程需要进行某种处理,将进程从正常活动转移到其他活动,这个过程称为“中断处理”。中断可以使进程在完成中断处理后恢复正常活动。
1.3 中断的来源
- 来自硬件的中断:例如,大楼火警、闹钟响了等。
- 来自其他人的中断:例如,电话响了、有人敲门等。
- 自己造成的中断:例如,割到手指、吃得太多等。
1.4 中断的分类
- 不可屏蔽中断(NMI):这些是紧急事件,例如大楼火警,需要立即处理。
- 可屏蔽中断:这些中断可以根据紧急程度进行处理,例如有人敲门,可以稍后回应。
1.5 进程中断
进程中断是发送给进程的中断。一个进程在执行时可能会收到来自三个不同来源的中断:
- 来自硬件的中断:例如终端输入、间隔定时器的“Ctrl+C”组合键等。
- 来自其他进程的中断:通过系统调用(如kill(pid, SIG#))向目标进程发送信号。
- 自己造成的中断:由被CPU识别为异常的错误引起,如除以0、无效地址、非法指令等。
1.6 进程的陷阱错误
进程也可能自己造成中断。这些中断由被CPU识别为异常的错误引起,例如除以0、无效地址、非法指令等。当进程遇到异常时,它会陷入操作系统内核,将陷阱原因转换为信号编号,并将信号发送给自己。在用户模式下发生异常时,进程的默认操作是终止,并使用可选的内存转储进行调试。不过,进程也可以用信号捕捉器代替默认动作函数,允许它在用户模式下处理信号。如果在内核模式下发生陷阱,原因可能是硬件错误或内核代码中的漏洞,在这种情况下,内核无法处理,通常只会打印一条PANIC错误消息然后停止。
2. Unix/Linux信号示例
2.1 Ctrl+C
按下"Ctrl+C"通常会导致当前运行的进程终止。这是因为"Ctrl+C"会生成一个键盘硬件中断,被转换为SIGINT(2)信号,发送给终端上的所有进程,并唤醒等待键盘输入的进程。在内核模式下,每个进程都要检查和处理未完成的信号。进程对大多数信号的默认操作是调用内核的kexit(exitValue)函数来终止。在Linux中,exitValue的低位字节是导致进程终止的信号编号。
2.2 nohup命令
使用nohup命令可以在后台运行一个程序,即使用户退出后,进程仍会继续运行。nohup命令会使Shell复制子进程来执行程序,子进程会忽略SIGHUP(1)信号。当用户退出时,Shell会向与终端有关的所有进程发送一个SIGHUP信号,但后台进程会忽略它,继续运行。为防止后台进程使用终端进行I/O,通常会将其文件描述符0、1、2重定向到/dev/null,使其完全不受任何面向终端信号的影响。
2.3 杀死进程
用户可以使用kill命令或信号编号(如SIGTERM或SIGKILL)来终止进程。进程可以选择响应这些信号,如果不响应,可以使用SIGKILL信号来强制终止。在最初的Unix中,只有9个信号,其中9号信号被保留为终止进程的终极手段。虽然后来的Unix/Linux系统将信号编号扩展到了31,但是信号编号9的含义仍然保留了下来。
3. Unix/Linux中的信号处理
3.1 信号类型
Unix/Linux支持31种不同的信号,每种信号在signal.h文件中都有定义。
3.2 信号的来源
- 信号可以来自硬件中断、异常或其他进程。硬件中断可以是键盘输入、定时器到期等。异常信号是由进程自身引起的,如除以0、无效地址等。其他进程可以使用系统调用向目标进程发送信号。
3.3 进程的信号处理
每个进程都有一个32位向量来记录发送给它的信号,以及一个MASK位向量来屏蔽相应的信号。每个信号都有一个处理函数,进程可在收到信号后执行该函数。
4. 信号处理步骤
4.1 信号处理过程
当进程处于内核模式时,会检查信号并处理未完成的信号。如果某信号有用户安装的捕捉函数,该进程会先清除信号,获取捕捉函数地址,对于大多数陷阱信号,则将已安装的捕捉函数重置为默认。然后,它会在用户模式下返回,执行捕捉函数,以这种方式篡改返回路径。当捕捉函数结束时,它会返回到最初的中断点,即它最后进入内核模式的地方。
4.2 重置用户安装的信号捕捉函数
用户安装的陷阱相关信号捕捉函数用于处理用户代码中的陷阱错误。由于捕捉函数也在用户模式下执行,因此可能会再次出现同样的错误。如果是这样,该进程最终会陷入无限循环,一直在用户模式和内核模式之间跳跃。为了防止这种情况,Unix内核通常会在允许进程执行捕捉函数之前先将处理函数重置为默认。这意味着用户安装的捕捉函数只对首次出现的信号有效。若要捕捉再次出现的同一信号,则必须重新安装捕捉函数。
5. Linux中的IPC(进程间通信)
IPC是指用于进程间通信的机制,包括多种机制,如管道、FIFO、System V IPC、POSIX消息队列、线程同步机制和套接字。这些机制允许进程之间传输数据、同步操作以及实现进程间的互斥和通信。
二、ChatGpt提问
三、实践及代码托管
(1)段错误捕捉
(2)实现一个消息的IPC
代码已托管至gitee,链接:https://gitee.com/wang-yuxuan333/123.git
具体详见:catch.txx ipc.txt
四、问题及解决
实践二代码编译出现问题,通过询问ChatGpt,对代码进行修复,成功编译运行。