Kill 一个进程的时候都发生了那些事情,从父子进程角度讲
1. 信号发送与接收
当你执行 kill <PID>
时,操作系统内核会向指定的进程(通常是子进程)发送 SIGTERM
信号
- 如果目标进程是子进程:父进程并没有直接参与这个过程。信号是由内核发送给目标进程的,由内核负责后续的调度和处理
- 如果目标进程是父进程:同样,信号由内核直接发送。但父进程的死亡会对其子进程产生连锁反应
2. 进程对信号的响应
这是最关键的一步,也是 SIGTERM
和 SIGKILL
最大的区别所在
- 接收
SIGTERM
(友好终止):- 这是一个“软性”的终止请求,目标进程可以捕获(handle)或忽略(ignore)这个信号
- 如果目标进程有信号处理程序,它会执行相应的清理工作,例如:
- 释放占用的内存、文件描述符等资源
- 保存当前的工作状态
- 优雅地关闭网络连接
- 清理完成后,进程会正常退出
- 父子进程关系:如果被
kill
的是父进程,并且父进程捕获了SIGTERM
并执行了清理,它可能会在退出前向它的子进程发送信号(例如SIGTERM
),或者等待子进程先退出。但如果父进程直接退出,其子进程会变成孤儿进程,被init
进程收养
- 接收
SIGKILL
(强制终止):- 这是一个“硬性”的终止请求,目标进程无法捕获、忽略或阻止这个信号
- 操作系统内核会直接终止这个进程,不会给它任何机会执行清理工作
- 这种方式非常粗暴,可能导致数据丢失、资源泄露(例如,没有关闭的文件、没有释放的锁),所以通常不建议作为首选
- 父子进程关系:
- 如果被
kill -9
的是子进程,它会立即被内核终止。子进程会进入僵尸状态,其父进程需要调用wait()
来收集它的退出状态,否则它会一直占用一个 PID - 如果被
kill -9
的是父进程,父进程会立即被内核强制终止。其所有子进程都会立刻变成孤儿进程,并被init
进程(PID 1)收养。init
进程会负责等待它们终止,并清理它们的僵尸状态,避免系统资源泄露