信号、Ctrl 组合键与进程状态

1:什么是信号?进程收到信号会怎么处理?

考察点:信号机制 · 异步中断

text 复制代码
信号(signal)= 内核或进程发给另一个进程的"异步通知",本质是软件中断。

进程对信号有三种处理方式:
  1) 默认动作(终止 / 暂停 / 继续 / 忽略 / core dump)
  2) 捕获(自己写 handler 处理,比如"收到 TERM 先把缓存落盘再退出")
  3) 忽略(显式忽略;但 SIGKILL、SIGSTOP 无法被捕获或忽略)
bash 复制代码
kill -l            # 列出所有信号编号和名字(面试前扫一眼)
kill -l 15         # 15 → TERM

2:kill -15 / kill -9 / kill -2 有什么区别?

kill 默认发 15(SIGTERM) ,是可捕获的优雅退出,进程可以落盘、关连接;kill -2 是 SIGINT ,等同 Ctrl+C,也是优雅中断;kill -9 是 SIGKILL,不可捕获不可忽略,内核直接杀,进程没有任何清理机会。

所以顺序是先 15、等几秒不退出,再上 9。


3:Ctrl+C、Ctrl+Z、Ctrl+D 有什么区别?

考察点 :终端控制 · Ctrl+D 不是信号(这是本题的关键)

这题的差距就在:能说出 Ctrl+D 不是信号,面试官立刻觉得你懂。

按键 发信号吗 信号 / 效果 进程状态变化 能恢复吗
Ctrl+C 是 SIGINT(2) 前台进程终止(可被捕获改写行为) 不能
Ctrl+Z 是 SIGTSTP(20) 前台进程暂停并放到后台 能,fg / bg 恢复
Ctrl+D 不是信号 表示输入结束(EOF) :read() 返回 0 不影响进程本身 ---
Ctrl+反斜杠 是 SIGQUIT(3) 终止 + core dump 不能
Ctrl+S / Ctrl+Q 不是 终端流控 暂停 / 恢复屏幕输出(程序还在跑) 能

Ctrl+D 要说清楚的三层:

text 复制代码
1) 它不是信号!它是终端把"输入结束"告诉程序(read() 返回 0,即 EOF)。
2) 在空行按 Ctrl+D → shell 读到 EOF → shell 退出(logout)。
3) 有输入时按 Ctrl+D → 把这行内容先交给程序(不结束输入),再按一次才结束。
   例:cat 里按 Ctrl+D 结束输入;python 交互里按 Ctrl+D 退出解释器。

对比记忆 :Ctrl+C 是「我不想让你跑了」,Ctrl+Z 是「你先歇会儿」,Ctrl+D 是「我说完了」。


4:进程有哪几种状态?D 状态是什么意思?

考察点 :ps 的 STAT 列 · 卡 IO 的判断

bash 复制代码
ps aux            # 看 STAT 列
ps -eo pid,stat,comm | grep -E '^ *[0-9]+ (D|Z|T)'
状态 含义 常见原因
R Running / Runnable(在跑或在等 CPU) 正常
S Interruptible sleep(可中断睡眠) 绝大多数进程的常态:等 IO、等事件
D Uninterruptible sleep(不可中断睡眠) 卡在磁盘/NFS/驱动的 IO 上,不响应信号
T Stopped(暂停) 收到 SIGSTOP / Ctrl+Z;被调试器停住
Z Zombie(僵尸) 子进程已退出,父进程没 wait 回收
I Idle 内核线程 基本不用管
text 复制代码
STAT 里的后缀字母:s = 会话首进程,l = 多线程,+ = 前台进程组,< = 高优先级,N = 低优先级

面试官最爱顺着问 :「你刚才说 Ctrl+Z 是挂起 ------ 那挂起之后进程是什么状态?」→ T 。「怎么恢复?」→ fg %1 / bg %1,或 kill -CONT <pid>


5:kill -9 不是强制杀吗?有没有杀不掉的情况?

