当前位置: 首页 > news >正文

linux信号机制[一]

目录

信号量

时序问题

原子性

什么是信号

 信号如何产生

引入

信号的处理方法

常见信号

如何理解组合键变成信号呢? 

如何理解信号被进程保存以及信号发送的本质?

为什么要有信号

信号怎么用?

样例代码

core文件有什么用呢?

验证core的状态

 一般生产环境为什么要关闭core

kill:结束进程

软件条件产生的信号 

硬件产生的信号

如何理解除0错误

如何理解野指针和越界问题


由于临界区,和临界资源的存在,在进入临界区访问呢临界资源的时候,必须要先申请一个信号量。通知临界区,提前预定访问临界资源。对临界资源访问的预定。只有我这个进程访问完成之后其他的资源才可以访问呢。

信号量
时序问题

信号量本质上是一个计数器。

假有一个变量n = 6需要多次--,多个进程执行

cpu执行指令的时候,将内存中的数据加载到cpu内部的寄存器中(读指令),之后(n--)分析执行命令,然后将cpu修改之后的数据写回内存。进程在执行的时候任何时候都可能被切换。寄存器只有一套,被所有执行流共享,但是寄存器数据是单独的,属于执行流的上下文。

假设一个进程刚对n执行--到5然后结果没写入,被切换了,然后其他的进程对n--到0,写回去结果,此刻之前的进程继续执行,将5写回去,这回导致之前的进程工作白费。这就引出了时序问题。这种执行是不安全的。 

原子性

为了保证避免时序问题,就需要保证,每个临界资源,被访问,只能一个进程执行完,另一个进程继续执行。这种就叫做原子性。

什么是信号

首先信号和信号量是2个东西。linux信号本质上是一中通知机制,用户或者操作系统通过发送一定的信号。通知进程,某些事件已经发生,你可以在进行后续处理。结合进程,我们可以得出以下结论:

a.进程必须有识别进程的能力

b.为什么能识别信号呢?通过程序员的逻辑处理

c.信号到来是随机的,进程可能在忙自己的事情,信号的后续处理,可能不是立即处理的。(就像打游戏时候外卖送过来)。

d.信号会被临时记录下对应的信号,方便后续的处理。

e.在什么时候处理呢?合适的时候

 f.一般而言信号的产生和进程都是异步的。

 信号如何产生
引入

当一个程序运行的时候,我们在键盘上按ctrl + c本质上就是通过键盘组合向目标发送2号信号。让程序结束。

信号的处理方法

a.默认  每个信号都有默认的信号处理方法。(进程自带的)

b.忽略(也是信号的一种处理方式)

c.自定义(捕捉信号,自己处理)

常见信号
kill -l 此命令查看所有信号

 1-31为普通信号,没有0号32,33号信号。34-64是实时信号。我们一般只关心1-31.

我们使用 man 7 signal 查看

里面有一个action 默认处理行为。

如何理解组合键变成信号呢? 

键盘的工作方式是通过中断方式进行的,可以识别组合键。操作系统解释组合键,查找进程列表找到相关的进程,修改内部数据结构。

如何理解信号被进程保存以及信号发送的本质?

为了识别信号,进程必须保存信号相关的信号数据结构。怎么表示呢?位图。pcb内部保存了信号位图字段。

信号位图是在task_struct里面保存的。发送信号的时候操作系统修改pcb内部位图字段。也就是说发信号,本质上就是修改操作系统内部指定的位图结构,完成发送信号的过程。

为什么要有信号

a.是什么信号

b.是否产生

信号怎么用?

介绍一个函数

#include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);

这个函数可以对信号进行自定义。参数1是对哪个信号进行捕捉,信号的类型,参数二是函数指针,回调函数。通过回调的方式,修改信号的处理方法。

样例代码
#include<iostream>
#include<signal.h>
#include<sys/types.h>
#include<unistd.h>
using namespace std;//信号捕捉
void catchsig(int sigum)
{cout<<"捕捉到了信号:"<<sigum<<"pid:"<<"getpid()"<<endl;
}int main()
{//SIGINT是二号信号,在用户输入ctrl信号时发出。用于通知前台结束进程signal(SIGINT,catchsig);//也可以直接写数字名字都可以,第一个参数是信号处理选项//信号的处理方法一般只有一个signal(SIGQUIT,catchsig);//二号和三号信号捕捉。//signal仅仅是修改进程对特定信号处理方法,而不是直接调用处理方法while(1){//加循环是为了给信号产生留下时间cout<<"我是一个进程在运行。。。pid:"<<getpid()<<endl;sleep(1);}return 0;
}

