Linux 第三十章
🐶博主主页:@ᰔᩚ. 一怀明月ꦿ
❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C++,linux
🔥座右铭:“不要等到什么都没有了,才下定决心去做”
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
目录
信号量
如何理解信号量
信号
信号的概念
信号的产生
singal
信号种类
0-31是普通信号
通过系统调用实现信号产生
Kill系统调用
raise
abort
异常发送信号
软件条件产生异常
alarm
信号量
信号量的本质是一把“计数器”
多个执行流(进程)看到的同一份资源,其实就是公共资源(由os提供的),如果并发访问同一份资源,会导致数据不一致的问题,我们就应该对公共资源进行保护,可以利用可同步和互斥(在多线程的时候着重理解)来解决。
互斥:任何时刻只允许一个执行流(进程)访问公共资源,加锁实现的
同步:多个执行流(进程)执行的时候,按照一定顺序执行,条件变量实现
被保护起来的公共资源,临界资源
访问临界资源的代码,临界区
非临界资源
非临界区
维护临界资源,其实就是在维护临界区
原子性:只有2两种状态,要么做,要么不做
如何理解信号量
信号量:表示资源数目的计数器,每一个执行流(进程)想要访问公共资源内的某一份资源,不应该让执行流(进程)直接访问,而是先申请信号量资源,其实就是先对信号量计数器进行--操作。本质上--就完成了,对资源的预定机制
如果申请不成功?我们的执行流(进程)被阻塞,等到申请成功
申请信号量资源是--
释放信号量资源是++
二元信号量:起到了互斥的效果(因为信号量资源只有一份),互斥锁
1.意味着,每一个进程都先看到同一个信号量资源 2.信号量本质也是公共资源 3.单个信号量 struct sem {Int count;Task_strct* wait_queue }
信号
信号的概念
生活中的信号
红绿灯、下课铃声、狼烟、闹钟等等
我(进程)为什么知道信号呢?肯定我(进程)之前就了解过信号
信号没有产生的时候,其实我(进程)已经能够知道,怎么处理这个信号
信号的到来,我(进程)并清楚具体什么时候,信号到来相对于我(进程)正在做的工作,是异步产生的
信号产生了,我(进程)不一定立即处理它,而是我(进程)在合理的时候处理
我(进程)必须要一种能力,将已经到来的信号进行暂时保存
什么叫做信号
信号是向目标进程发送通知消息的一种机制
异步
简单理解:在同一个时间下,一个进程做一个事情的时候,另一个进程也在做事情
信号的产生
进程在运行的时候
例:
前台运行:./myprocess
后台运行:./myprocess &前台进程只能有一个,后台进程可以有多个
在 Linux 终端中,jobs 是一个命令用于显示当前终端会话中正在运行的作业(进程)。当你在终端上启动一个作业时,它将在前台或后台运行。使用 jobs 命令可以列出这些作业的状态和编号。
以下是一些与 jobs 命令相关的常用操作:
1. jobs:列出当前终端会话中正在运行的进程。每个进程都有一个编号,并且会显示进程状态(运行中、停止等)。
2. bg <job编号>:将一个停止的进程切换到后台运行。<job编号> 是通过 jobs 命令列出的进程编号。
3. fg <job编号>:将一个在后台运行的进程切换到前台运行。<job编号> 是通过 jobs 命令列出的进程编号。
4. Ctrl+Z:将当前正在前台运行的进程暂停,并将其放置到后台。可以使用 jobs 命令查看该进程的状态和编号。
5. Ctrl+C:终止当前正在前台运行的进程(不会终止shell)。OS怎么知道键盘有数据输入呢?
通过硬件向CPU发送中断号,CPU就能够知道键盘有数据输入
信号本质其实就是用软件,来模拟中断的行为
键盘有两种数据输入:
1.普通数据
2.组合键的输入(^C、^Z等)
信号在合适的时候处理
1.默认行为(例如,生活中红灯时,需要我们等一等)
2.忽略行为
3.自定义的(例如,在等红灯的时候,唱歌)
singal
在 Linux 中,signal() 函数用于注册信号处理函数,
该函数原型如下:
#include <signal.h> void (*signal(int signum, void (*handler)(int)))(int); * signum 表示要捕获的信号编号,比如 SIGINT、SIGTERM 等。 * handler 是一个指向函数的指针,该函数负责处理接收到的信号。 signal() 函数的返回类型是一个函数指针,指向当前信号的处理函数。在调用 signal() 函数时,会将之前注册的信号处理函数(如果有的话)替换为新的处理函数,并返回之前注册的处理函数。
下面是一个简单的示例,演示如何使用 signal() 函数来捕获 SIGINT 信号并设置相应的处理函数:
#include <stdio.h> #include <signal.h> #include <unistd.h>void sigint_handler(int signum) {printf("Caught SIGINT signal, exiting...\n");exit(1); }int main() {// 注册 SIGINT 信号处理函数signal(SIGINT, sigint_handler);printf("Press Ctrl+C to send a SIGINT signal...\n");while (1) {// 进程持续执行}return 0; }
在示例中,我们定义了一个名为 sigint_handler 的函数,用于处理接收到的 SIGINT 信号。然后,在 main() 函数中使用 signal() 函数注册了这个信号处理函数。当用户按下 Ctrl+C 发送 SIGINT 信号时,该处理函数将被调用。需要注意的是,signal() 函数在一些情况下可能会有一些不确定的行为,因此推荐使用更加可靠和灵活的 sigaction() 函数来注册信号处理函数。
信号种类
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP6) 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
信号既有名字,又有值,说明是用宏定义的
没有0号信号(用来标识进程正常退出)
信号一共62个信号,是从0-31和34-64
0-31是普通信号
* SIGHUP (1):挂起信号,通常用于重启进程。 * SIGINT (2):中断信号,通常由Ctrl+C发出,用于停止进程。 * SIGQUIT (3):退出信号,通常由Ctrl+\发出,用于强制终止进程。 * SIGILL (4):非法指令信号,通常由进程执行无效的机器指令而引起。 * SIGTRAP (5):陷阱信号,通常用于调试。 * SIGABRT (6):异常终止信号,通常由abort()函数发出,表示进程存在严重问题需要终止。 * SIGBUS (7):总线错误信号,通常由非法内存访问引起。 * SIGFPE (8):浮点异常信号,通常由除零或其他数学错误引起。 * SIGKILL (9):强制终止信号,无法被捕获、忽略或阻塞,用于强制杀死进程。 * SIGUSR1 (10):用户定义信号1。 * SIGSEGV (11):段错误信号,通常由非法内存访问引起。 * SIGUSR2 (12):用户定义信号2。 * SIGPIPE (13):管道破裂信号,通常发生在进程向已关闭的管道写入数据时。 * SIGALRM (14):定时器信号,通常由alarm()函数或setitimer()函数发出。 * SIGTERM (15):终止信号,通常用于请求进程正常停止。 * SIGSTKFLT (16):堆栈错误信号,通常发生在堆栈溢出时。 * SIGCHLD (17):子进程状态改变信号,通常用于父进程监控子进程的状态。 * SIGCONT (18):继续执行信号,通常用于恢复被停止的进程。 * SIGSTOP (19):停止信号,无法被捕获、忽略或阻塞,用于暂停进程。 * SIGTSTP (20):挂起信号,通常由Ctrl+Z发出,用于暂停进程。 * SIGTTIN (21):后台读取信号,通常发生在后台进程尝试从终端读取数据时。 * SIGTTOU (22):后台写入信号,通常发生在后台进程尝试向终端写入数据时。 * SIGURG (23):紧急数据可读信号,通常发生在带外数据到达时。 * SIGXCPU (24):CPU时间限制信号,通常发生在进程超过CPU时间限制时。 * SIGXFSZ (25):文件大小限制信号,通常发生在进程超过文件大小限制时。 * SIGVTALRM (26):虚拟定时器信号,通常由setitimer()函数发出。 * SIGPROF (27):CPU时间分配信号,通常由setitimer()函数发出。 * SIGWINCH (28):窗口大小改变信号,通常发生在终端窗口大小改变时。 * SIGIO (29):异步I/O信号,通常用于异步I/O操作。 * SIGPWR (30):电源故障信号,通常发生在电源故障时。 * SIGSYS (31):系统调用错误信号,通常由进程执行非法的系统调用而引起。
每一个进程都有一张自己的函数指针数组表,数组的下标就和信号编号相关的
对于普通信号来讲,进程收到信号之后,进程要表示自己是否收到了某种信号
怎么表示是否收到呢?
可以使用位图的方式:0000 0000 比特位的位置,决定信号编号 比特位的内容,决定是否收到信号 在进程控制块中,有一个字段就是位图 task_struct {//信号位图uint32_t sigmap; }
OS向目标进程发送信号,其实就是向目标进程pcb的位图写信号
注意:无论信号有多少种产生方式,永远只能让OS向目标进程发送(OS是进程的管理者)
每个进程与信号相关都两个字段
1.函数指针数组
2.信号位图
34-64是实时信号
ctrl+z:默认暂停进程
ctrl+\:默认是终止进程
signal系统调用可以自定义,信号的处理方法
man 7 signal可以查看信号的默认处理方法
注意,像9号等信号不能自定义信号的处理方法
通过系统调用实现信号产生
Kill系统调用
kill 系统调用的原型如下:
#include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); 其中,pid 参数指定要发送信号的目标进程的进程ID,sig 参数指定要发送的信号编号。
以下是 kill 系统调用的常见用法:
终止进程:使用 SIGKILL 信号(编号为9)可以强制终止指定进程。
kill(pid, SIGKILL);请注意,kill 系统调用只能发送信号给具有合法权限的目标进程。此外,kill 系统调用返回0表示成功,返回-1表示出错,并设置相应的错误码。
raise
raise 是一个函数,用于向当前进程发送信号。它的原型如下:
#include <signal.h> int raise(int sig); 其中,sig 参数指定要发送的信号编号。使用 raise 函数,可以向当前进程发送指定的信号。例如,以下代码将向当前进程发送 SIGTERM 信号(请求进程优雅地终止): raise(SIGTERM); 与 kill 系统调用不同,raise 函数只能向当前进程发送信号,不能向其他进程发送信号。此外,raise 函数返回0表示成功,返回非零值表示出错,通常是因为指定了无效的信号编号。
abort
abort 是一个函数,用于向当前进程发送 SIGABRT 信号并终止进程。它的原型如下: #include <stdlib.h> void abort(void); abort 函数会向当前进程发送 SIGABRT 信号,该信号的默认处理方式是生成一个核心转储文件并终止进程。abort 函数通常被用于在程序发生无法恢复的错误时,终止程序并生成一个核心转储文件以供调试分析。例如,在以下代码中,如果 malloc 函数返回空指针,我们可以使用 abort 函数终止程序并生成一个核心转储文件: #include <stdlib.h> void *ptr = malloc(size); if (ptr == NULL) {fprintf(stderr, "Error: failed to allocate memory.\n");abort(); } 请注意,与 exit 函数不同,abort 函数不会调用已注册的退出处理程序,也不会关闭流或执行任何其他清理操作。因此,abort 函数应该谨慎使用,仅在必要时才使用。
异常发送信号
int a=10; a/=0;如果异常不做处理(杀掉该进程),os会一直调度该进程,然后又出异常,循环往复。
寄存器!=寄存器里内容(进程上下文)
进程中的程序异常,进程一定会退出吗?默认情况下会退出,如果用signal自定义信号处理方法的话,就不一定了
如果进程出异常,和我们的编译器还有关系吗?进程会被OS直接终止了
一般出异常,是没有办法去处理这个异常,一般出异常,我们会显示这个异常,让我们自己看到
软件条件产生异常
alarm
#include <unistd.h> unsigned int alarm(unsigned int seconds); 调用alarm函数可以设定一个闹钟,也就是告诉内核在seconds秒之后给当前进程发SIGALRM信号, 该信号的默认处理动 作是终止当前进程,如果 seconds 参数为0,则之前设置的闹钟将被取消,并返回剩余的闹钟时间。int main() {alarm(1);int cnt=0;while(true){cout<<"alarm: "<<cnt++<<endl;}return 0; }
操作系统中的时间:
1.所有用户的行为,都是以进程的形式在OS中表现的
2.OS只要把进程调度好,就能完成所有的用户任务
3.CMOS,周期性,高频率的,向CPU发送时钟中断
OS本质就是一个死循环,操作系统的执行,是基于硬件中断的!!!
🌸🌸🌸如果大家还有不懂或者建议都可以发在评论区,我们共同探讨,共同学习,共同进步。谢谢大家! 🌸🌸🌸
相关文章:

Linux 第三十章
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C,linux 🔥座右铭:“不要等到什么都没有了…...

Linux网络——自定义序列化与反序列化
前言 之前我们学习过socket之tcp通信,知道了使用tcp建立连接的一系列操作,并通过write与read函数能让客户端与服务端进行通信,但是tcp是面向字节流的,有可能我们write时只写入了部分数据,此时另一端就来read了&#x…...
大模型介绍
大模型通常指的是参数量超过亿级别,甚至千亿级别的深度学习模型。这类模型能够处理更加复杂的任务,并在各项基准测试中取得了优异的成绩。大模型在自然语言处理、计算机视觉、推荐系统等领域都取得了显著的成果。 大模型的主要优势在于其强大的表征能力&…...
【思维】根号分治
写在前面的话: 个人理解 根号分治本身就是一种卡着评测机过题的做法,所以非必要不要写 #define int long long !!! 本篇博客参考:暴力美学——浅谈根号分治 做到过两三题根号分治了,来总结一下…...

Linux线程(三)死锁与线程同步
目录 一、什么是死锁 死锁的四个必要条件 如何避免死锁 避免死锁算法 二、Linux线程同步 三 、条件变量 1、条件变量基本原理 2、条件变量的使用 3、条件变量使用示例 为什么 pthread_cond_wait 需要互斥量? 一、什么是死锁 死锁是计算机科学中的一个概念,…...

SpringAMQP 发布订阅-TopicExchange
根据这个模型编写代码: RabbitListener(bindings QueueBinding(value Queue(name "topic.queue1"),exchange Exchange(name "itcast.topic",type ExchangeTypes.TOPIC),key {"china.#"}))public void listenTopicQueue1(String msg){Syst…...

uniapp h5 配置代理服务器
"devServer": {"disableHostCheck": true,"proxy": {"/api": {// 需要被代理的后台地址"target": "http://自己的地址","changeOrigin": true,"secure": false,"pathRewrite": {&q…...

使用Apache Spark从MySQL到Kafka再到HDFS的数据转移
使用Apache Spark从MySQL到Kafka再到HDFS的数据转移 在本文中,将介绍如何构建一个实时数据pipeline,从MySQL数据库读取数据,通过Kafka传输数据,最终将数据存储到HDFS中。我们将使用Apache Spark的结构化流处理和流处理功能&#…...

一篇文章拿下Redis 通用命令
文章目录 Redis数据结构介绍Redis 通用命令命令演示KEYSDELEXISTSEXPIRE RedisTemplate 中的通用命令 本篇文章介绍 Redis 的通用命令, 通用命令在 Redis 的所有数据类型下都使用, 学好通用命令可以让我们更好的使用 Redis. Redis数据结构介绍 Redis 是一个key-value的数据库&…...
锂电池充电充放电曲线分析
前言 锂电池的充电曲线通常包括三个阶段:恒流充电阶段、恒压充电阶段和滞后充电阶段。在恒流充电阶段,电流保持恒定,电压逐渐增加;在恒压充电阶段,电压保持恒定,电流逐渐减小;在滞后充电阶段,电流进一步减小,电池开始充满。通过监测这些阶段的电流和电压变化,可以评…...
vue3 第二十九节 (vue3 事件循环之nextTick)
引言 vue 项目中为什么要使用 nextTick 这个函数,是做什么用的,解决了哪些问题 1、nextTick 作用 用于处理DOM更新完成之后,执行回调函数的方法; 2、实现方案 vue2 中 nextTick() 是基于浏览器的 异步队列和微任务队列而执行…...

使用Flask-SocketIO构建实时Web应用
文章目录 准备工作编写代码编写HTML模板运行应用 随着互联网的发展,实时性成为了许多Web应用的重要需求之一。传统的HTTP协议虽然可以实现实时通信,但是其长轮询等机制效率低下,无法满足高并发、低延迟的需求。为了解决这一问题,诞…...

可重构柔性装配产线:为工业制造领域注入了新的活力
随着科技的飞速发展,智能制造正逐渐成为引领工业革新的重要力量。在这一浪潮中,可重构柔性装配产线以其独特的技术优势和创新理念,为工业制造领域注入了新的活力,开启了创新驱动的智能制造新篇章。 可重构柔性装配产线是基于富唯智…...

懒人网址导航源码v3.9
测试环境 宝塔Nginx -Tengine2.2.3的PHP5.6 MySQL5.6.44 为防止调试错误,建议使用测试环境运行的php与mysql版本 首先用phpMyAdmin导入数据库文件db/db.sql 如果导入不行,请直接复制数据库内容运行sql语句也可以 再修改config.php来进行数据库配置…...
springboot 开启缓存 @EnableCaching(使用redis)
添加依赖 pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>application.yml 配置redis连参数 spring:# redis 配置redis:# 地址host: 127.0.0.…...

Adobe After Effects AE v24.3.0 解锁版 (视频合成及视频特效制作)
Adobe系列软件安装目录 一、Adobe Photoshop PS 25.6.0 解锁版 (最流行的图像设计软件) 二、Adobe Media Encoder ME v24.3.0 解锁版 (视频和音频编码渲染工具) 三、Adobe Premiere Pro v24.3.0 解锁版 (领先的视频编辑软件) 四、Adobe After Effects AE v24.3.0 解锁版 (视…...

Qt---文件系统
一、基本文件操作 1. QFile对文件进行读和写 QFile file( path 文件路径) 读: file.open(打开方式) QlODevice::readOnly 全部读取->file.readAll(),按行读->file.readLine(),atend()->判断是否读到文件尾 …...
ruoyi-vue-pro 使用记录(2)
ruoyi-vue-pro 使用记录(2) 数据库商城商品模块数据表营销数据库交易数据库统计数据库 数据库 商城 参考官方文档 ruoyi-vue-pro yudao 项目商城 mall 模块启用及相关SQL脚本 商品模块(中心)以 product_ 作为前缀的表交易模块…...

centos7中如何全局搜索一下nginx的配置文件?
在CentOS 7中搜索Nginx的配置文件,你可以使用一些常用的命令行工具,比如find、grep等。这些工具可以帮助你在文件系统中查找文件,也可以用来查找Docker容器内部的文件,只要你知道如何访问容器的文件系统。 1. 搜索系统中的Nginx配…...

2024年5月10日有感复盘
2024年5月10日有感复盘 时间 今天是一个很美好的一天,原因是很平凡,读书很平凡,玩游戏很平凡,然后生活很平凡,未来可期,听歌很舒服,很喜欢一个人呆在图书馆的感觉,很喜欢发呆&…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
五年级数学知识边界总结思考-下册
目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解:由来、作用与意义**一、知识点核心内容****二、知识点的由来:从生活实践到数学抽象****三、知识的作用:解决实际问题的工具****四、学习的意义:培养核心素养…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

springboot 日志类切面,接口成功记录日志,失败不记录
springboot 日志类切面,接口成功记录日志,失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...

若依登录用户名和密码加密
/*** 获取公钥:前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...