首页 > 其他分享 >信号-1-信号的产生

信号-1-信号的产生

时间:2024-11-07 17:50:22浏览次数:3  
标签:status core 产生 int 信号 进程 include

什么是信号

信号产生方式

键盘产生:

ctrl c:SIGINT  2号信号, 终止前台进程

ctrl \ :SIGQUIT 3号信号, 也是终止前台进程, 不过其action是core,有核心转储功能

指令

kill -9 pid  :向指定进程发送9号信号

由于9号信号不可被用户自定义捕捉, 即kill -9 pid一定可以成功终止指定进程, 所以常用9号信号终止进程

系统调用

kill, raise, alarm, abort均为可发送信号的系统调用接口

异常

如代码中出现野指针, 除零等操作, 

除零

若用户用signal函数自定义捕捉SIGFPE(11号, 浮点数错误,如除0)且自定义handler函数中没有退出exit,此进程会死循环(循环接收该信号,进入handler)

原因:CPU运算出错后Eflags(溢出标志位)置为1,且cpu数据随进程。每次调度该进程都保持Eflags=1,发送11信号,进入handler,不断循环

野指针

野指针也类似

MMU:memory manager unit

CR3:CR3 寄存器用于存储 页目录基址寄存器(Page Directory Base Register,PDBR)的值,它指向当前进程的页目录表(Page Directory)或页全局目录表(PGD)的位置,是进行 虚拟内存到物理内存的映射 过程中的关键寄存器。

EIP:在 x86 架构中,EIPExtended Instruction Pointer)是一个关键的寄存器,它用于存储 CPU 当前正在执行的 指令地址,即 指令指针。它是一个 32 位寄存器(在 x86 体系结构中),用于跟踪程序执行的进度。

EIP中出现0指针/野指针时,由于无权访问就会报错(发信号),同上SIGFPE,每次调度该进程都会向进程发送信号,不断循环。

signal

core & term

core & term是什么

是不同信号有着不同退出模式(指令:man 7 signal)

term:进程正常退出

core(核心转储):在term基础上生成一个core.pid文件(pid为进程实际pid)

core功能有什么作用

便于事后调试

gbd中输入指令 core-file core即可直接查看进程退出原因,便于快速发现错误。

如何从status中获取core dump & SIG值
printf("exit signal: %d, core dump: %d\n", status&0x7F, (status>>7)&1);

为什么云服务器默认关闭core功能?

云服务器会循环重启退出的进程, 这会导致core文件大量堆积,直到云服务器崩溃。

有的云服务器会去掉core的pid后缀, 也可解决这个问题,但大多数云服务器选择直接关闭自动生成core文件的功能

如何生成core文件

产生core文件两个条件:

  • 退出信号动作为core 
  • 服务器开启core功能

如何服务器开启core功能:

使用ulimit -a 查看core是否开启, ulimit -c 10240 开启core功能(即将core-file-size从0改为10240)

core dump标志

core dump在status的第八位

coredump可用于判断子进程是否生成core文件

code

#include <iostream>
#include <string>
#include <functional>
#include <vector>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>

int main()
{
    if (fork() == 0)
    {
        sleep(1);
        int a = 10;
        a /= 0;

        exit(0);
    }

    int status = 0;
    waitpid(-1, &status, 0);

    printf("exit signal: %d, core dump: %d\n", status&0x7F, (status>>7)&1); 
    return 0;
}

// void handler(int signo)
// {
//     std::cout << "get a signo: " << signo << std::endl;
//     // 我捕捉了11/8号信号,没执行默认动作哦。也没有退出进程哦!
// }

// int main()
// {
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     // signal(8, handler);
//     int a = 10;
//     a /= 0;
//     int *p = nullptr;
//     *p = 100;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;
//     std::cout << "hello world" << std::endl;

//     // alarm(1);
//     while(true);
// }

using func_t = std::function<void()>;

int gcount = 0;
std::vector<func_t> gfuncs;

// 把信号 更换 成为 硬件中断
void hanlder(int signo)
{
    for(auto &f : gfuncs)
    {
        f();
    }
    std::cout << "gcount : " << gcount << std::endl;
    alarm(1);
}

int main()
{
    gfuncs.push_back([]()
                     { std::cout << "我是一个内核刷新操作" << std::endl; });

    gfuncs.push_back([]()
                     { std::cout << "我是一个检测进程时间片的操作,如果时间片到了,我会切换进程" << std::endl; });

    gfuncs.push_back([]()
                     { std::cout << "我是一个内存管理操作,定期清理操作系统内部的内存碎片" << std::endl; });

    alarm(1); // 一次性的闹钟,超时alarm会自动被取消
    signal(SIGALRM, hanlder);

    while (true)
    {
        pause();
        std::cout << "我醒来了..." << std::endl;
        gcount++;
    }
}

// // void Handler(int signo)
// // {
// //     // 当对应的信号被触发,内核会将对应的信号编号,传递给自定义方法
// //     std::cout << "Get a signal, signal number is : " << signo << std::endl;
// // }

// // void Usage(std::string proc)
// // {
// //     std::cout << "Usage: " << proc << " signumber processid" << std::endl;
// // }

// int number = 0;

// void die(int signumber)
// {
//     printf("get a sig : %d, count : %d\n", signumber, number);
//     exit(0);
// }

// // ./mykill 9 1234
// int main(int argc, char *argv[])
// {
//     // 统计我的服务器1S可以将计数器累加多少!
//     alarm(10); // 我自己,会在1S之后收到一个SIGALRM信号

//     sleep(4);