在之前我们查看信号的时候action里面有2个选项term 和 core

那么core是什么呢?core全程core dump核心转储标志,表示是否发送核心转储。一般而言核心转储是被关闭的。

首先解释什么是Core Dump。当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部保存到磁 盘上,文件名通常是core,这叫做Core Dump。进程异常终止通常是因为有Bug,比如非法内存访问导致段错误, 事后可以用调试器检查core文件以查清错误原因,这叫做Post-mortem Debug(事后调试)。一个进程允许 产生多大的core文件取决于进程的Resource Limit(这个信息保存 在PCB中)。默认是不允许产生core文件的, 因为core文件中可能包含用户密码等敏感信息,不安全。在开发调试阶段可以用ulimit命令改变这个限制,允许 产生core文件。 首先用ulimit命令改变Shell进程的Resource Limit,允许core文件最大为1024K:

ulimit -a

 这个命令可以查看服务器状态,里面会显示core的状态。

可以使用ulimit  -c 1024命令打开core状态,并指定core为1024字节。如果我们使用带有 core的信号的时候例如8号信号结束程序,程序会结束时带有core.并且生成core文件,以自己的pid为结尾。

core文件有什么用呢?

当进程出现异常的时候,由系统将当前进程内存中的核心数据dump到磁盘中。也就是core文件。

那么为什么要转储呢?——调试。

在使用调试生成文件之后使用gdb进行调试 core-file加载定位文件。可以直接定位到出错位置。

验证core的状态

    int status =0;waitpid(id,&status,0);cout<<"父进程"<<getppid()<<"子进程"<<getpid()<<" 退出码:"<< status&0x7f<<"是否 core"<<(status>>7&1)<<endl;
 一般生产环境为什么要关闭core

生产环境内存空间有限,因为有时候服务可能不可抗力导致一直重启,一直生产core文件,极有可能塞满内存空间出问题。

信号接口

kill:结束进程

#include <signal.h>

int kill(pid_t pid, int signo);

向指定进程发送指定信号。

int raise(int signo); 这两个函数都是成功返回0,错误返回-1

自己给自己发送自己定义的信号。

#include

void abort(void);

就像exit函数一样,abort函数总是会成功的,所以没有返回值。  自己终止自己。想当于自己给自己发6号信号

系统调用本质上也就是操作系统,修改对应的数据结构。

软件条件产生的信号 

管道——独端不读,而且一直写,会发生什么?系统会自动终止通过发送信号的方式SIGPIPE.

include <unistd.h>

unsigned int alarm(unsigned int seconds); 调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动 作是终止当前进程。

#include<iostream>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
using namespace std;
#include<signal.h>
#include<string>int main()
{alarm(1);int count =0;while(1){cout<<"cout :"<<count++<<endl;}}

 这个代码是计算一秒钟count++了多少次

虽然这个数很大但是,相比于cpu的性能其实很拉跨,这是为什么呢?

cout大量IO很消耗时间,还有网络传输发送,导致非常慢。

闹钟有一个问题,一旦使用过就会自动移除。那么闹钟如果想要周期性的使用怎么办呢?

就需要信号捕获之后在处理方法中重新设定闹钟。

硬件产生的信号

硬件异常被硬件以某种方式被硬件检测到并通知内核,然后内核向当前进程发送适当的信号。例如当前进程执行了除 以0的指令,CPU的运算单元会产生异常,内核将这个异常解释 为SIGFPE信号发送给进程。再比如当前进程访问了非 法内存地址,,MMU会产生异常,内核将这个异常解释为SIGSEGV信号发送给进程。

如何理解除0错误

数据在cpu上进行计,cpu上由寄存器,其中有一种状态寄存器。有对应的状态标记位,如果发生错误,os会自动进行计算之后的检测。这个状态是由cpu执行的,由操作系统检测。而出现硬件异常一般会打印消息然后退出。但是不退出也不是不行,不过即使不退出也没什么用。信号捕捉之后如果发生死循环这是,此刻的寄存器还是处于错误状态,没有进行复位。

如何理解野指针和越界问题

都必须通过地址,找到目标位置,语言上的地址都是虚拟地址,将语言上的虚拟地址转换成物理地址。页表+MMU(硬件),找到地址。而野指针,和越界,在mmu转化的时候一定会报错。

