Um processo pode ser congelado temporariamente no linux?

53

Eu queria saber se existe uma maneira de congelar qualquer processo por um certo período de tempo?

O que quero dizer é o seguinte: é possível que um aplicativo (provavelmente executando como root) faça uma pausa na execução de outro processo já em execução (qualquer processo, GUI e linha de comando) e depois o retome mais tarde? Em outras palavras, não quero que certos processos sejam agendados pelo agendador do linux por um certo período de tempo.

Pal Szasz
fonte

Respostas:

81

Veja aqui

Existem dois sinais que podem suspender a execução de um processo. Um é "gracioso" e o outro é "vigoroso".

O "gracioso" é SIGTSTP, e seu objetivo é "gentilmente" pedir ao processo, se lhe parecer, suspender a execução até receber um SIGCONT. No caso de SIGTSTP, o processo pode ignorar o SIGTSTP e continuar executando de qualquer maneira, portanto, isso requer cooperação de um programa projetado para lidar com o SIGTSTP.

O "forçado" é SIGSTOP, e seu objetivo é suspender todos os threads de espaço do usuário associados a esse processo. É tão impossível para o processo ignorar SIGSTOPquanto é para ignorar SIGKILL(o último mata o processo com força).

Para enviar um sinal arbitrário, incluindo qualquer dos mencionados aqui, você pode usar programas como kill, killall, ou pkill; ou use a chamada do sistema kill(2). Consulte as páginas de manual do seu sistema operacional para obter detalhes e erratas dependentes da plataforma / arquitetura / versão e qualquer uma das opções acima. Observe que a palavra "matar" em todos esses comandos e o syscall é um nome impróprio incorreto. Esses comandos não foram projetados, exclusivamente, para finalizar processos. Eles podem fazer isso enviando certos sinais; mas os sinais também podem ser usados ​​para outras funções além de terminar um processo. Por exemplo, SIGSTOPapenas suspende o processo e é apenas um dos vários sinais que podem ser enviados dessa maneira.

Para adicionar uma condição de retomar automaticamente o processo após um período de tempo, você precisará usar algum tipo de processo de monitoramento que permaneça em execução e definir um temporizador para ativar o processo de monitoramento, que, por sua vez, chama kill(2)novamente e envia o SIGCONTsinal para o processo parado, a fim de solicitar que o kernel retome a execução. Observe que o Linux possui vários mecanismos de temporização com vários graus de exatidão e precisão; além disso, se o seu sistema estiver muito ocupado, seu processo de monitoramento poderá não ser ativado até bem depois que o cronômetro expirar e, portanto, a ativação poderá ser atrasada.

Se depender de precisão muito precisas de suspensão e retomada do processo de suspensão, pode ser necessário para executar o seu programa de monitoramento com permissões em tempo real (ver esta página de manual on sched_setscheduler(2)para obter informações sobre como fazer seu processo em tempo real). Você também pode usar temporizadores de alta resolução, um recurso do kernel Linux (disponível apenas se o seu hardware oferecer suporte a eles), em combinação com agendamento em tempo real, para obter uma precisão muito precisa, abaixo de milissegundos, no momento certo. ative e envie o sinal para retomar o processo monitorado muito rapidamente.

Você não indicou quais tecnologias deseja usar para implementar isso. No mínimo, você precisará de pelo menos scripts bash, embora não seja possível obter um tempo muito detalhado dessa maneira. Aqui está um "script" bash (não testado, portanto, tenha cuidado) que é apenas uma prova do conceito de sua consulta. Se você precisar de tempo preciso, precisará escrever um programa, provavelmente em C / C ++ ou outro idioma nativo, e usar agendamento e hrtimers em tempo real.

#!/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}"

Observe que o script será finalizado e o script de controle será encerrado, mas, devido ao screencontrole do processo do monitor, ele continuará sendo executado em segundo plano por 10 segundos (com base no argumento passado para sleep) e, em seguida, será ativado e continuará o processo filho. Mas isso será muito tempo depois que o script de controle terminar. Se você deseja esperar de forma síncrona o tempo decorrido, basta omitir a segunda chamada screene codificar permanentemente o sono e interromper o script de controle.

Você pode testar se o processo realmente suspende executando

screen -rS child

depois de iniciar esse script. Você não verá nada no console. Depois que o timer expirar (10 segundos), ele inundará sua tela com dados base64 (caracteres aleatórios de 0 a 9 e AF). Pressione Ctrl + C para sair.

allquixotic
fonte
Resposta muito boa muito completa, incluindo o snippet de PoC bash. Agradável!
fgysin
Se um processo congelar no meio de uma sessão de rede, como uma conexão TCP, quando for continuado, essa sessão de rede poderá estar corrompida ou cair? Existe um comportamento definido para isso?
CMCDragonkai
@cmcdragonkai porque, como processo parado, não está em execução, ele não pode ler ou gravar em nenhum fd, mas o kernel continua transferindo bytes até que seu buffer esteja cheio em uma sessão TCP, ou seja, nenhuma transferência entre o espaço do kernel e o espaço do usuário. processos de congelamento é verificar diferentes https://www.kernel.org/doc/Documentation/power/freezing-of-tasks.txt
Nizam Mohamed
Descobri que as conexões TCP podem continuar após trazer o processo de volta ao primeiro plano (os tempos limite são específicos ao aplicativo, há manutenção do TCP ativa, mas também manutenção do nível do aplicativo). Processos de congelamento, parece significar quando o computador está no modo de hibernação ou suspensão. Isso está certo?
precisa saber é o seguinte
Este script faz nenhum efeito sobre códigos não-cooperativos: gist.github.com/ceremcem/864dd94b52ffe7b18da29558df4f1f5b
ceremcem
14

Sim, você pode fazer isso enviando um sinal de STOP para um processo para suspendê-lo e, em seguida, um CONT para continuar.

uso:

kill -STOP <pid>

kill -CONT <pid>

fonte
11

Se você tiver uma definição adequada de "congelar", verifique o renicecomando.

Renice permite alterar a prioridade de agendamento dos processos em execução.

O valor normal do processo normal é 0. Aumentar o valor legal torna o processo mais agradável, como em "por que você não vai primeiro". Embora diminuir o valor agradável torne um processo menos agradável, como em "saia do meu caminho, estou com pressa". O intervalo de valor agradável é de -20 a 19.

Qualquer um pode tornar seus próprios processos mais agradáveis. Somente o root pode tornar um processo menos agradável ou alterar a gentileza de outros usuários.

Se você definir um valor legal de processos como 19, ele será executado apenas quando nada mais o sistema desejar.

Aqui está um exemplo executado na minha caixa linux local.

Use ps -le observe a coluna NI para ver um valor agradável dos processos.

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

A execução renice +10no processo vim faz com que seja executada com uma prioridade mais baixa.

-> renice +10 -p 1105
1105: prioridade antiga 0, nova prioridade 10

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

Supondo que você possa esticar "congelar" para significar "não incomodar mais ninguém no sistema", você pode criar um script como:

renice 20 -p <pid de interesse>
sono <certa quantidade de tempo>
renice 0 -p <pid de interesse>

(lembre-se de executá-lo como root).


note que tomei algumas liberdades com a ps -lsaída acima para fazer com que as colunas interessantes aparecessem bem nas pequenas caixas azuis :)

Maurice
fonte