栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Linux C++ 通信 - 信号的概念、认识、处理动作

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Linux C++ 通信 - 信号的概念、认识、处理动作

信号的概念、认识、处理动作

明镜止水,长话短说。


目录
  • 信号的概念、认识、处理动作
    • 信号的基本概念
    • 通过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	
/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参数对应的信号

kill的参数该参数发出的信号以及操作系统动作
-1SIGHUP(连接断开),终止进程(进程没了)
-2SIGINT(终端中断符,如Ctrl+C),终止进程(进程没了)
-3SIGQUIT(中断退出符, 如Ctrl+),终止进程(进程没了)
-9SIGKILL(终止),终止进程(进程没了)
-18SIGCONT(使暂停的进程继续),忽略(进程继续运行不受影响)
-19SIGSTOP(停止),可使用SIGCONT继续,任务放到后台,停止进程(不是终止,进程还在)
-20SIGTSTP(终端停止符,同Ctrl+Z),任务于后台,可使用SIGCONT继续,停止进程(不是终止,进程还在)
进程状态

查看进程状态(STAT选项)

ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E '程序检索字段'
   PID    PPID     SID TT          PGRP COMMAND         STAT
      1       0       1 ?              1 systemd         Ss
      2       0       0 ?              0 kthreadd        S
      3       2       0 ?              0 rcu_gp          I<
      4       2       0 ?              0 rcu_par_gp      I<
      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,是这些进程的一个状态,进程状态字母对应的状态含义:

状态含义
D不可中断的休眠状态(通常是I/O枫如进程),可以处理信号,有延迟
R可执行状态&运行状态(再运行队列里的状态)
S可中断的休眠状态之中(等待某事件完成),可以处理信号
T停止或被追踪(被作业控制信号所停止)
Z僵尸进程
X死掉的进程
<高优先级的进程
N低优先级的进程
L有些页被锁进内存
ssession leader(会话首进程),其下有子进程
t追踪期间被调试器停止
i空闲的任务(进程)
+位于前台的进程组
信号测试:

一样,ssh连接ubuntu,打开两个终端,一个终端负责程序的执行于=和结果,另一个负责进程的状态和kill命令的执行。

第一个终端:
C++简单代码编写:

#include
#include
#include
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
./t141
Linux C++
子进程
子进程
子进程
子进程

第二个终端:

#此时程序状态为置于前台的可中断休眠状态
root@ubuntu:/home/qiye# ps -eo pid,ppid,sid,tty,pgrp,comm,stat | grep -E 't141'
  10095    6202    5942 pts/1      10095 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/1      10095 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/1      10095 t141            S

程序继续运行:

但是Ctrl+C无法终止它:

在第二个终端中使用kill -9 终止程序:

root@ubuntu:/home/qiye# kill -9 10095
root@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信号这俩依旧列外。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1029588.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号