相关文章:

linux信号机制[一]

目录 信号量 时序问题 原子性 什么是信号 信号如何产生 引入 信号的处理方法 常见信号 如何理解组合键变成信号呢&#xff1f; 如何理解信号被进程保存以及信号发送的本质&#xff1f; 为什么要有信号 信号怎么用&#xff1f; 样例代码 core文件有什么用呢&#…...

elementui 中el-date-picker 选择年后输出的是Wed Jan 01 2025 00:00:00 GMT+0800 (中国标准时间)

文章目录 问题分析 问题 在使用 el-date-picker 做只选择年份的控制器时&#xff0c;出现如下问题&#xff1a;el-date-picker选择年后输出的是Wed Jan 01 2025 00:00:00 GMT0800 (中国标准时间)&#xff0c;输出了两次如下 分析 在 el-date-picker 中&#xff0c;我们使用…...

Redis 集群(Cluster)

集群概念 Redis 的哨兵模式&#xff0c;提高了系统的可用性&#xff0c;但是正在用来存储数据的还是 master 和 slave 节点&#xff0c;所有的数据都需要存储在单个 master 和 salve 节点中。 如果数据量很大&#xff0c;接近超出了 master / slave 所在机器的物理内存&#…...

260.【华为OD机试真题】信道分配(贪心算法-JavaPythonC++JS实现)

🚀点击这里可直接跳转到本专栏,可查阅顶置最新的华为OD机试宝典~ 本专栏所有题目均包含优质解题思路,高质量解题代码(Java&Python&C++&JS分别实现),详细代码讲解,助你深入学习,深度掌握! 文章目录 一. 题目-信道分配二.解题思路三.题解代码Python题解代码…...

Python打发无聊时光:3.实现简单电路的仿真

看到这个标题肯定有人会问&#xff1a;好好的multisim、 proteus之类的专门电路仿真软件不用&#xff0c;非要写一个简陋的python程序来弄&#xff0c;是不是精神失常了。实际上&#xff0c;我也不知道为什么要这么干&#xff0c;前两篇文章是我实际项目中的一些探索&#xff0…...

MyBatis-Plus:通用分页实体封装

分页查询实体&#xff1a;PageQuery package com.example.demo.demos.model.query;import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.Data; import org.springframework.util.St…...

MVC 、DDD(domain-driven design,软件主动学习业务)、中台、Java SPI(Service Provider Interface)

文章目录 引言I 单体架构DDD实现版本1.1 核心概念1.2 DDD四层架构规范1.3 案例1.4 请求转发流程II 领域服务调用2.1 菱形对称架构2.2 中台III Java SPI3.1 概念3.2 实现原理3.3 例子:本地SPI找服务see alsojava -cp<...

添加环境变量

目录 一、前言二、目的三、添加环境变量的步骤四、检查环境变量是否配置成功 一、前言 在很多地方在下载完软件后都需要添加环境变量方可使用。这里以要在终端使用MySQL为例来说一下&#xff0c;在安装好MySQL8.0版本的前提下&#xff0c;如何添加环境变量。 二、目的 添加环…...

学习Android的第十六天

目录 Android 自定义 Adapter Adapter 接口 SpinnerAdapter ListAdapter BaseAdapter 自定义 BaseAdapter 参考文档 Android ListView 列表控件 ListView 的属性和方法 表头表尾分割线的设置 列表从底部开始显示 android:stackFromBottom 设置点击颜色 cacheColorH…...

若依项目改造

ctrlalt l 格式化项目 alt f6 修改包和import包名 替换com.ruoyi 为 com.cj 替换若依版本为自己的版本 将ruoyi改成自己项目的英文名 修改中文名字 修改文件包名 修改有ruoyi的类名 &#xff1a; 验证码生成器包名修改&#xff1a;...

相机图像质量研究(34)常见问题总结:图像处理对成像的影响--拖影

系列文章目录 相机图像质量研究(1)Camera成像流程介绍 相机图像质量研究(2)ISP专用平台调优介绍 相机图像质量研究(3)图像质量测试介绍 相机图像质量研究(4)常见问题总结&#xff1a;光学结构对成像的影响--焦距 相机图像质量研究(5)常见问题总结&#xff1a;光学结构对成…...

算法学习系列(三十五):贪心(杂)

