![在 Linux 中可以暂时冻结进程吗?](https://linux22.com/image/1332872/%E5%9C%A8%20Linux%20%E4%B8%AD%E5%8F%AF%E4%BB%A5%E6%9A%82%E6%97%B6%E5%86%BB%E7%BB%93%E8%BF%9B%E7%A8%8B%E5%90%97%EF%BC%9F.png)
我想知道是否有办法在一定时间内冻结任何进程?
我的意思是:一个应用程序(可能以 root 身份运行)是否可以暂停另一个已经运行的进程(任何进程,包括 GUI 和命令行)的执行,然后稍后恢复它?换句话说,我不希望某些进程在一定时间内由 linux 调度程序调度。
答案1
看这里
有二可以暂停进程执行的信号。一种是“优雅的”,一种是“强制的”。
“优雅”的方法是SIGTSTP
,其目的是“礼貌地”请求进程(如果它愿意的话)暂停执行,直到收到SIGCONT
。在 的情况下SIGTSTP
,进程可以忽略 SIGTSTP 并继续执行,因此这需要专门用于处理 SIGTSTP 的程序的配合。
“强制”的是SIGSTOP
,其目的是暂停与该进程相关的所有用户空间线程。进程不可能忽略它,SIGSTOP
就像它不可能忽略它一样SIGKILL
(后者强制终止进程)。
要发送任意信号(包括此处提到的任何信号),您可以使用诸如kill
、killall
或之类的程序pkill
;或者使用系统调用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
sleep 和 kill 硬编码到控制脚本中。
您可以通过运行来测试该进程是否确实暂停
screen -rS child
启动此脚本后。控制台上不会显示任何内容。然后,计时器到期(10 秒)后,屏幕上会显示 base64 数据(0-9 和 AF 的随机字符)。按 Ctrl+C 退出。
答案2
是的,您可以通过发送停止向进程发出信号以暂停它,然后继续接着说。
用法:
kill -STOP <pid>
kill -CONT <pid>
答案3
如果您对“冻结”有一个足够宽松的定义,您可以检查一下该renice
命令。
Renice 允许您改变正在运行的进程的调度优先级。
正常进程的 nice 值为 0。增加 nice 值会使进程更 nice,例如“你为什么不先走”。而降低 nice 值会使进程不那么 nice,例如“走开,我很着急”。nice 值的范围是 -20 到 19。
任何人都可以让自己进程变得更好。只有 root 可以让进程变得不那么好或改变其他用户进程的友好度。
如果将进程的 nice 值设置为 19,则仅当系统上没有其他进程想要运行时,它才会运行。
这是在我的本地 Linux 机器上运行的一个例子。
使用ps -l
并查看 NI 列来查看进程的 nice 值。
-> ps -l FS UID PID PPID C PRI NI 地址 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 完成点/0 vim 0 R 29190 794 402 0 76 0 - 15874 - 点/0 点
renice +10
在 vim 进程上运行会导致其以较低的优先级运行。
-> renice +10 -p 1105 1105:旧优先级 0,新优先级 10 -> ps -l FS UID PID PPID C PRI NI 地址 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 完成点/0 vim 0 R 29190 1998 402 0 78 0 - 15874 - pts/0 ps
假设你可以将“冻结”延伸为“不打扰系统上的任何其他人”,你可以编写如下脚本:
renice 20 -p <感兴趣的进程号> 睡眠<一定时间> renice 0 -p <感兴趣的进程号>
(记住以 root 身份运行)。
请注意,我对上面的ps -l
输出进行了一些修改,以便让有趣的列很好地显示在小蓝框中:)