当前位置: 首页> 教育> 锐评 > 动态照片制作_网站首页设计效果图_太原百度关键词排名_seo排名优化公司

动态照片制作_网站首页设计效果图_太原百度关键词排名_seo排名优化公司

时间:2025/7/13 19:03:30来源:https://blog.csdn.net/2302_80026357/article/details/146441360 浏览次数:0次
动态照片制作_网站首页设计效果图_太原百度关键词排名_seo排名优化公司

引言

在Linux系统中,信号机制是实现进程间异步通信的重要方式,其生命周期可分为三个关键阶段:信号产生→信号保存→信号处理。这种机制如同我们生活中的红绿灯系统:信号随时可能异步产生(红灯亮起),操作系统需要暂存信号(等待行人到达路口),最终在合适时机执行处理(做出停止或通行决策)。

信号基础

  1. 信号分类
    • 普通信号(1-31):经典UNIX信号,如SIGINT(2)/SIGKILL(9)
    • 实时信号(34-64):扩展信号,支持队列化处理
    • 查看命令:kill -l显示62个有效信号(缺失0/32/33号)
  2. 生活化类比
    • 红绿灯规则:认识信号(颜色识别)→定义行为(停/行)
    • 外卖通知:异步响应(游戏挂机时接电话)→延迟处理(推完高地再取餐)
    • 闹钟提醒:默认动作(起床)→忽略处理(蒙头继续睡)→自定义响应(关闭闹钟后晨练)

信号特性

  1. 异步性
    信号产生与处理存在时间窗口,如同快递员送货与收件人活动的独立时序。这种异步特性要求系统必须通过pending位图等机制暂存未决信号。
  2. 内核级流转
    当信号触发时,CPU从用户态陷入内核态完成信号检测,再返回用户态执行处理程序。这种状态切换如同交警临时接管交通指挥权。
  3. 处理三态

处理方式

系统行为

生活案例

默认动作

SIG_DFL(终止/忽略等)

绿灯通行

忽略信号

SIG_IGN

屏蔽骚扰电话

自定义处理

注册handler函数

特殊门铃响应机制

理解信号的预备工作

信号的本质认知

  1. 信号接收主体
    • 信号的本质是操作系统向进程发送的异步通知,所有信号操作均以进程为基本单位
    • 验证方式:kill -9 PID命令通过进程ID定向发送信号
  2. 进程识别机制
    • 识别前提:
      • 认知能力:通过代码预定义信号处理逻辑(程序员编写)
      • 响应能力:操作系统维护的进程控制块(PCB)提供支持
    • 类比理解:如同人类通过教育习得红绿灯规则(认知)并形成条件反射(响应)

信号存储原理

存储维度

技术实现

核心特性

数据结构

PCB中的pending位图(32位无符号整型)

比特位映射信号编号(1-31)

编码规则

比特位索引=信号编号-1

0表示未接收,1表示已接收

修改权限

仅操作系统可操作

用户空间无法直接访问内核数据

信号发送本质

  1. 操作实质
    • 所有信号发送操作最终表现为修改目标进程PCB中的信号位图
    • 示例:发送9号信号 = 将pending位图的第9位设为1
  2. 权限体系
    • 内核独占:只有操作系统有权修改PCB结构
    • 用户接口:通过系统调用(如kill())触发内核级操作
    • 命令本质:kill命令是封装系统调用的用户态工具

关键设计思想

1.异步处理机制

  • 信号产生与处理的时间窗口分离设计
    • 当进程收到信号的时候,进程可能正在执行更重要的代码,所以信号不一定会被立即处理进程本身必须对信号有保存能力。
    • 类比场景:外卖通知到达时用户可能正在执行高优先级任务

2.内核态管控

  • PCB是内核维护的数据结构对象,管理者是操作系统,所以我们未来发送信号的方式,本质上都是通过操作系统向目标进程发送信号的

  • 系统调用作为安全边界保障操作合法性
  • 用户程序通过注册handler实现有限自定义
  • 信号生命周期全程由操作系统调度
         [用户空间]                          [内核空间]│                                  │├─ kill命令                        ││    │                             ││    └─ 触发系统调用                │▼                                  ▼
进程A发送信号请求 → 系统调用接口 → 内核修改进程B的PCB位图│▼信号暂存于pending位图│▼等待进程B进入可中断状态

信号的产生

一、通过终端按键产生信号

  1. Ctrl+C的本质
    • 硬件中断触发:键盘控制器检测到Ctrl+C组合键时产生中断
    • 内核转换机制:操作系统将中断转换为SIGINT(2)信号
    • 默认处理动作:立即终止前台进程(对应SIG_DFL标志)
    • 仅影响前台进程(带+号的进程)

二、调用系统函数向进程发信号

  1. kill 给任意进程发送任意信号

#include <signal.h>
int kill(pid_t pid, int sig);

函数

作用域

等效操作

典型信号

raise()

当前进程

kill(getpid(), sig)

SIGTERM

abort()

强制终止

kill(getpid(),6)

SIGABRT

alarm()

定时触发

内核定时器

SIGALRM

三、由软件条件产生信号

alarm系统调用

#include <unistd.h>
unsigned int alarm(unsigned int seconds);

软件条件 --"闹钟"其实就是用软件实现的。任意一个进程,都可以通过alarm系统调用在内核中设置闹钟,OS内可能会存在着很多的闹钟,那么操作系统要不要管理这些闹钟呢?要。

四、硬件异常产生信号

信号产生不一定由用户显示发送,也可以由操作系统自动发送。

异常类型

