信号的概念、认识、处理动作
明镜止水,长话短说。
目录
信号的概念、认识、处理动作信号的基本概念通过kill命令认识一些信号进程状态信号测试: 信号处理的相关动作执行系统默认动作忽略某个信号捕捉某个信号信号的基本概念
信号,在服务器编程和大型应用程序中即为常见。信号就是一个通知(事件通知),用来通知某个进程发生了某一件事。很多时候,信号都是突然产生的,比如,一个程序某个地方出现异常,它给自己发送一个中断自己进程的信号,此时程序可能迎来结束,从而防止更大异常(来自游戏闪退的怨念),换一句话,信号是异步发生的,又称“软件中断”。
信号的产生:
(1)某个进程发送给另一个进程或者发送给自己
(2)由内核发送给某个进程
通过在键盘上输入一些命令动作,Ctrl+C组合键(终端信号),使用kill命令等。内存访问异常。除数为0等,硬件会检测并通知内核等。
信号名字一般都为SIG开头的字母组成,但基于头文件源代码来看,却是数字。
//查看各signal.h 中文件SIGHUP信号的位置root@ubuntu:/home/qiye/Desktop# sudo find / -name "signal.h" | xargs grep -in "SIGHUP"/usr/src/linux-headers-5.11.0-49/arch/mips/include/uapi/asm/signal.h:25:#define SIGHUP 1/* Hangup (POSIX). *//usr/src/linux-headers-5.11.0-49/arch/xtensa/include/uapi/asm/signal.h:35:#define SIGHUP 1/usr/src/linux-headers-5.11.0-49/arch/s390/include/uapi/asm/signal.h:26:#define SIGHUP 1/usr/src/linux-headers-5.11.0-49/arch/ia64/include/uapi/asm/signal.h:13:#define SIGHUP 1/usr/src/linux-headers-5.11.0-49/arch/x86/include/uapi/asm/signal.h:23:#define SIGHUP 1/usr/src/linux-headers-5.11.0-49/arch/sparc/include/uapi/asm/signal.h:12:#define SIGHUP 1/usr/src/linux-headers-5.11.0-49/arch/arm/include/uapi/asm/signal.h:18:#define SIGHUP 1/usr/src/linux-headers-5.11.0-49/arch/parisc/include/uapi/asm/signal.h:5:#define SIGHUP 1/usr/src/linux-headers-5.11.0-49/arch/m68k/include/uapi/asm/signal.h:18:#define SIGHUP 1.....
打开任意一个signal.h文件:
vim /usr/src/linux-headers-5.11.0-49/arch/x86/include/uapi/asm/signal.h
为了方便使用信号,通过使用define预处理器建立数字的别名。
通过kill命令认识一些信号
kill命令常用来杀死了一个进程,我印象最深、用得最多的一句就是sudo kill -9 进程号
,但现在,入这大坑后,kill就不再是单纯用来杀死进程这么简单,而是通过使用kill命令给一个进程发送信号来控制进程的中断、再续、终止来影响程序状态的一个命令。
常用的kill参数对应的信号
进程状态
查看进程状态(STAT选项)
ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E '程序检索字段'PID PPIDSID TTPGRP COMMAND STAT1 0 1 ? 1 systemd Ss2 0 0 ? 0 kthreadd S3 2 0 ? 0 rcu_gpI<4 2 0 ? 0 rcu_par_gpI<6 2 0 ? 0 kworker/0:0H-ev I<9 2 0 ? 0 mm_percpu_wq I<10 2 0 ? 0 rcu_tasks_rude_ S
其中STAT,是这些进程的一个状态,进程状态字母对应的状态含义:
信号测试:
一样,ssh连接ubuntu,打开两个终端,一个终端负责程序的执行和结果,另一个负责进程的状态和kill命令的执行。
第一个终端:
C++简单代码编写:
#include<iostream>#include<unistd.h>#include<signal.h>using namespace std;int main() {pid_t pid;cout << "Linux C++" << endl;while (1){sleep(1);cout << "子进程" << endl;}cout << "end!" << endl;return 0;}
C++文件编译和执行:
g++ -o t141 /mnt/hgfs/c/t141.cpp./t141Linux C++子进程子进程子进程子进程
第二个终端:
#此时程序状态为置于前台的可中断休眠状态root@ubuntu:/home/qiye# ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E 't141'10095 6202 5942 pts/110095 t141 S+#发送SIGSTOP(停止)信号root@ubuntu:/home/qiye# kill -19 10095/#此时程序为停止或被追踪的状态root@ubuntu:/home/qiye# ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E 't141'10095 6202 5942 pts/110095 t141 T
第一个终端出现stopped的提示:
继续使用第二个终端:
#发送SIGCONT(使暂停的进程继续)信号,恢复程序运行root@ubuntu:/home/qiye# kill -18 10095#可以发现恢复回S的状态,但是+号没了,说明已经不是前台运行了,#你会发现再第一个终端里使用Ctrl+C无法终止程序运行root@ubuntu:/home/qiye# ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E 't141'10095 6202 5942 pts/110095 t141 S
程序继续运行:
但是Ctrl+C无法终止它:
在第二个终端中使用kill -9 终止程序:
root@ubuntu:/home/qiye# kill -9 10095root@ubuntu:/home/qiye# ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E 't141'root@ubuntu:/home/qiye#
信号处理的相关动作
执行系统默认动作
当进程收到一个信号时,操作系统(内核)就会对该进程执行一个默认动作,
相应的信号会有相应的默认动作,但大多数时候操作系统的默认动作是终止。
忽略某个信号
当不希望一个进程收到某个信号时,就要使操作系统不对这个信号做出默认动作,常用的是signal(信号名, SIG_IGN)函数,作用是忽略某个信号,操作系统就会忽略这个信号名,但两个信号列外,SIGKILL信号和SIGSTOP信号,这俩不能被忽略,你也不希望一个程序无法被任何手段终止吧?
捕捉某个信号
signal(信号名, 自定义函数),专门捕捉某个信号名,并且成功捕捉后可以送进自定义函数里实现自定义功能,SIGKILL信号和SIGSTOP信号这俩依旧列外。
如果觉得《Linux C++ 通信 - 信号的概念 认识 处理动作》对你有帮助,请点赞、收藏,并留下你的观点哦!