考察点:D 状态 · 内核不可中断等待 · 僵尸的本质

这题能答出来,说明你不只会用命令。

情况 原因 怎么处理
进程处于 D 状态 卡在内核的 IO 等待里,信号要等系统调用返回才能处理,而 -9 也不能打断已经启动的不可中断等待 等 IO 超时恢复;查是哪块盘/NFS 慢(cat /proc/<pid>/stack、dmesg),严重时只能重启
进程已经是僵尸 Z 它已经死了,只剩进程表项,信号无处可发 杀父进程,让它被 init/PID 1 收养并回收
是内核线程 不是用户态进程,信号不适用 别动
权限不足 非 root 杀别人的进程 → Operation not permitted 用 root 或 sudo
容器里的 PID 1 容器内 1 号进程对未注册的信号会忽略(内核为此有特殊处理) 用 docker stop(先 TERM 后 KILL)或修容器入口

一句话答法 :「-9 杀不掉通常有三种:D 状态 卡在不可中断 IO(要等 IO 恢复)、僵尸 Z (要杀父进程)、权限不足或容器 PID 1。」


6:systemctl stop 背后做了什么?

考察点:优雅停止 · TimeoutStopSec

text 复制代码
systemctl stop nginx
  → systemd 给主进程发 SIGTERM(默认 KillSignal)
  → 等 TimeoutStopSec(默认 90 秒)让进程自己退
  → 还没退就补一个 SIGKILL

所以「为什么推荐 15 而不是 9」在这里得到闭环 :15 给应用时间做收尾,9 是最后的兜底。


7:为什么关掉终端,程序就没了?怎么让它不受影响?

考察点:SIGHUP · 会话与终端 · 四种脱离方式

text 复制代码
关闭终端 → 内核给该终端的前台进程组发 SIGHUP → 程序默认被终止

四种免疫方式(按推荐度排):

bash 复制代码
# 1) 生产推荐:写成 systemd 服务(由 PID 1 托管,和终端无关,还能开机自启)
systemctl enable --now myservice

# 2) nohup:忽略 SIGHUP,输出重定向到 nohup.out
nohup ./run.sh &

# 3) disown:先后台,再从 shell 的任务表里摘掉
./run.sh & disown

# 4) setsid:新会话,彻底脱离终端
setsid ./run.sh
方式 一句话
nohup 让进程忽略 SIGHUP(关终端不死)
disown 把任务从 shell 的任务表里摘掉
setsid 新建会话(session),彻底脱离控制终端
systemd 最稳:PID 1 托管、可开机自启、可自动重启、日志进 journald

面试加分 :「临时调试用 nohup 就够;但生产上我会写成 systemd 服务 ,这样能开机自启、能设 Restart=on-failure、日志也统一进 journalctl。」

相关推荐
大能嘚吧嘚1 小时前
Debian13系统安装
linux
qetfw1 小时前
grep 文本筛选:匹配、反选与退出状态验证
linux·shell
开开心心就好1 小时前
文件被占用删不掉?解锁工具强制删除
java·运维·服务器·开发语言·前端·pdf·ocr
就像楞次定律2 小时前
【Linux 学习记之一】日常生产力工具与终端流的高效闭环实践(1)
linux
奔跑的架构师2 小时前
[A-51]ARMv9/v8-SCMI系统架构
linux·arm开发·架构·系统架构·arm
小超人诞生日记2 小时前
Linux 进程优先级
linux·运维·服务器
weixin_460443562 小时前
Java+Linux私有化训考平台:服务、数据库与终端部署结构解析
java·linux·数据库·私有化部署·企业培训考试系统·企业考试系统
科技象限2 小时前
数据防泄漏系统:文件是怎么溜出门的,就该怎么堵
运维·网络·网络安全·安企神
cpolar技术支持2 小时前
端口被谁占了、这台机上开了哪些监听?本机起一个端口占用只读清单,cpolar 给异地同事远程看谁在监听
运维·python·内网穿透·cpolar·端口占用