目录
[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行为
表示进程的退出方式不需要被追踪
- 执行atexit()注册的函数
- 清理打开的文件描述符
- 向父进程发送SIGCHLD信号
- 仅传递退出状态码
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; //自动定位错误的位置