一. 信号产生的场景
1. 用户输入命令, 在shell 启动一个前台进程
2. 当用户按一下 Ctrl + C 的时候,从键盘产生一个硬件中断
3. 此时CPU 正在执行这个进程的带代码, 则该进程的执行代码暂停执行, CPU 从用户态切换到内核态处理该硬件中断.
4. 中断驱动程序将Ctrl + C 解释为一个 SIGIN 信号, 记在该进程的 PCB 中(操作系统给进程法送了一个 SUGIN 信号)
5. 当操作系统要从内核返回到该进程的代码继续执行之前, 首先要处理PCB中记录的信号, 发现了一个 SUGIN 信号, 而该信号的默认处理动作是终止进程, 所以此时进程直接终止, 不再返回.
注意:
1. Ctr + C 只能发给一个前台正在运行的进程, 一个命令后加 & 便可以将该进程放在后台取执行, 这样shell就不用等待进程结束便可以启动新的进程
2. shell 可以一次执行一个前台进程, 但可以一次执行多个后台进程, 只有前台信号才能接受控制键产生的信号
3. 进程在运行的如何时候都可以接到像 Ctr + C 的这种键盘控制信号而终止, 因此信号相对于进程而言是异步的.
查看信号的命令: kill -l
其中前 31 个信号属于普通信号, 没有 32 和 33 号信号, Ctrl + C 产生 11 号 SIGSEGV 信号, Ctrl + Z 产生 SIGTSTP 20 号信号, Ctrl + / 产生 SIGQUIT 3 号信号.
二. 信号产生的几种方式
1. 用户在终端键盘产生中断,终端驱动程序会发送信号给当前前台进程,.
2. 硬件异常产生中断,如执行除以 0 的操作, 此时 CPU 运算单元产生异常, 内核将这个异常解释为一个 SUGFPE 发送给该前台进程, 或者当程序访问了非法内存时, 此时MMU产生一个异常, 内核将这个异常解释为 SIGSEGV 发送给该进程.
3. 通过命令给当前进程发送信号 kill -11 test(给test进程发送 11 号信号)
4. 软件条件产生异常, 如管道读写时, 读端关闭, 此时写端还在继续写, 此时,操作系统会给当前进程发送一个 13 号信号, 进程发现这个信号, 退出.
三. 调用系统函数给信号发送信号
1.kill -信号编号 进程编号
2.kill -信号名 进程编号
该进程是一个死循环的程序, 但此时给该进程发送一个11号信号, 这个信号在进程眼里就是一个SIGEGV 信号, 进程收到这个信号的默认执行动作是终止信号, 并且给用户发送段错误提示信息.
3. kill 命令的函数实现
其中 pid 指的是该进程的 pid, sig 指的是需要发送的信号的编号.
kill 函数用来给对应进程发送一个编号为 sig 的信号
raise 函数用来给当前进程发送一个编号为 signo 的信号
abort 函数是是当前信号接收到信号而异常终止
四. 软件条件产生信号
用来设定一个闹钟, 告诉内核在 seconds 秒之后给进程发送一个SIGALRM 信号, 该信号的默认执行动作时终止当前进程. 函数的返回值是 0 或者是以前设定的闹钟时间还余下的秒数.如果将 seconds 设为 0, 表示取消以前设定的闹钟,闹钟的返回值任然是以前设定的闹钟剩余的秒数.