触发信号

典型场景

除零错误

SIGFPE(8)

int a = 5/0;

非法内存访问

SIGSEGV(11)

野指针解引用

非法指令

SIGILL(4)

损坏的可执行文件

状态寄存器:每个CPU运算结果都会更新状态寄存器标志位

一旦除0,在硬件上CPU先出异常,然后被操作系统识别,操作系统将溢出标志位的异常转化为对应的信号,发送给目标进程 。操作系统如何知道我除0了呢?语言上写的C/C++代码最底层都属于硬件异常,然后操作系统将硬件问题转化为软件问题,向你的目标进程发信号,终止这个进程,这就是我们除0进程会崩溃的原因。收到信号,不一定会引起进程退出,如果没有退出,这个信号的行为还会被调度到。我们没有能力去修正CPU所维护的状态寄存器,所以当进程被切换的时候,状态信息被保存,进程恢复的时候,操作系统会再次识别到CPU里的状态寄存器,从而一直发送信号。


MMU检测:内存管理单元校验虚拟地址合法性

graph LR
A[虚拟地址] --> B(页表查询)
B --> C{物理页存在?}
C -->|是| D[正常访问]
C -->|否| E[触发SIGSEGV]

#include <iostream>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>using namespace std;static void Usage(const std::string &proc)
{std::cout << "\nUsage: " << proc << " pid signo\n"<< std::endl;
}// int cnt = 0;
void catchSig(int signo)
{std::cout << "获取到一个信号,信号编号是: " << std::endl;// exit(1);// alarm(1);
}
// ./myprocess pid signo
int main(int argc, char *argv[])
{// for(int signo = 1; signo <= 31; signo++)// {//     signal(signo, catchSig);// }// while(true) // {//     cout << "我在运行: " << getpid() <<endl;//     sleep(1);// }// 核心转储// while (true)// {//     int a[10];//     // a[10000] = 106;// }// 4. 软件条件 -- "闹钟"其实就是用软件实现的// IO其实很慢// 统计1S左右,我们的计算机能够将数据累计多少次!// signal(SIGALRM, catchSig);// alarm(1);// while(true)// {//     cnt++;// }// 3. 产生信号的方式:硬件异常产生信号// 信号产生,不一定非得用户显示的发送!// signal(SIGFPE, catchSig);// int a = 10;// // 如何证明?// // 受到信号,不一定会引起进程退出 -- 没有退出,有可能还会被调到// // -- CPU内部的寄存器只有一份,但是寄存器中的内容,属于当前进程的上下文!// // 你有没有能力或者动作修正这个问题呢?没有// // 当进程被切换的时候,就有无数次状态寄存器被保存和回复的过程// // 所以每一次恢复的时候,就让OS识别到了CPU内部的状态寄存器中的溢出标志位是1// // OS如何得知应该给当前进程发送8号信号的-- OS怎么知道我除0了呢??,CPU会异常// a /= 0; // 为什么除0 会终止进程?当前进程会受到来自OS系统的信号(告知),SIGFPE// signal(11, catchSig);// while (true)// {//     std::cout << "我在运行中...." << std::endl;//     sleep(1);//     int *p = nullptr;//     // p = nullptr; // 1//     // OS怎么知道呢??我野指针了呢?//     *p = 100;  //为什么 野指针 就会崩溃呢?因为OS会给当前进程发送指定的11号信号// }// 2. 系统调用向目标进程发送信号// kill()可以想任意进程发送任意信号// raise() 给自己 发送 任意信号kill(getpid(), 任意信号)// abort() 给自己 发送 指定的信号SIGABRT, kill(getpid(), SIGABRT)// 关于信号处理的行为的理解:有很多的情况,进程收到大部分的信号,默认处理动作都是终止进程// 信号的意义:信号的不同,代表不同的事件,但是对事件发生之后的处理动作可以一样!// int cnt = 0;// while(cnt <= 10)// {//     printf("cnt: %d, pid: %d\n", cnt++, getpid());//     sleep(1);//     // if(cnt >= 5) abort(); // kill(getpid(), signo)//     // if(cnt >= 5) raise(9); // kill(getpid(), signo)// }// if(argc != 3)// {//     Usage(argv[0]);//     exit(1);// }// pid_t pid = atoi(argv[1]);// int signo = atoi(argv[2]);// int n = kill(pid, signo);// if(n != 0)// {//     perror("kill");// }// 1. 通过键盘发送信号// while(true)// {//     std::cout << "hello world" << std::endl;//     sleep(1);// }
}

进程退出时的核心转储问题

核心转储的概念

当进程出现异常的时候,我们将进程在对应的时刻,在内存中的有效数据核心转储到磁盘中

Term与Core终止的本质区别

在Linux信号机制中,进程的异常退出分为两种类型:

  1. Term(SIGTERM)
    • 正常终止:操作系统直接结束进程,不保留额外信息
    • 典型场景:kill -15 PID 或 Ctrl+C 触发的默认终止
    • 特点:无调试信息留存,适用于预期内的进程终止
  2. Core(SIGSEGV/SIGFPE等)
    • 异常终止:操作系统在终止进程前生成核心转储文件
    • 典型场景:段错误(SIGSEGV)、除零错误(SIGFPE)
    • 特点:保存进程崩溃时的完整内存镜像,支持事后调试

结语

本文主要讲解了信号的预备知识、信号的产生以及核心转储等内容,下一篇我们将详细介绍信号的保存和递达处理。

关键字:动态照片制作_网站首页设计效果图_太原百度关键词排名_seo排名优化公司

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: