50

Мне было интересно, есть ли способ заморозить какой-либо процесс на определенное время?

Я имею в виду следующее: возможно ли для одного приложения (возможно, работающего от имени пользователя root) приостановить выполнение другого уже запущенного процесса (любого процесса, как с графическим интерфейсом, так и из командной строки), а затем возобновить его позже? Другими словами, я не хочу, чтобы планировщик linux планировал определенные процессы в течение определенного периода времени.

3 ответа3

78

Смотрите здесь

Есть два сигнала, которые могут приостановить выполнение процесса. Один "грациозен", а другой "силен".

"Изящным" является 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 и жестко закодируйте сон и уничтожьте его в управляющем скрипте.

Вы можете проверить, что процесс на самом деле приостанавливается, запустив

screen -rS child

после запуска этого скрипта. Вы не увидите ничего на консоли. Затем, после истечения таймера (10 секунд), он заполнит ваш экран данными base64 (случайные символы от 0 до 9 и AF). Нажмите Ctrl+C, чтобы выйти.

12

Да, вы можете сделать это, отправив сигнал STOP процессу, чтобы приостановить его, а затем CONT, чтобы продолжить.

использование:

kill -STOP <pid>

kill -CONT <pid>
10

Если у вас есть достаточно свободное определение "заморозить", вы можете проверить команду renice .

Renice позволяет изменить приоритет планирования запущенных процессов.

Обычное значение nice процесса равно 0. Увеличение приятного значения делает процесс приятнее, например, «почему бы вам не пойти первым». В то время как уменьшение значения nice делает процесс менее приятным, как в случае «убирайся с дороги, я тороплюсь». Хороший диапазон значений от -20 до 19.

Любой может сделать свои собственные процессы приятнее. Только root может сделать процесс менее приятным или изменить процесс обработки других пользователей.

Если вы установите значение nice для процесса равным 19, оно будет запускаться только тогда, когда в системе больше ничего не нужно.

Вот пример запуска на моей локальной машине Linux.

Используйте ps -l и посмотрите на столбец NI, чтобы увидеть значение nice процесса.

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

Запуск renice +10 в процессе vim приводит к тому, что он запускается с более низким приоритетом.

-> renice +10 -p 1105
1105: old priority 0, new priority 10

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

Предполагая, что вы можете растянуть "заморозить", чтобы означать «не беспокоить кого-либо еще в системе», вы можете написать что-то вроде:

renice 20 -p &ltpid of interest&gt
sleep &ltcertain amount of time&gt
renice 0 -p &ltpid of interest&gt

(не забудьте запустить его как root).


обратите внимание, что я взял некоторые вольности с приведенным выше выводом ps -l чтобы интересные столбцы хорошо отображались в маленьких синих прямоугольниках :)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .