Linux系统篇32——信号(四):kill -9 是最后手段?内核说:它连“现场“都不给你留

发布时间:2026/9/16 8:44:37

Linux系统篇32——信号(四):kill -9 是最后手段?内核说:它连“现场“都不给你留 本文收录于「流浪」的系列专栏系列专栏直达链接 Linux系统进入专栏 →⚙️ C进入专栏 → 数据结构与算法进入专栏 → Python进入专栏 → LangChain LangGraph进入专栏 →️ MySQL 数据库进入专栏 → Git 工具进入专栏 → 计算机网络进入专栏 → AI进入专栏 → 大厂面试、八股进入专栏 → 学习筑基专栏进入专栏 → 博客主页流浪 原创首发于 CSDN前言篇31 把被屏蔽的信号去哪了讲透了——它一直挂在 pending 位图里解除屏蔽才递达而且普通信号连发会丢。但生命周期还有半截没走完信号真递达之后进程是怎么结束的为什么有的信号退出时会吐出一个 core 文件有的却什么都不留凭什么说 kill -9 是最后手段、谁也拦不住本篇把这三个问号一次填平Term 与 Core 两种归宿、core dump 的完整实战流程、以及 9 号和 19 号为什么能绕过你设的一切防线。一、终止信号的两种归宿Term vs Core1.1 Term直接退出进程直接终止不留任何额外文件干干净净地消失。1.2 Core先把现场写进文件再退出进程异常退出时会先把自己在内存中的核心数据转储到磁盘形成一个文件然后才退出。这个文件就是 core 文件本质是进程临死前留下的一份现场快照。1.3 哪些信号会产 coreman 7 signal 实测按man 7 signal标准信号表默认动作是Core的一共10 个SIGABRTabort 触发、SIGBUS总线错误、SIGFPE算术异常如除零、SIGILL非法指令、SIGQUIT终端退出、SIGSEGV非法内存访问段错误、SIGSYS错误系统调用、SIGTRAP断点陷阱、SIGXCPUCPU 时间超限、SIGXFSZ文件大小超限。两点补充说明SIGIOT是SIGABRT的同义名、SIGUNUSED是SIGSYS的同义名不算独立信号。反直觉点SIGKILL(9)的默认动作是Term不是 Core——被kill -9杀掉的进程不会留下 core 文件。想留现场别用 9 号。1.4 core 文件里到底写了什么它不是随便 dump 一堆内存核心是三类内容寄存器上下文包括程序计数器PC和信号相关信息——这是能定位到死在哪一行的关键。进程内存中的核心数据把进程的内存映射转储到磁盘。信号相关信息是哪个信号、什么原因导致的终止。1.5 为什么要 core事后调试core 文件的全部价值就一句话直接帮我们定位到出错行。程序半夜崩了你不可能守在旁边有了 core 文件第二天照样能把当时的现场完整复现出来这叫事后调试post-mortem debugging。【衔接篇30 §6.1】篇30 讲过abort()为什么保证终止——它发的 SIGABRT 默认动作正是终止 core所以 abort 一定会留下 core 文件前提是 core dump 功能是打开的见下一节。1.6 父进程怎么知道孩子是怎么死的子进程被信号干掉后父进程waitpid()拿到的那个status不是随便一个整数它编码了死因。三个宏挨着用int status; waitpid(pid, status, 0); if (WIFEXITED(status)) // 正常退出exit / 从 main return printf(exit code %d\n, WEXITSTATUS(status)); else if (WIFSIGNALED(status)) { // 被信号杀死 printf(killed by signal %d\n, WTERMSIG(status)); if (WCOREDUMP(status)) // 仅在 WIFSIGNALED 为真时才能用 printf(并且留下了 core 文件\n); }按man 2 waitpidman-pages 6.19原文WIFSIGNALED在子进程被信号终止时返回真WTERMSIG返回导致终止的信号编号该宏只在 WIFSIGNALED 返回真时使用WCOREDUMP返回子进程是否产出了 core dump同样只在 WIFSIGNALED 为真时使用手册中该宏标注为 POSIX.1-2024。这一组和本篇主题咬得很紧WCOREDUMP为真就说明这个信号的默认动作属于 Core 那一类1.3 那 10 个之一而且 core dump 功能是开着的——比你跑到目录里去找 core 文件可靠得多。同样的编码规则在 shell 里也看得到echo $?打出139就是128 11表示进程被 11 号 SIGSEGV 干掉了bash(1) 对命令被信号 N 杀死的退出状态约定。1.7 回头重读篇16 那张 status 位图core 就记在第 8 位回顾 wait/waitpid 的 status 位图正常终止高 8 位存放退出码低 7 位全 0信号杀死低 7 位存放终止信号第 8 位是 core dump 标记低 7 位WTERMSIG(status)保存终止信号 (1~31)低 7 位全 0 代表进程不是被信号终止此时高 8 位的退出码才有效。第 8 位core dump 标志。仅当子进程触发 Core 类信号、并且成功生成 core 文件时置 1WCOREDUMP就是读取这一位。宏必须配合判断WIFSIGNALED使用status 有两套解析逻辑。进程正常终止就读高 8 位被信号杀死就读低 7 位。不做分支判断会把正常退出误判为死于 0 号信号。glibc 源码位掩码定义bits/waitstatus.h#define __WEXITSTATUS(status) (((status) 0xff00) 8) //高8位退出码 #define __WTERMSIG(status) ((status) 0x7f) //低7位终止信号 #define __WCOREDUMP(status) ((status) __WCOREFLAG) //第8位core标记 #define __WCOREFLAG 0x80代码演示int main() { pid_t pidfork(); if(pid0) { std::cout我是一个子进程getpid()我即将退出std::endl; exit(1); } int statu; waitpid(pid,statu,0); printf(我是父进程收到了子进程的退出信息signal: %d, exit code: %d, core dump: %d\n, (statu 0x7F), (statu 8) 0xFF, (statu 7) 0x1); return 0; }二、core dump 实战怎么开、怎么用、为什么默认关2.1 先看看当前开没开ulimit -a在输出里找core file size这一项。默认值通常是 0——意思是允许生成的 core 文件大小为 0也就是等于关闭。所以很多人踩过这个坑程序明明段错误崩了却死活找不到 core 文件。2.2 怎么打开ulimit -c 4096 # 放开到 4096 个 block ulimit -c unlimited # 或者干脆不限制大小注意ulimit是shell 内建命令只对当前 shell 及其子进程生效重开终端就恢复默认。要永久生效得写进配置文件。再次被core信号终止后 就会有core文件了2.3 core 文件的命名规则早期 / 简单配置就叫core生成在当前工作目录。RHEL 7 及多数现代发行版默认core.PID带上进程号避免多个进程互相覆盖。2.4 想自己定路径和名字core_patterncore.PID只是发行版给的默认值真正说了算的是/proc/sys/kernel/core_pattern。按man 5 core该文件自 Linux 2.6 与 2.4.21 起默认值是 core可以写成一个模板模板里的%占位符会被替换占位符含义依据 man 5 core%p被 dump 进程的 PID%e进程/线程的 comm 值通常就是可执行文件名不带路径最长截到 15 字符%E可执行文件路径其中的 / 替换成 !自 Linux 3.0%s导致 dump 的信号编号%tdump 发生时间Epoch 秒数%u / %g被 dump 进程的实际 UID / GID%h主机名比如写成/var/coredump/core-%e-%p-%t所有 core 就统一落到/var/coredump下还自带进程名、PID 和时间戳。注意两点模板里可以带 /会被当成目录分隔符生成的文件名最长128 字节Linux 2.6.19 之前是 64 字节。还有一个更狠的用法模板以|开头时自 Linux 2.6.19core 不再落成文件而是作为标准输入喂给一个用户态程序——systemd-coredump、abrt 这些就是靠它接管 core 的。手册给了几条硬约束程序必须用绝对路径且紧跟在|后面该程序以 root 身份运行并且走管道的 core dump 不受 RLIMIT_CORE 限制——也就是说ulimit -c 0拦不住它。这也解释了为什么有些机器上你明明没开 core却还是能在 systemd 的日志里翻到崩溃记录。如何配置让core形成在当前目录下# 1. 停止apport sudo service apport stop # 2. core文件输出到当前目录 sudo sysctl -w kernel.core_patterncore.%p # 3. 检查配置 cat /proc/sys/kernel/core_pattern ulimit -c顺带把 2.3 那个core.PID的来龙去脉补完/proc/sys/kernel/core_uses_pid非 0 时自 Linux 2.4若core_pattern里没有%p内核就会在文件名后面追加上.PID。2.5 怎么用它调试gdb 可执行文件 core.PID # 一步到位 # 或者先起 gdb 再加载 gdb ./a.out (gdb) core-file core.PID # 加载 core 文件加载之后 gdb 会直接告诉你进程是被哪个信号干掉的、死在哪一行、当时的调用栈长什么样。这就是 1.5 说的定位到出错行。进去以后最常用的几条命令(gdb) bt # 打调用栈直接看死在哪个函数调用链上 (gdb) frame 0 # 切到栈顶那一帧出事的那个函数 (gdb) list # 列出当前行附近的源码 (gdb) print 变量名 # 看崩溃那一刻这个变量的值 (gdb) info registers # 看寄存器x86-64 上重点看 rip就是 PC其中bt是性价比最高的一条——core 调试里绝大多数场景靠它就能定位到出错的函数和行号后面几条是用来回答为什么会错的。还有一个前提别漏编译时必须带-g。没调试信息的二进制加载 core只能看到地址和函数名看不到行号——这也是很多线上程序崩了却调不出行号的原因发布版本把调试信息 strip 掉了。2.6 云服务器上为什么默认把它关掉两个原因缺一不可磁盘core 文件可能非常大它装的是整个进程的内存镜像。线上服务一崩就吐几个 G几个来回就能把磁盘写满进而拖垮同一台机器上的其他服务。安全core 里是进程内存的完整快照可能包含密码、密钥、用户数据等敏感信息。文件一旦落到磁盘就多了一条泄露通道。对应的控制位置/etc/security/limits.confPAM 限制和 systemd 的DefaultLimitCORE0。想在生产环境开 core dump通常是定向开、限额开并且放在受控目录里。三、终极手段SIGKILL / SIGSTOP 为什么拦不住3.1 一个灵魂问题如果一个病毒进程启动后第一件事就是把所有信号全部屏蔽那我们不就拿它没辙了3.2 答案9 号和 19 号不受屏蔽影响不会没辙。man 7 signal里写得明明白白SIGKILL 和 SIGSTOP不可被捕获、不可被阻塞、不可被忽略原文cannot be caught, blocked, or ignored。大家可以执行下面代码 尝试先不加if判断 看看会有什么效果void hander(int sig) { std::cout收到了一个信号 sig 我可以被捕捉 std::endl; } int main() { for(int i0;i32;i) { signal(i,hander); } for(int i0;i32;i) { sleep(1); if(i9||i19) continue; raise(i); } return 0; }所以不管你把 blocked 位图填满成什么样kill -9 照样能把它送走。3.3 底层原因内核不信任你的 blocked 集【衔接篇30 §6.5】篇30 已经给过这个结论并做过9 号杀不掉后台进程的误区澄清本篇补的是为什么内核在投递信号时对这两个信号直接绕过用户 blocked 位图的检查走强制投递路径。sigprocmask能改你的 blocked 位图不假但内核在 9/19 上根本不查这张表——你改了也白改。这是操作系统刻意留的一道后门设计必须保证管理员永远握有终止失控进程的最后手段否则一个恶意进程只要屏蔽全部信号就能永久霸占 CPU整个系统就失控了。3.4 完整名单只有两个真正拦不住的只有SIGKILL(9)和SIGSTOP(19)这两个其余所有信号都可以被屏蔽或捕获。这也是为什么 9 号被称为最后手段——它是唯一保证生效的终止方式代价见 1.3它不产 core杀完不留现场。3.5 什么时候 kill -9 也杀不掉先把话说准9 号拦不住指的是进程没法通过屏蔽、捕获、忽略来躲不等于它能在任何状态下立刻生效。下面两种情况你敲kill -9就是看不到进程消失僵尸进程Z 状态它已经死了只是父进程还没wait()给它收尸内核留着它的 task_struct 只是为了给父进程一个交代。你没法杀死一个已经死的进程——正确做法是处理它的父进程结束或修复父进程的 wait 逻辑让它被 init/systemd 收养后回收。不可中断睡眠D 状态进程卡在内核态等某个 IO典型是坏掉的 NFS 挂载、故障磁盘。这个状态存在的意义就是信号打不断否则数据一致性没法保证。信号照样被记进 pending但要等它从 D 状态里出来才会被处理——所以 9 号对它不是无效是被延后。怎么判断ps -o pid,stat,comm -p PIDSTAT 列看到Z是僵尸看到D是卡在内核态 IO。所以运维排查杀不掉的进程第一步永远是先看 STAT 那一列而不是反复加 9。进阶补充容易答漏的一层严格来说D 状态一定杀不死也不绝对。内核还有一种TASK_KILLABLE睡眠它只认致命信号也就是 SIGKILLps 里同样显示成D。所以准确说法是看它卡在哪种等待上——普通不可中断等待要等 IO 完成可杀等待才会被 9 号提前唤醒。四、小结两句话收住本篇Term 与 Core 是信号递达后进程的两种归宿Term 干干净净退出、什么也不留Core 会先把寄存器上下文含 PC、进程内存中的核心数据、信号相关信息落盘成 core 文件再退出这是事后调试的黑匣子。但它默认是关的——ulimit -c为 0 等于关闭云上更因为磁盘和安全两重考虑默认不吐真要用/proc/sys/kernel/core_pattern才是定路径和名字的总开关。SIGKILL(9) 与 SIGSTOP(19) 是内核刻意留的后门投递时直接绕过用户 blocked 位图的检查sigprocmask 改了也白改保证管理员永远握有终止失控进程的最后手段。代价是 9 号默认动作是 Term 不是 Core杀完不留现场而且它只对活着且在被调度的进程有效僵尸和 D 状态这两类它照样带不走。【四篇串起来看】篇29 讲信号是什么、从哪来、发给谁 → 篇30 讲怎么存位图、怎么发只有 OS 能改、怎么收handler 三选一 → 篇31 讲被屏蔽时去哪了、会不会丢 → 本篇讲递达后进程怎么死、什么信号拦不住。四篇同属一条主线对照着看最清楚。五、面试官爱问带答案5.1 core 文件里记录了什么为什么能定位到出错行答core 文件里主要是三类——寄存器上下文含 PC、进程内存中的核心数据、信号相关信息。因为保存了PC 和调用栈gdb 加载后能直接还原死在哪一行这就是事后调试的价值。5.2 程序明明崩了为什么看不到 core 文件答最常见的原因是 core dump 功能没开——ulimit -c显示core file size为 0等于关闭。用ulimit -c 4096或unlimited打开即可另外还要注意 ulimit 只对当前 shell 及子进程生效以及 core 生成路径是否有写权限。5.3 云服务器上为什么默认关闭 core dump答两个原因。一是磁盘core 文件是进程内存的完整镜像可能非常大频繁崩溃会写满磁盘进而影响同机其他服务二是安全内存快照里可能含有密码、密钥、用户数据等敏感信息落盘就多一条泄露通道。5.4 SIGKILL 为什么拦不住内核是怎么做到的答内核对 SIGKILL(9) 和 SIGSTOP(19)直接绕过用户 blocked 位图的检查做强制投递——sigprocmask改得了 blocked 位图但内核在这两个信号上根本不查这张表。这是 OS 刻意保留的后门保证管理员永远有终止失控进程的最后手段。真正拦不住的就这两个信号。5.5 core 文件的名字和路径由什么决定答由/proc/sys/kernel/core_pattern决定自 Linux 2.6 与 2.4.21默认值 core。它支持%p(PID)、%e(进程名)、%t(时间)、%s(信号号) 等占位符也允许带/指定目录core.PID这种形态是core_uses_pid非 0 时的追加行为。若模板以|开头自 Linux 2.6.19core 会作为标准输入交给用户态程序处理且不受 RLIMIT_CORE 限制。5.6 kill -9 也有杀不掉的时候吗答有。9 号拦不住是指进程没法屏蔽/捕获它不代表任何状态下都立刻生效。僵尸进程Z已经死了只是父进程没收尸杀它没意义得处理父进程不可中断睡眠D卡在内核态 IO 上信号只能先记在 pending 里等它出来属于延后而非无效。排查时先看ps的 STAT 列。遇到不一样的结果或者没看懂的点评论区直接说。也欢迎把本篇和篇29信号一、篇30信号二、篇31信号三串起来复习——四篇是同一条主线拆成的。
延伸阅读

更多相关文章

2026/9/16 8:44:37

【xilem0.4基础语法学与练】第56课 四步通关80%核心语法

前言 学习 Xilem 0.4 无需啃完海量官方示例,它的高频实用语法高度集中。 只要按顺序跑通四步:最简 Counter 状态流 → OneOf 条件渲染 → 动态列表渲染 → Lens 子组件拆分,就能直接覆盖 Xilem0.4 日常开发 80% 以上核心语法。 这四步是 Xile…

2026/9/16 8:44:37

【AI 智能体】Windows 环境 Hermes Agent(爱马仕)安装详细过程

目录 一、前言 二、Hermes Agent 介绍 2.1 Hermes 是什么 2.2与普通AI聊天 工具区别 2.3 Hermes 核心功能 2.4 哪些人适合使用Hermes 三、Hermes Agent 安装详细过程 3.1 步骤一安装WSL环境 3.1.1 检查WSL状态 3.1.2 安装Ubuntu发行版 3.2 安装Python 环境 3.2.1 进…

2026/9/16 8:39:37

PLC编程培训与现场调试差在哪?从学完到会干活的实战路径

我接触过不少PLC培训班出来的学员,也带过刚入行的新人。最常听到的一句话是:“老师,程序我都能看懂,指令也都会用,可到了现场就是不知道从哪里下手。”这根本不是个例,而是培训模式下的一种普遍困境。你花了…

2026/9/16 9:29:48

静态网页设计期末作业95分攻略:从源码规范到交互实现

简介:这套基于原生 HTML、CSS、JavaScript 编写的前端静态网页大作业源码,精准面向高校网页设计课程期末作业场景,适合正在筹备大学生静态网页设计项目、需要高质量参考方案的学生。压缩包共 31 个文件,大小约 30.28MB&#xff0c…

2026/9/16 9:29:48

Agent技能工程化:用Nx+TypeScript构建可治理的技能契约体系

1. “agent-skills”不是库名,而是工程级能力抽象层的设计起点你第一次在 GitHub 或内部项目里看到agent-skills这个仓库名时,大概率会下意识认为:这是个封装了“AI Agent 常用工具函数”的 npm 包——比如调用天气 API、查数据库、发邮件、读…

2026/9/16 9:29:48

Windows自带三招查看电脑配置和显卡信息,不用装任何软件

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/16 9:29:48

不占CPU的GPIO高速采集:K60上PIT触发eDMA完整指南

简介:针对NXP Kinetis K60微控制器的GPIO与DMA驱动开发,这份压缩包给出了基于IAR环境的完整参考工程,面向嵌入式底层开发者与备赛学生,用于解决外设驱动配置繁琐、数据搬运占用CPU等问题。工程内附C源码与头文件,可学习…

2026/9/16 9:24:47

分布式能源系统选址定容的双层优化Matlab实现

1. 项目背景与核心价值分布式能源系统正在重塑现代电网的格局。作为一名在电力系统优化领域摸爬滚打多年的工程师,我亲眼见证了光伏储能组合如何从实验室走向商业化应用。这个项目要解决的痛点很明确:当大量分布式电源接入配电网时,如何科学地…

2026/9/15 4:54:30

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/16 0:04:09

PHP源码部署实战:从环境配置到运行情侣游戏全攻略

简介:这是一套面向情侣互动场景的PHP完整源码,集成情侣飞行棋、真心话大冒险、情趣骰子等玩法,并内置完整分销制度,可自定义多种返佣比例,源码完全开源无加密,支持微信无感自动授权登录与第三方授权&#x…

2026/9/15 14:22:53

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/15 21:31:11

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/15 11:42:23

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码