linux笔记之初次接触信号

2023-11-15

一.关于信号概念


1.信号是Linux所使用的进程间通信的最古老的方式。它是在软件层次上对中断机制的一种模拟,是一种异步通信的方式 。一个完整的信号周期包括三个部分,信号的产生,信号在进程中的注册,信号在进程中的注销,执行信号处理函数。如下图所示:这里写图片描述

这里的对信号产生注册和注销都是信号的内部机制,而不是信号函数完成的

2.对信号的处理动作有三种:

a. 忽略此信号

b.执行该信号的默认处理动作

c.捕捉信号(自由态)

3.查看系统定义中的信号列表: kill -l 命令

这里写图片描述
每个信号都有一个编号和一个宏定义名称,这些宏定义名称可以在signal.h中找到,例如:其中有定义#define SIGINT 2

二.产生信号

1. 通过终端按键产生信号

如下代码:

#include<stdio.h>
#include<signal.h>
void hander(int sig)
{
    printf("%d\n",sig);
}


int main()
{
    signal(2,hander);
    while(1)
    {
        printf("i am a proc\n");
        sleep(1);
    }
}

这里写图片描述
以上代码使用了signal函数用来捕捉信号,则可以说明的是:ctrl+c实现的是信号的2号信号SIGINT。

2.调用系统函数向进程发信号

介绍几个函数

  • kill命令是调用kill函数实现的。kill函数可以给一个指定的进程发送指定的信号。
#include<signal.h>
int kill(pid_t pid,int signo);
  • raise函数可以给当前进程发送指定的信号(自己给自己发信号)
#include<signal.h>
int raise(int signo);

如下两个代码实现raise函数的功能:

#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<stdlib.h>

void hander(int sig)
{
    printf("%d\n",sig);
}

int main()
{
     signal(2,hander);
     sleep(3);
     while(1)
     {
       raise(2);
        printf("i am a proc\n");
        sleep(1);
    }

}

结果如下图:

这里写图片描述

#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<stdlib.h>

void hander(int sig)
{
    printf("%d\n",sig);
}

int main()
{
     signal(2,hander);
     sleep(3);
     raise(2);
     while(1)
     {
        printf("i am a proc\n");
        sleep(1);
    }

}

结果如下图:

这里写图片描述

  • abort函数可以使当前进程接收到信号而异常终止,像exit函数一样,abort函数总会成功,故无返回值
#include<stdlib.h>
void abort(void);

3.由软件条件产生信号

例如:模拟闹钟

调用alarm函数可以设定一个闹钟,告诉内核在seconds秒之后给当前进程发SIGALRM信号,该信号的默认动作是终止当前程序

该函数的返回值是0或者是以前设定的闹钟时间还余下的秒数

用以下代码实现alarm的功能:

代码1:

#include<stdio.h>
#include<unistd.h>

int main()
{
    alarm(1);
    int count=0;
    for(;1;count++)
    {
    printf("count= %d\n",count);
    }
    return 0;
}

结果示意图:

这里写图片描述

###代码2:

#include<stdio.h>
#include<signal.h>
#include<sys/types.h>
#include<stdlib.h>
#include<unistd.h>

int count=0;

void hander(int sig)
{
    printf("count = %d\n",count);
}


