假设我想用swap(实际上是zram)终止Linux机器上的一个进程。交换区大小是 RAM 的一半。 RAM 中只有 10% 的可用空间,并且交换区也几乎已满。
该进程仅使用 2% 的 RAM,但使用了大约 90% 的交换空间。
执行软关闭 (SIGTERM) 并允许进程捕获信号并自行关闭将导致取消交换所有交换的映射,但没有足够的可用 RAM 来容纳整个进程。
因此,使用 SIGKILL 终止进程可能会更好,但我仍然担心 OOM-killer 会由于内存不足而终止其他进程,甚至整个 X 会话或 init。
那么发送终止信号是否会使内核将进程的交换部分移动到物理内存中?(我应该期待什么?它取决于内核的版本吗?)
如果是的话,这种情况该怎么办?目标是终止进程而不触及其余进程(还有其他重要进程正在运行)。
此外,当它不是一个进程而是一棵进程树并且我不能让应用程序自行终止时,如何正确杀死它?
答案1
一般来说,除非需要,否则页面不会被交换回 RAM。也就是说,只有当页面实际被某些东西访问时,该页面才会被加载回 RAM(在 MMU 中导致页面错误异常,操作系统将通过在允许访问线程继续之前将页面加载回 RAM 来处理该异常)。硬终止进程(使用 SIGKILL)不会运行该进程的任何线程,因此被终止的进程无法尝试访问其任何页面,并且这些页面不应加载到 RAM 中。
事实上,即使您不终止该进程并且它恢复运行,它仍然只会将其实际访问的页面换入(到 RAM)。此外,如果所有 RAM 已满并且需要访问不在 RAM 中的另一个页面,操作系统将选择 RAM 的其他页面进行换出(到磁盘),以便在 RAM 中为程序需要访问的页面腾出空间。只要磁盘上的交换分区中有一些空间,这种页面交换就可以无限期地继续,使所有内容保持活动状态,而不会触发 OOM 杀手。当然,如果这种情况经常发生,它确实会减慢你的机器速度,因为它大部分时间都在 RAM 和磁盘之间移动内存,而不是执行程序指令。这称为“殴打”。
答案2
关于杀死整个进程树,您可以尝试以下操作:
# in pid is saved pid of the parent process
CPIDS=`pgrep -P $pid` # gets pids of child processes
for cpid in $CPIDS ; do kill -9 $cpid ; done # first kill children
kill -9 $pid # then the parent (yeah, that sound kinda bad)