//     int n = alarm(0); // 0:取消闹钟
//     std::cout << "n : " << n << std::endl;

//     // signal(SIGALRM, die);

//     // while(true)
//     // {
//     //     number++;
//     //     // printf("count: %d\n", number++); // IO影响了计算速度!
//     // }

//     // int cnt = 5;
//     // while(true)
//     // {
//     //     std::cout << "hahaha alive" << std::endl;
//     //     cnt--;
//     //     if(cnt<=0)
//     //         // abort();
//     //     sleep(1);
//     // }

//     // if(argc != 3)
//     // {
//     //     Usage(argv[0]);
//     //     exit(1);
//     // }

//     // int signumber = std::stoi(argv[1]);
//     // pid_t id = std::stoi(argv[2]);

//     // int n = ::kill(id, signumber);
//     // if(n < 0)
//     // {
//     //     perror("kill");
//     //     exit(2);
//     // }
//     // exit(0);

//     // signal怎么不放在循环里面?
//     // signal:如果没有产生2或者3号信号呢?Handler不被调用!
//     // for (int signo = 1; signo < 32; signo++)
//     // {
//     //     signal(signo, Handler); // 默认终止 -> 执行自定义方法:Handler
//     //     std::cout << "自定义捕捉信号: "<< signo << std::endl;
//     // }

//     // while (true)
//     // {
//     //     std::cout << "hello world" << std::endl;
//     //     sleep(1);
//     // }
// }

板书笔记

 

 

 

标签:status,core,产生,int,信号,进程,include
From: https://blog.csdn.net/li_peixiansang/article/details/143600521

相关文章

  • 基于GA-PSO-SVM算法的混沌背景下微弱信号检测matlab仿真
    1.算法运行效果图预览(完整程序运行后无水印) svm参数取值对检测性能的影响: SVM,PSO,GA-PSO-SVM的检测性能对比: 2.算法运行软件版本matlab2022a 3.部分核心程序(完整版代码包含详细中文注释和操作步骤视频,参考文献,说明文档)loadGAPSO.mat%调用四个最优的......
  • SATA系列专题之一《1.0 Physical Layer物理层OOB信号》
    文章目录前言一、SATA物理层概述二、OOB(OutofBand)信号解析三、实例解析总结前言一、SATA物理层概述说OOB之前,首先得了解一下SATA结构以及物理层的含义。SATA主要包括:应用层(ApplicationLayer), 传输层(TransportLayer),链路层(LinkLayer)、物理层(P......
  • 【Linux】进程间通信(命名管道、共享内存、消息队列、信号量)
                                 作者主页:   作者主页                           本篇博客专栏:Linux                ......
  • 【matlab版】如何估算波形信号的幅值、频率与相位
    1.幅值(A_init)幅值的估算是通过信号的最大值和最小值来计算的。具体计算方法如下:A_init=(max(signal)-min(signal))/2;max(signal):获取信号的最大值。min(signal):获取信号的最小值。(max(signal)-min(signal))/2:通过最大值和最小值的差的一半来估算幅值。这种......
  • 8. 定时器 / 信号处理
    有关定时器的详细内容,见10.定时器简而言之,web服务器需要处理定时事件,如定期检测一个客户连接的活动状态。服务器程序通常管理着众多定时事件,有效地组织这些定时事件,使其在预期的时间被触发且不影响服务器的主要逻辑,对于服务器的性能有至关重要的影响。为此,我们要将每个定......
  • Python轴承故障诊断 (17)基于TCN-CNN并行的一维故障信号识别模型
    往期精彩内容:Python-凯斯西储大学(CWRU)轴承数据解读与分类处理Pytorch-LSTM轴承故障一维信号分类(一)-CSDN博客Pytorch-CNN轴承故障一维信号分类(二)-CSDN博客Pytorch-Transformer轴承故障一维信号分类(三)-CSDN博客三十多个开源数据集|故障诊断再也不用担心数据集了!P......
  • 梁山派入门指南4——定时器使用详解,包括定时器中断、PWM产生、输入捕获测量频率
    梁山派入门指南4——定时器使用详解,包括定时器中断、PWM产生、输入捕获测量频率1.定时器概览2.基本定时器2.1基本定时器介绍2.2梁山派上的基本定时器开发2.2.1.了解梁山派上的基本定时器资源(实际上我们以及在上面了解过了)2.2.2.配置定时器2.2.3.编写定时器中断服务......
  • 数字信号处理Python示例(3)生成三相正弦信号
    文章目录前言一、三相正弦信号的表示二、生成三相正弦信号的Python代码三、三相正弦信号的图示与分析四、生成幅度不相等的三相正弦信号的Python代码五、幅度不相等的三相正弦信号的图示与分析写在后面的话前言首先给出三相正弦信号的数学表达式,并给出生成三相正弦......
  • PCB电源层布线信号
    在印刷电路板(PCB)的设计过程中,电源层通常被视为电源分配网络(PDN)的核心。电源层和接地层通常是通过平面铜层来实现的,旨在确保系统稳定性。然而,随着电路板复杂性的增加,尤其是在多层电路板中,设计师可能面临在电源层上布置信号线路的需求。虽然这种做法可以节省空间,但也带来了许......
  • 高频小信号放大器与自激
    目录Y参数等效模型 单级高频谐振小信号放大器 增益非谐振部分:对于谐振部分:要点小结通频带 品质因素 矩形系数多级高频谐振小信号放大器 增益 通频带 矩形系数 自激产生原因分析 稳定电压增益  克服自激的产生中和法失配法阻抗(又名:复......