Чи можна тимчасово заморозити процес у Linux?


53

Мені було цікаво, чи є спосіб заморозити якийсь процес на певний час?

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

Відповіді:


81

Дивіться тут

Є два сигнали, які можуть призупинити виконання процесу. Одна - «витончена», а одна - «силова».

"Витончений" є SIGTSTP, і його мета - "приємно" попросити процес, якщо він відчуває себе таким, щоб просити призупинити виконання, поки він не отримає SIGCONT. У випадку з SIGTSTPцим процес може ігнорувати SIGTSTP і продовжувати виконувати все-таки, тому для цього потрібна співпраця програми, призначеної для обробки SIGTSTP.

"Силовим" є SIGSTOP, і його мета - призупинити всі потоки простору користувачів, пов'язані з цим процесом. Так само неможливо ігнорувати процес, SIGSTOPяк і його ігнорувати SIGKILL(остання вбиває процес насильно).

Щоб відправити довільний сигнал, в тому числі і будь-який з них , згаданих тут, ви можете використовувати програми , такі як kill, killallабо pkill; або використовувати системний виклик kill(2). Перегляньте підказки вашої операційної системи щодо детальної інформації про платформу / архітектуру / версію та помилки стосовно будь-якого з перерахованого вище. Зауважте, що слово "вбити" у всіх цих командах і syscall є поганим помилкою. Ці команди не призначені виключно для завершення процесів. Вони можуть це зробити, надсилаючи певні сигнали; але сигнали можуть також використовуватися для функцій, відмінних від завершення процесу. Наприклад, SIGSTOPлише призупиняється процес, і це лише один із декількох сигналів, який може бути надісланий таким чином.

Щоб додати умову автоматичного відновлення процесу через певний проміжок часу, вам потрібно буде використовувати якийсь процес моніторингу, який залишається запущеним, і встановлює таймер, щоб прокинути процес моніторингу, який потім по черзі викликає kill(2)знову і посилає SIGCONTсигнал до зупиненого процесу, щоб попросити ядро ​​відновити виконання. Зауважте, що у Linux є кілька механізмів синхронізації з різним ступенем точності та точності; Крім того, якщо ваша система дуже зайнята, ваш процес моніторингу може не пробуджуватися, поки не закінчиться її таймер, і, таким чином, пробудження може затриматись.

Якщо ви залежите від дуже точної точності припинення і відновлення призупиненого процесу, можливо , буде потрібно запустити програму моніторингу з правами доступу в режимі реального часу (див цієї сторінки керівництва на sched_setscheduler(2)інформацію про те , щоб ваш процесі в режимі реального часу). Ви також можете використовувати таймери високої роздільної здатності, функцію ядра Linux (яка доступна лише у тому випадку, якщо ваше обладнання забезпечує їх підтримку), у поєднанні з плануванням у режимі реального часу, щоб отримати дуже точну субмілісекундну точність визначення часу, прокинутися і відправити сигнал для відновлення спостережуваного процесу дуже швидко.

Ви не вказали, які технології ви готові використовувати для цього. Як мінімум, вам буде потрібно щонайменше баш сценаріїв, хоча ви не зможете отримати дуже тонкий графік таким чином. Ось базовий "скрипт" (неперевірений, тому будьте уважні), що є лише доказом концепції вашого запиту. Якщо вам потрібні точні терміни, вам доведеться написати програму, ймовірно, на 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 секунд) він заллє ваш екран базовими даними 64 (випадкові символи від 0-9 та AF). Натисніть Ctrl + C для виходу.


Дуже хороша дуже повна відповідь, включаючи фрагмент PoC bash. Приємно!
fgysin

Якщо процес застигає в середині мережевого сеансу, як TCP-з'єднання, чи продовжується, чи може цей сеанс мережі бути пошкодженим або відхиленим? Чи є для цього визначена поведінка?
CMCDragonkai

@cmcdragonkai, оскільки, оскільки зупинений процес не працює, він не може читати або записувати на будь-який fd, але ядро ​​продовжує передавати байти, поки його буфер не заповниться протягом сеансу TCP, тобто немає передачі між простором ядра та простором користувача. Процеси заморожування різні - перевірити https://www.kernel.org/doc/Documentation/power/freezing-of-tasks.txt
Nizam Mohamed

Я виявив, що TCP-з'єднання можуть продовжуватися після повернення процесу на перший план (тайм-аути залежать від програми, є TCP keepalive, але і keepalive на рівні програми). Процеси заморожування, здається, означають, коли комп'ютер перебуває в сплячому режимі або в режимі сну. Це так?
CMCDragonkai

Цей сценарій не впливає на кооперативні коди: gist.github.com/ceremcem/864dd94b52ffe7b18da29558df4f1f5b
ceremcem

14

Так, ви можете зробити це, надіславши сигнал STOP процесу, щоб призупинити його, а потім CONT для продовження.

використання:

kill -STOP <pid>

kill -CONT <pid>

11

Якщо у вас є вільне визначення "заморозити", ви можете перевірити reniceкоманду.

Renice дозволяє змінювати пріоритет планування запущених процесів.

Нормальне значення приємного процесу дорівнює 0. Збільшення приємного значення робить процес приємнішим, як у "чому ти не йдеш першим". Хоча зменшення приємної цінності робить процес менш приємним, так як "виходьте зі свого шляху, я поспішаю". Приємний діапазон значень - від 20 до 19.

Будь-хто може зробити свої власні процеси приємнішими. Тільки root може зробити процес менш приємним або змінити інших користувачів, які обробляють приємність.

Якщо встановити для файлу nice value 19, воно запуститься лише тоді, коли нічого іншого в системі не хоче.

Ось приклад запуску на моєму локальному вікні Linux.

Використовуйте ps -lта подивіться на стовпець NI, щоб побачити гарне значення процесів.

-> пс -л
FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD
0 S 29190 402 31146 0 75 0 - 16547 чекайте очок / 0 баш
0 T 29190 1105 402 0 75 0 - 23980 фінішна балів / 0 вим
0 R 29190 794 402 0 76 0 - 15874 - очок / 0 пс

Запуск renice +10у процесі vim змушує його працювати з нижчим пріоритетом.

-> renice +10 -p 1105
1105: старий пріоритет 0, новий пріоритет 10

-> пс -л
FS UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD
0 S 29190 402 31146 0 76 0 - 16547 чекайте очок / 0 баш
0 T 29190 1105 402 0 95 10 - 23980 фінішна балів / 0 вим
0 R 29190 1998 402 0 78 0 - 15874 - очок / 0 пс

Припускаючи, що ви можете розтягнути "заморожування", щоб означати "не турбувати когось іншого в системі", ви можете написати щось подібне:

renice 20 -p <зацікавленість>
сон <певна кількість часу>
renice 0 -p <зацікавленість>

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


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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.