Linux信号产生

目录

[1 键盘产生](#1 键盘产生)

[2 kill指令产生](#2 kill指令产生)

[3 系统调用](#3 系统调用)

[1.1 kill](#1.1 kill)

[1.2 raise](#1.2 raise)

[1.3 abort](#1.3 abort)

[1.4 alarm](#1.4 alarm)

[4 异常](#4 异常)

[5 Core和Term](#5 Core和Term)

[5.1 Core Dump行为](#5.1 Core Dump行为)

[5.2 Term行为](#5.2 Term行为)

[5.3 通过gdb调试core](#5.3 通过gdb调试core)


1 键盘产生


  • ctrl + c( SIGINT - 2 )
  • ctrl + \( SIGQUIT - 3 )

2 kill指令产生


复制代码
kill -signal(信号) pid(进程pid)

3 系统调用


1.1 kill

(1)功能

**kill()**是Linux系统中用于向进程或进程组发送信号的核心系统调用,它是进程间通信的基础机制之一。

(2)函数原型

复制代码
#include <sys/types.h>
#include <signal.h>

int kill(pid_t pid, int sig);

(3)参数

pid参数(目标标识):

|-------|--------------------------|
| pid值 | 含义 |
| > 0 | 发送信号给指定PID的进程 |
| = 0 | 发送信号给调用进程所在进程组的所有进程 |
| = -1 | 发送信号给所有有权发送的进程(除init和自身) |
| < -1 | 发送信号给进程组ID等于 |

sig参数(信号编号):

  • 信号编号(1-64),如SIGTERM(15)、SIGKILL(9)等
  • 特殊值0:空信号,用于检查目标是否存在(不实际发送信号)

(4)返回值

  • 成功:返回0
  • 失败:返回-1,并设置errno

1.2 raise

(1)功能

raise() 是C标准库提供的用于向当前进程发送信号的函数,它实际上是kill()系统调用的简化封装。

(2)函数原型

复制代码
#include <signal.h>

int raise(int sig);

(3)参数

  • sig:要发送的信号编号(如SIGINT、SIGTERM等)

(4)返回值

  • 成功:返回0
  • 失败:返回非0值

(5)示例

复制代码
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void handler(int sig) {
    printf("Received signal %d\n", sig);
}

int main() {
    signal(SIGUSR1, handler);
    
    printf("Sending SIGUSR1 to myself\n");
    raise(SIGUSR1);  // 等同于 kill(getpid(), SIGUSR1)
    
    return 0;
}

1.3 abort

(1)功能

abort() 是C标准库提供的用于异常终止程序的函数,它会引发SIGABRT信号,默认情况下会导致进程终止并生成核心转储(core dump)。

(2)功能特性
1.信号触发

  • 发送SIGABRT信号给当前进程
  • 默认行为是终止进程并生成核心转储
    2.不可返回
  • 除非信号被捕获且信号处理函数没有返回
  • 即使信号处理函数返回,abort()仍会终止进程
    3.清理行为
  • 不会调用atexit()注册的函数
  • 不会调用对象的析构函数(C++中)

(3)函数原型

复制代码
#include <stdlib.h>

void abort(void);

(4)示例

复制代码
#include <stdlib.h>
#include <stdio.h>

int main() {
    printf("Before abort\n");
    abort();
    printf("This will never be printed\n");  // 不会执行
    return 0;
}

1.4 alarm

(1)功能

**alarm()**是用于设置一个实时定时器的系统调用,经过指定秒数后,内核会向进程发送SIGALRM信号。

(2)函数原型

复制代码
#include <unistd.h>

unsigned int alarm(unsigned int seconds);

(3)参数

  • seconds :定时器秒数
    • 如果为0,表示取消之前设置的定时器

(4)返回值

  • 返回之前定时器的剩余秒数
  • 如果之前没有设置定时器,返回0

(5)特性
1.单一定时器

  • 每个进程只能有一个alarm定时器
  • 新调用会覆盖之前的设置
    2.信号机制
  • 定时器到期后发送SIGALRM信号
  • 默认行为是终止进程
    3.精度限制
  • 以秒为单位,不适合需要高精度的场景
  • 对于更高精度需求,建议使用setitimer()timer_create()

(5)示例

复制代码
#include <iostream>
#include <signal.h>
#include <unistd.h>

void func(int signal)
{
    std::cout<<"process pid:"<<getpid()<<", catch signal:"<<signal<<std::endl;
    alarm(3); // 重复开启闹钟
}

int main()
{
    signal(14, func);
    alarm(3); // 3秒后发送SIGALRM

    while(true)
    {
        std::cout<<"process pid:"<<getpid()<<std::endl;
        sleep(1);
    }
    return 0;
}

4 异常


问:为什么在代码中 除0,野指针 会导致进程崩溃?

答;原因在于 除0,野指针 操作会被操作系统识别,然后给目标进程发送信号,进程在处理信号,默认终止了进程

(1)除0

复制代码
#include <iostream>
#include <signal.h>
#include <unistd.h>

void func(int signal)
{
    std::cout<<"process pid:"<<getpid()<<", catch signal:"<<signal<<std::endl;
    exit(0);
}

int main()
{
    signal(8, func);
    int num = 1;
    // 除0 发送 ------ SIGFPE
    int n = num / 0;

    std::cout<<"hello world"<<std::endl;
    return 0;
}

(2)野指针

复制代码
#include <iostream>
#include <signal.h>
#include <unistd.h>

void func(int signal)
{
    std::cout<<"process pid:"<<getpid()<<", catch signal:"<<signal<<std::endl;
    exit(0);
}

int main()
{
    signal(11, func);
    int* ptr = nullptr;
    // 野指针 发送 ------ SIGSEGV
    *ptr = 100;

    std::cout<<"hello world"<<std::endl;

    return 0;
}

5 Core和Term


通过 core dump 标识识别正常退出和异常退出,0 为正常退出(Term),非 0 为异常退出(Core)

5.1 Core Dump行为

(1)表示进程的退出方式需要被追踪:

1.生成core文件(需系统配置允许)

2.记录进程终止时的完整状态:

  • 内存映像
  • 寄存器值
  • 调用栈信息

3.典型文件命名:core或core.PID

注意:云服务器默认是关闭 Core file

(2)Core Dump配置

复制代码
// 查看core dump 大小
ulimit -c

// 设置core dump 大小
ulimit -c size // 设置大小

// 临时设置可写路径
sudo bash -c "echo core.%p > /proc/sys/kernel/core_pattern"

5.2 Term行为

表示进程的退出方式不需要被追踪

  1. 执行atexit()注册的函数
  2. 清理打开的文件描述符
  3. 向父进程发送SIGCHLD信号
  4. 仅传递退出状态码

5.3 通过gdb调试core

gdb/cgdb调试core指令:

复制代码
core-file core // 加载core文件,定位出错行

(gdb) core-file core

[New LWP 344536]
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x000063192a6c125d in main () at process.cpp:16
16	    *ptr = 100; //自动定位错误的位置
相关推荐
A.A呐1 小时前
【Linux第九章】程序地址空间
linux
打码人的日常分享2 小时前
数据中心信息中心信息科管理制度
大数据·运维·网络·云计算·制造
vortex53 小时前
Linux 终端优化:Alacritty + Zellij 配置指南
linux·kali·终端模拟器
juncaixingchilove3 小时前
Linux轻量级浏览器
运维·服务器
码农编程录3 小时前
【notes11】并发/IO/内存
linux
cuijiecheng20183 小时前
Linux下MyIpAdd库的使用
linux·运维·服务器
一路往蓝-Anbo4 小时前
第 12 章:Linux 侧 RPMsg 用户态驱动与数据接口
linux·运维·服务器·stm32·单片机·嵌入式硬件·网络协议
乔碧萝成都分萝5 小时前
二十六、IIO子系统 + SPI子系统 + ICM20608
linux·驱动开发·嵌入式
海盗猫鸥5 小时前
Linux权限详解
linux·c语言