可以在Linux中暂时冻结进程吗?


53

我想知道是否有一种方法可以在一定时间内冻结任何进程?

我的意思是:一个应用程序(可能以root身份运行)是否可以暂停另一个已经运行的进程(任何进程,包括GUI和命令行)的执行,然后再恢复运行?换句话说,我不希望Linux调度程序在一定时间内调度某些进程。

Answers:


81

这里

两个信号可以挂起进程的执行。一种是“优雅”,一种是“有力”。

“优美”的是SIGTSTP,其目的是“很好地”询问该过程(如果感觉合适),请中止执行,直到收到为止SIGCONT。在的情况下SIGTSTP,该进程可以忽略SIGTSTP并继续执行,因此需要与旨在处理SIGTSTP的程序进行合作。

“强制”是SIGSTOP,其目的是挂起与该进程关联的所有用户空间线程。忽略流程SIGSTOP就像忽略它一样是不可能的SIGKILL(后者会强行杀死流程)。

要发送任意的信号,包括任何这里提到的那些,你可以使用程序,如killkillallpkill; 或使用系统调用kill(2)。有关与平台/体系结构/版本有关的详细信息和上述内容的勘误,请参见操作系统的手册。请注意,所有这些命令和系统调用中的“ kill”一词都是错误的误称。这些命令并非专门用于终止进程。他们可以通过发送某些信号做到这一点;但是信号也可以用于终止进程以外的功能。例如,SIGSTOP仅暂停该过程,而这只是可以通过这种方式发送的多个信号之一。

要添加的自动恢复过程后的一段时间已经过去一个条件,你将需要使用某种形式的剩余,并设定一个计时器,以唤醒监控过程,然后又调用监控过程的kill(2)一次发送SIGCONT信号到停止的进程,以请求内核恢复执行。请注意,Linux有几种计时机制,其准确性和精确度各不相同。此外,如果您的系统非常繁忙,则可能要等到其计时器到期后才能唤醒监视过程,因此唤醒时间可能会延迟。

如果你依赖于挂起的进程的中止和恢复的非常准确的精度,您可能需要通过实时权限运行监控程序(见本手册页sched_setscheduler(2)有关建立用户进程的实时信息)。您还可以将高分辨率计时器(Linux内核的一项功能(仅当您的硬件提供对它们的支持时才可用))与实时调度结合使用,以获得非常精确的亚毫秒级精度,然后唤醒并发送信号以非常快速地恢复受监视的过程。

您没有指出愿意使用哪些技术来实现此目的。尽管您将无法以这种方式获得非常精细的时序,但至少需要至少bash脚本。这是一个bash“脚本”(未经测试,请小心),它只是查询概念的证明。如果需要精确的计时,则可能必须使用C / C ++或另一种本地语言编写程序,并使用实时调度和hrtimers。

#!/bin/bash
#This is the process you want to suspend.
screen -mdS child bash -c "cat /dev/urandom | base64"
#This is the process ID of the child process
THEPID=$(screen -list | grep child | cut -f1 -d'.' | sed 's/\W//g')
#Send SIGSTOP to the child process.
kill -SIGSTOP ${THEPID}
#Now it is suspended. This process will sleep for 10 seconds asynchronously, then resume the process.
screen -mdS monitor bash -c "sleep 10; kill -SIGCONT ${THEPID}"

请注意,脚本将结束并且控制脚本将终止,但是由于screen控制了监视进程,它将继续在后台运行10秒钟(基于传递给的参数sleep),然后唤醒并继续执行子进程。但这将在控制脚本结束后很长时间。如果要同步等待时间过去,则只需省略对的第二个调用,screen并对睡眠进行硬编码并杀死到控制脚本中即可。

您可以通过运行以下命令来测试该进程是否实际上已挂起

screen -rS child

启动此脚本后。您不会在控制台上看到任何内容。然后,计时器到期(10秒)后,它将以base64数据(0-9和AF中的随机字符)淹没您的屏幕。按Ctrl + C退出。


非常好的非常完整的答案,包括PoC bash片段。真好!
fgysin

如果某个进程像TCP连接一样在网络会话的中间冻结,那么在继续进行下去时,该网络会话可能会损坏或丢失吗?是否有为此定义的行为?
CMCDragonkai '16

@cmcdragonkai因为在未运行的已停止进程中无法读取或写入任何fd,但内核会一直传输字节,直到其缓冲区在TCP会话中已满为止,即内核空间与用户空间之间不会进行任何传输。冻结过程有所不同检查https://www.kernel.org/doc/Documentation/power/freezing-of-tasks.txt
Nizam Mohamed

我发现将进程恢复到前台后,TCP连接可以继续(超时是特定于应用程序的,既有TCP keepalive,也有应用程序级keepalive)。冻结过程似乎意味着计算机处于休眠或睡眠模式时。那正确吗?
CMCDragonkai '17

该脚本对非合作代码无效
ceremcem

14

是的,您可以通过向进程发送STOP信号来挂起它,然后继续发送CONT来做到这一点。

用法:

kill -STOP <pid>

kill -CONT <pid>

11

如果您对“冻结”的定义适当松散,则可以签出该renice命令。

Renice允许您更改正在运行的进程的调度优先级。

正常过程的nice值是0。增加nice值会使过程更好,例如“为什么不先走”。降低美观值会使过程变得不太美观,例如“走开,我急着走”。好的值范围是-20到19。

任何人都可以使自己的流程变得更好。只有root可以使进程变得不太友好或更改其他用户进程的友好。

如果将进程的值设置为19,则只有在系统上没有其他条件时,它才会运行。

这是在我的本地linux机器上运行的示例。

使用ps -l并查看NI列以查看流程的价值。

-> ps -l
FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD
0 S 29190 402 31146 0 75 0-16547等待pts / 0 bash
0 T 29190 1105 402 0 75 0-23980完成pts / 0 vim
0 R 29190 794 402 0 76 0-15874-pts / 0 ps

运行renice +10在Vim进程使其以较低的优先级运行。

->蕾妮丝+10 -p 1105
1105:旧优先级0,新优先级10

-> ps -l
FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD
0 S 29190 402 31146 0 76 0-16547等待pts / 0 bash
0 T 29190 1105 402 0 95 10-23980完成pts / 0 vim
0 R 29190 1998 402 0 78 0-15874-pts / 0 ps

假设您可以将“冻结”扩展为“不打扰系统上的其他任何人”,则可以编写如下脚本:

renice 20 -p <感兴趣的pid>
睡眠<一定时间>
renice 0 -p <感兴趣的pid>

(请记住以root身份运行它)。


请注意,我对上述ps -l输出采取了一些自由态度,以使有趣的列很好地显示在蓝色小方框中:)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.