4. IPC信号
信号(Signals)
信号(Signals)是 Linux/UNIX 进程间通信(IPC)的一种方式(共七种方式)。信号由一个用户进程或者操作系统内核产生,通过 Linux 或 UNIX 操作系统内核传递给另外一个进程。信号在经过操作系统时,操作系统可以根据信号的意义做出相应的操作。
信号是一个 1~64 的整数,每一个整数代表不同的含义,这个含义由操作系统和用户定义。
我们可以使用 kill -l 命令列出所有的信号值和对应的类型,如下所示:
weimingze@mzstudio:~$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
其中 1~31 由早期 UNIX 系统定义并延续至 Linux 系统,每个信号的用途已经明确定义,是标准信号。
其中 34 ~ 64 是 Linux 扩展的信号,用于用户自定义用途。
标准信号(1-31)
以下是传统的 UNIX 信号,具有明确的用途,如下表所示:
SIGHUPnginx -s reload)。SIGINTControl+C),由终端发送,请求进程终止。SIGQUITControl+\),类似 SIGINT,但会生成核心转储(core dump)。SIGILLSIGTRAPgdb)用于断点调试。SIGABRTabort() 触发,表示严重错误(如 assert 失败)。SIGBUSSIGFPESIGKILLSIGUSR1nginx 日志重载)。SIGSEGVNULL 指针)。SIGUSR2SIGPIPESIGALRMalarm() 或 setitimer() 触发(如 timeout 命令)。SIGTERMkill),请求进程正常退出(可捕获)。SIGSTKFLTSIGCHLDSIGCONTSIGSTOP/SIGTSTP 停止的进程(如 fg 命令)。SIGSTOPSIGTSTPControl+Z),可捕获(如 vim 临时挂起)。SIGTTINcat & 后尝试输入)。SIGTTOUecho "test" & 后尝试输出)。SIGURGOOB 到达 socket)。SIGXCPUulimit -t 限制)。SIGXFSZulimit -f 限制)。SIGVTALRMsetitimer(ITIMER_VIRTUAL) 触发)。SIGPROFsetitimer(ITIMER_PROF) 触发)。SIGWINCHvim 自适应)。SIGIOSIGPWRSIGSYS常用信号列表
SIGHUPSIGINTSIGQUITSIGKILLSIGSEGVSIGPIPESIGALRMSIGTERMSIGCHLDSIGCONTSIGSTOPSIGTSTP常见终端信号
Control + CSIGINTControl + \SIGQUITControl + ZSIGTSTP测试终端信号
写一个 Python 程序 always_run.py,内容如下:
import os
print("PID:", os.getpid())
while True:
pass
注意: pass 前面要保留 4 个空格其他行前面不要留有空格。
具体 Python 的语法详见我的 《python教程》
此程序先打印当前进程的 PID ,然后进入死循环,一直运行不退出。
运行 always_run.py 程序
weimingze@mzstudio:~$ python3 always_run.py
PID: 8217
此时程序一直执行,一直占用终端,没有退出。因此在终端中不会看见 weimingze@mzstudio:~$ 这样的命令提示符。
再打开另外一个终端查看 启动命令为 python3(使用 -C python3 选项)的进程的详细信息(使用 -l 选项),如下:
weimingze@mzstudio:~$ ps -l -C python3
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 1000 8217 5889 99 80 0 - 7336 - pts/0 00:04:42 python3
可见第二列(S 列)对应的状态是 R 说明程序在运行状态。
此时使用 top 命令查看,你会发现此进程将一个 CPU 占用 99.7% 的资源。 如下:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
8217 weiming+ 20 0 29344 9116 6300 R 99.7 0.2 11:07.93 python3
在第一个终端中输入 Control + C 向程序发送 SIGINT 信号,则 always_run.py 程序停止运行,提示如下:
weimingze@mzstudio:~$ python3 always_run.py
PID: 8217
^CTraceback (most recent call last):
File "/home/weimingze/always_run.py", line 4, in <module>
while True:
^^^^
KeyboardInterrupt
weimingze@mzstudio:~$
此时程序停止,命令提示符 weimingze@mzstudio:~$ 出现,CPU 占有率降低。再用 ps 命令也查不到此进程。
再次运行 always_run.py 程序。
weimingze@mzstudio:~$ python3 always_run.py
PID: 8358
然后在终端中输入 Control + Z 向程序发送 SIGTSTP 信号,则 always_run.py 程序 停止运行,提示如下:
weimingze@mzstudio:~$ python3 always_run.py
PID: 8358
^Z
[1]+ Stopped python3 always_run.py
使用 ps 命令查看进程情况:
weimingze@mzstudio:~$ ps -l -C python3
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 T 1000 8358 5889 92 80 0 - 7336 do_sig pts/0 00:03:10 python3
此时 此进程的状态是 T(停止状态),此时 top 命令发现 CPU 占有率下降。
使用 fg 命令(后面再讲) 回复此进程为运行状态,如下:,
weimingze@mzstudio:~$ fg
python3 always_run.py
使用 ps 命令查看进程情况:
weimingze@mzstudio:~$ ps -l -C python3
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 R 1000 8358 5889 93 80 0 - 7336 - pts/0 00:07:54 python3
状态为 R 运行状态。
然后再终端中输入 Control + \ 向程序发送 SIGQUIT 信号,则 always_run.py 程序 退出运行,提示如下:
weimingze@mzstudio:~$ fg
python3 always_run.py
^\Quit (core dumped)
weimingze@mzstudio:~$ ps -l -C python3
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
练习:
- 编写上述示例中
always_run.py文件。 - 使用
python3 always_run并运行此程序,然后查看CPU占有率。 - 使用
Control + Z让此程序停止并进入后台运行,然后查看CPU占有率。 - 使用
fg命令回复程序的运行,然后查看CPU占有率。 - 使用
Control + \让此程序终止运行,然后查看CPU占有率。