目录 引言一、合并果子&#xff08;Huffman树&#xff09;二、排队打水&#xff08;排序不等式&#xff09;三、货仓选址&#xff08;绝对值不等式&#xff09;四、耍杂技的牛&#xff08;推公式&#xff09; 引言 上一篇文章也说过了这个贪心问题没有一个规范的套路和模板&am…...

嵌入式面试:瑞芯微

文章目录 一、2024 秋招1.1 IIC的速率范围 &#xff1a;1.2 linux驱动子系统汇总 &#xff1a;1.3 linux关抢占情况汇总 &#xff1a;1.4 操作或者读写一个文件时&#xff0c;从用户态到内核态再到物理介质的流程(考点&#xff1a;虚拟文件系统) &#xff1a; 一、2024 秋招 1…...

【性能测试】分布式压测之locust和Jmeter的使用

受限于单台机器的配置问题&#xff0c;我们在单台机器上达不到一个很高的压测并发数&#xff0c;那这个时候就需要引入分布式压测 分布式压测原理&#xff1a; 一般通过局域网把不同测试计算机链接到一起&#xff0c;达到测试共享、分散操作、集中管理的目的。 选择一台作为…...

ABC341A-D题解

文章目录 A题目AC Code&#xff1a; B题目AC Code&#xff1a; C题目AC Code&#xff1a; D题目你以为这就完了&#xff1f; 时间复杂度分析&#xff1a;AC Code&#xff1a; E A 题目 这个没什么好说的&#xff0c;就先输出一个 1&#xff0c;再输出 n n n 个 01就大功告成…...

计算机网络——07协议层次及服务模型

协议层次及服务模型 协议层次 网络是一个复杂的系统 网络功能复杂&#xff1a;数字信号的物理信号承载、点到点、路由、rdt、进程区分、应用等现实来看&#xff0c;网络的许多构成元素和设备&#xff1a; 主机路由器各种媒体的链路应用协议硬件&#xff0c;软件 问题是&am…...

Netty Review - NIO空轮询及Netty的解决方案源码分析

文章目录 Pre问题说明NIO CodeNetty是如何解决的&#xff1f;源码分析入口源码分析selectCntselectRebuildSelector Pre Netty Review - ServerBootstrap源码解析 Netty Review - NioServerSocketChannel源码分析 Netty Review - 服务端channel注册流程源码解析 问题说明 N…...

PAM | 账户安全 | 管理

PAM PAM&#xff08;Pluggable Authentication Modules&#xff0c;可插入式身份验证模块&#xff09;是一个灵活的身份验证系统&#xff0c;允许我们通过配置和组合各种模块来实现不同的身份验证策略。 在 Linux 或类 Unix 系统中&#xff0c;常见的 PAM 模块包括以下几种类…...

Leetcode 16-20题

最接近的三数之和 给定整数数组和目标值target&#xff0c;从数组中选出三个整数&#xff0c;使得和与target最接近&#xff0c;并返回三数之和。保证恰好存在一个解。 和上一题类似&#xff0c;我们先对整数数组排序&#xff0c;然后固定i&#xff0c;枚举j&#xff0c;找到满…...

【开源训练数据集1】神经语言程式(NLP)项目的15 个开源训练数据集

一个聊天机器人需要大量的训练数据,以便在无需人工干预的情况下快速解决用户的询问。然而,聊天机器人开发的主要瓶颈是获取现实的、面向任务的对话数据来训练这些基于机器学习的系统。 我们整理了训练聊天机器人所需的对话数据集,包括问答数据、客户支持数据、对话数据和多…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

如何在最短时间内提升打ctf(web)的水平?

刚刚刷完2遍 bugku 的 web 题&#xff0c;前来答题。 每个人对刷题理解是不同&#xff0c;有的人是看了writeup就等于刷了&#xff0c;有的人是收藏了writeup就等于刷了&#xff0c;有的人是跟着writeup做了一遍就等于刷了&#xff0c;还有的人是独立思考做了一遍就等于刷了。…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek

文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama&#xff08;有网络的电脑&#xff09;2.2.3 安装Ollama&#xff08;无网络的电脑&#xff09;2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

日常一水C

多态 言简意赅&#xff1a;就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过&#xff0c;当子类和父类的函数名相同时&#xff0c;会隐藏父类的同名函数转而调用子类的同名函数&#xff0c;如果要调用父类的同名函数&#xff0c;那么就需要对父类进行引用&#…...