int main()
{
    signal(14 ,hander);
    alarm(1);
    while(1)
    {
        count++;
    }

    return 0;

结果示意图:

这里写图片描述

以上两个代码均是表示count 在1 秒累加的次数,从结果看出第二个数比第一个数大很多,所以说明输入输出流对计算的速度影响非常大

三.阻塞信号


1. 信号在内核中的表示

a.实际执行信号的处理动作叫信号递达(Delivery),信号从产生到递达的状态,称为信号未决(Pending).进程可以选择阻塞某个信号。

b.信号阻塞就不会被递达,除非信号先被未决,然后解除阻塞。

c.信号在那内核中的表示示意图:

这里写图片描述

2.信号集操作函数

#include<signal.h>
int sigemptyset(sigset_t *set);//初始化set所指向的信号集,使其所有的bit清零,表示该信号集不包含任何有效信号。
int sigfillset(sigset_t *set);//初始化set所指向的信号集
int sigaddset(sigset_t *set,int signo);//在信号集中添加某种信号
int sigdelset(sigset_t *set,int signo);//在信号集中删除某种信号
int sigismemset(const sigset_t *set,int signo);//是一个布尔函数,用于判断一个信号集的有效信号中是否包含某种信号,包含返回1,反之返回0;

3.sigprocmask

#include<signal.h>
int sigprocmask(int how,const sigset *set,sigset_t *oset);//可以读取和改进进程的信号屏蔽字(阻塞信号集)

4.sigpending

#include<signal.h>
int sigpending(sigset_t *set);//读取当前进程的未决信号集,通过set参数传出

使用以上函数模拟一个信号在内核中的表示

#include<stdio.h>
#include<signal.h>
#include<unistd.h>
void show(sigset_t* pending)
{
    int i=1;
    for(; i<32; i++)
    {
        if(sigismember(pending,i))
        {
            printf("1 ");
        }
        else
        {
            printf("0 ");
        }
    }
    printf("\n");
}


int main()
{
    sigset_t block;
    sigset_t oblock;
    sigemptyset(&block);
    sigemptyset(&oblock);
    sigfillset(&block);
    sigfillset(&oblock);
    sigaddset(&block,2);
    sigprocmask(SIG_BLOCK,&block,&oblock);
    sigprocmask(SIG_BLOCK,&oblock,NULL);

    while(1)
    {
        sigpending(&block);

        show(&block);
        sleep(1);
    }
    return 0;

}

结果示意图:

这里写图片描述

程序运行时候,每秒钟都把各个信号的未决状态打印一遍,由于我们阻塞了SIGINT信号,故按CTRL+C将会使SIGINT信号处于未决状态,按CTRL+\则可以终止程序,因为SIGQUIT信号没有被阻塞。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

linux笔记之初次接触信号 的相关文章

  • 我应该使用哪个 Linux 发行版作为 Xen 主机? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我为家庭办公室订购了一台服务器 我想用 Xen 对其进行分区 我认为这将使事情保持干净并且更容易维护 我将运行 MySQL PostgreSQL
  • 是否从页面缓存中的脏页面进行文件读取?

    当字节写入文件时 内核不会立即将这些字节写入磁盘 而是将这些字节存储在页缓存中的脏页中 回写缓存 问题是 如果在脏页刷新到磁盘之前发出文件读取 则将从缓存中的脏页提供字节 还是首先将脏页刷新到磁盘 然后进行磁盘读取以提供字节 将它们存储在进
  • 进程名称长度的最大允许限制是多少?

    进程名称允许的最大长度是多少 我正在读取进程名称 proc pid stat文件 我想知道我需要的最大缓冲区 我很确定有一个可配置的限制 但就是找不到它在哪里 根据man 2 prctl http man7 org linux man pa
  • 如何在 Linux 主机上的 docker 容器中挂载目录 [重复]

    这个问题在这里已经有答案了 我想将一个目录从 docker 容器挂载到本地文件系统 该目录是网站根目录 我需要能够使用任何编辑器在本地计算机上编辑它 我知道我可以跑docker run v local path container path
  • touch命令在一个目录下创建多个文件(不同名称)

    我想制作一个在 bash 中创建目录和文件结构的脚本 我尝试过这样的事情 mkdir p 1 2 touch 1 2 a b c a b c 应该是在一个命令或其他命令中创建的文件 但由于某种原因 结构是这样的 current folder
  • 如何获取 linux 实用程序 tail 的源代码?

    这个命令确实非常有用 但是我可以在哪里获取源代码以查看内部发生的情况 thanks tail 实用程序是 Linux 上 coreutils 的一部分 源压缩包 ftp ftp gnu org gnu coreutils coreutils
  • 如何用X11复制到剪贴板?

    使用 OS X 上的框架 我可以使用以下命令将 PNG 复制到粘贴板 在 C 中 显然我可以将 NSPasteboard 与 Cocoa 一起使用 include
  • 如何使用AWK脚本检查表的所有列数据类型? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 在这里 我正在检查表中第一列的数据类型 但我想知道AWK中表的所有列数据类型 我尝试过 但只能获得一列数据类型 例如 Column 1
  • git在Windows和Linux之间切换后强制刷新索引

    我有一个Windows和Linux共享的磁盘分区 格式 NTFS 它包含一个 git 存储库 约 6 7 GB 如果我只使用Windows or 只使用Linux操作 git 存储库一切正常 但是每次切换系统的时候git status命令将
  • 每个进程每个线程的时间量

    我有一个关于 Windows 和 Linux 中进程和线程的时间量子的问题 我知道操作系统通常为每个线程提供固定的时间量 我知道时间量根据前台或后台线程而变化 也可能根据进程的优先级而变化 每个进程有固定的时间量吗 例如 如果操作系统为每个
  • 从多线程程序中调用 system()

    我们正在开发一个用 C 编写的多线程内存消耗应用程序 我们必须执行大量的 shellscript linux 命令 并获取返回码 读完之后article http www linuxprogrammingblog com threads a
  • 如何在特定 systemd 服务重新启动时触发自定义脚本运行

    我想知道如何安排自定义脚本在重新启动服务时运行 我的用例是 每当重新启动 Tomcat 服务时 我都必须运行多个命令 我想知道是否有一种方法可以编写脚本并安排它在重新启动 Tomcat 服务时运行 我已将 tomcat 脚本设置为 syst
  • Linux 桌面快捷方式和安装图标

    我需要添加什么到我的 spec文件来创建桌面快捷方式并在安装过程中为快捷方式分配一个图标 rpm 如果需要脚本 一个示例将非常有帮助 您在 Linux 下使用 desktop 文件作为图标 图标放置的位置取决于您使用的发行版和桌面环境 由于
  • 设置 Apache POI 的路径

    我想创建 Excel 文件并使用 java 程序在该文件中写入数据 That is here http www techbrainwave com p 554我在 java 文件所在的位置提取了 Apache POI 并将该路径包含在路径变
  • 没有可用的符号表信息

    我正在测试第三方的库 它崩溃了 当我想查看崩溃的原因时 我的 gdb 告诉我没有可用的调试符号 Program received signal SIGSEGV Segmentation fault Switching to Thread 0
  • 在 /dev/input/eventX 中写入事件需要哪些命令?

    我正在开发一个android需要将触摸事件发送到 dev input eventX 的应用程序 我知道C执行此类操作的代码结构如下 struct input event struct timeval time unsigned short
  • SONAR - 使用 Cobertura 测量代码覆盖率

    我正在使用声纳来测量代码质量 我不知道的一件事是使用 Cobertura 测量代码覆盖率的步骤 我按照以下步骤操作http cobertura sourceforge net anttaskreference html http cober
  • diff 文件仅比较每行的前 n 个字符

    我有2个文件 我们将它们称为 md5s1 txt 和 md5s2 txt 两者都包含a的输出 find type f print0 xargs 0 md5sum sort gt md5s txt 不同目录下的命令 许多文件被重命名 但内容保
  • 如何更改 Ubuntu 14.04 上的 php-cli 版本?

    我是 Linux 新手 在篡改时破坏了一些 php 设置 如果我执行一个包含以下内容的 php 脚本 phpinfo 它显示 php 版本为 5 6 但通过命令行 如果我运行php v它返回 7 0 版本 我想让两个版本匹配 我怎样才能修复
  • 嵌入式Linux poll()不断返回

    我有一个特别的问题 当我知道没有什么可读时 民意调查不断返回 因此设置如下 我有 2 个文件描述符 它们构成fd设置民意调查监视 一种用于引脚从高到低的变化 GPIO 另一个用于代理输入 代理输入出现问题 处理的顺序是 启动main函数 然

随机推荐

  • Webots安装和教程推荐

    安装与推荐 软件介绍 Webots是一款专业的物理仿真软件 被广泛运用在机器人 智能车仿真实践控制算法中 2018年12月该软件宣布开源 Webots最初采用C进行编程 至今已经实现提供C C Python Java Matlab接口的AP
  • JS setAttribute()方法:设置元素的属性值

    在 JavaScript 中 使用元素的 setAttribute 方法可以设置元素的属性值 用法如下 setAttribute name value 参数 name 和 value 分别表示属性名称和属性值 属性名和属性值必须以字符串的形
  • 用户政策和隐私协议

    杭州宜果送信息科技有限公司 以下简称 宜果送 重视用户的隐私 宜果送隐私政策 更新日期 2022年1月18日 提示条款 您的信任对我们非常重要 我们深知个人信息对您的重要性 我们将按法律法规要求 采取相应安全保护措施 尽力保护您的个人信息安
  • 隔离式栅极驱动器输入级对电机驱动应用的影响

    介绍 在电机驱动应用中为功率级选择隔离式栅极驱动器时 您有多种选择 栅极驱动器可简单可复杂 具有集成米勒箝位 分离输出或绝缘栅双极晶体管 IGBT 发射极的欠压 UVLO 锁定参考等功能 输入级有两个选项 电压输入级或电流输入级 在本文中
  • Visual Studio问题汇总

    合并两个vs解决方案 不能 下载别人的vs程序易出现sdk不符合等问题 项目右键属性 目标版本平台 平台工具集 都改为自己已有的就行了 还要注意配置和平台对应哦 1 问题 Callback 模板 从属名称的使用必须以模板为前缀 解决 项目右
  • 大一Python期末复习笔记

    目录 前言 一 输出格式控制 多行输出 不换行输出 精度保留和对齐 format f 二 嵌套 嵌套循环 for while 嵌套列表 字典 三 列表与字符串 添加元素 切片访问与逆序 join count find index 删除与替换
  • js闭包——简单例子

    闭包 当内部函数被保存到外部时 将生成闭包 闭包会导致原有的作用域链不释放 造成内存泄漏 如下两个例子 function test var tmp 100 function a console log tmp return a 把里面的函数
  • 4.Vue3计算属性computed实现原理

    computed实现原理 computed特性 computed可以传入一个函数 也可以传入一个对象 带有get和set方法 计算属性返回一个计算值 该值通过value属性访问 当参与计算的数据发生改变 则重新计算 不发生改变 则直接返回之
  • el-popover 样式修改

    el popover 样式修改 通过popper class绑定自定义类名popperOptions 注意popperOptions需放在样式的根文件中 原始样式 更改后的样式
  • uva 101 vector+函数设计

    vector c 中封装好的类 头文件
  • SQL DROP

    SQL DROP SQL 撤销索引 撤销表 以及撤销数据库 通过使用DROP 语句 可以轻松地删除索引 表和数据库 DROP INDEX 语句 DROP INDEX 语句用于删除表中得索引 DROP INDEX table name ind
  • Go语言入门【10】Map

    Map map是一种键值对形式的数据结构 一个键对应一个值 可以通过键快速检索出其对应的value值 在map中key的值是唯一的 value的值不唯一 并且map中保存的数据是无序的 Map声明 声明Map可以使用map关键字进行声明 同
  • 【华为OD机试真题 JS】连续出牌数量

    标题 连续出牌数量 时间限制 1秒 内存限制 262144K 语言限制 不限 有这么一款单人卡牌游戏 牌面由颜色和数字组成 颜色为红 黄 蓝 绿中的一种 数字为0 9中的一个 游戏开始时玩家从手牌中选取一张卡牌打出 接下来如果玩家手中有和他
  • 核磁共振重建算法综述

    自己整理的一些核磁共振重建综述文章 仅供参考 不发表 文章目录 摘要 一 引言 二 核磁共振成像原理 2 1 核磁共振成像过程 2 2 K空间 2 3 核磁共振数据采集过程 三 核磁共振重建方法 3 1 部分傅里叶重建方法 3 2 并行重建
  • 毕业设计—基于深度学习的网络流量预测研究

    目录 前言 课题背景和意义 实现技术思路 一 网络流量预测评价指标 二 基于深度学习的网络流量预测方法 实现效果图样例 最后 前言 大四是整个大学期间最忙碌的时光 一边要忙着备考或实习为毕业后面临的就业升学做准备 一边要为毕业设计耗费大量精
  • 【微信公众号】微信公众号授权出现的常见问题解决方案

    问题1 在微信公众号授权时出现了 解决方案 1 首先查看后端的url配置是否正确 是否进行了转码 官方API上说明了redirectUrl应使用String redirectUri URLEncoder encode redirectUrl
  • 记一次VUE项目中内存崩溃的排查

    F12 内存工具查看内存情况 大量的数据被 vue 代理 UI 框架内存溢出
  • 第七课:变量的高级主题(下)

    变量的高级主题 下 环境变量 全局变量 makfile中能够直接使用环境变量的值 定义了同名变量 环境变量将被覆盖 运行make时指定 e 选项 优先使用环境变量 为什么要在makefile中使用环境变量 优势 环境变量可以在所有的make
  • 【Attention】Dual Attention(DANet) & Fully Attention(FLA)

    空间注意力有助于保留细节信息 通道注意力有助于保留大物体的语义一致性 有效使用两种注意力可以提升性能 本文旨在记录一些常用的注意力 以及代码实现 包括两篇文章 DANet FLA Dual Attention Network for Sce
  • linux笔记之初次接触信号

    一 关于信号概念 1 信号是Linux所使用的进程间通信的最古老的方式 它是在软件层次上对中断机制的一种模拟 是一种异步通信的方式 一个完整的信号周期包括三个部分 信号的产生 信号在进程中的注册 信号在进程中的注销 执行信号处理函数 如下图