Um processo pode ser congelado temporariamente no linux?

49

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

O que quero dizer é que: é possível que uma aplicação (provavelmente em execução como root) pause a execução de outro processo já em execução (qualquer processo, tanto a GUI quanto a linha de comando) e depois a retome mais tarde? Em outras palavras, não quero que certos processos sejam agendados pelo agendador do Linux por um determinado período de tempo.

    
por Pal Szasz 10.10.2012 / 16:10

3 respostas

77

Veja aqui

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

O "gracioso" é SIGTSTP , e sua finalidade é "muito bem" pedir ao processo, se quiser, suspender a execução até receber SIGCONT . No caso de SIGTSTP , o processo pode ignorar o SIGTSTP e continuar a execução de qualquer maneira, portanto, isso requer cooperação de um programa projetado para manipular o SIGTSTP.

O "forçado" é SIGSTOP e sua finalidade é suspender todos os encadeamentos do espaço do usuário associados a esse processo. É igualmente impossível para o processo ignorar SIGSTOP , pois é para ignorar SIGKILL (o último mata o processo com força).

Para enviar um sinal arbitrário, incluindo qualquer um 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 sobre plataforma / arquitetura / versão relacionados a qualquer um dos itens acima. Observe que a palavra "kill" em todos esses comandos e o syscall é um erro incorreto. Esses comandos não são projetados exclusivamente para encerrar processos. Eles podem fazer isso enviando certos sinais; mas os sinais também podem ser usados para funcionalidade diferente de encerrar um processo. Por exemplo, SIGSTOP apenas suspende o processo e é apenas um dos vários sinais que podem ser enviados dessa maneira.

Para adicionar uma condição de retomada automática do processo após um período de tempo, você precisará usar algum tipo de processo de monitoramento que permaneça em execução e defina um cronômetro para ativar o processo de monitoramento, que por sua vez chama kill(2) novamente e envia o sinal SIGCONT para o processo parado, para solicitar que o kernel retome a execução. Note 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, o seu processo de monitoramento pode não ser despertado até bem depois do seu temporizador ter expirado e, portanto, o despertar pode estar atrasado.

Se você depende de uma precisão muito precisa da suspensão e da retomada do processo suspenso, pode ser necessário executar seu programa de monitoramento com permissões em tempo real (consulte esta página de manual em sched_setscheduler(2) para informações sobre como tornar seu processo em tempo real). Você também pode usar Temporizadores de Alta Resolução, um recurso do kernel do Linux (que só está disponível se o seu hardware fornecer suporte para eles), em combinação com o agendamento em tempo real, para obter muito preciso, sub - precisão de milissegundos no tempo, depois despertar e enviar 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 um script bash, embora não seja possível obter um timing muito refinado dessa maneira. Aqui está um bash "script" (não testado, então, por favor, tenha cuidado), que é apenas uma prova de conceito de sua consulta. Se você precisar de um tempo preciso, você terá que escrever um programa, provavelmente em C / C ++ ou outro idioma nativo, e usar agendamento em tempo real e 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}"

Observe que o script terminará e o script de controle será encerrado, mas devido a screen controlar o processo do monitor, ele continuará sendo executado em segundo plano por 10 segundos (com base no argumento transmitido para sleep ) e depois Acorde e continue o processo filho. Mas isso será muito tempo depois que o script de controle terminar. Se você quiser esperar de forma síncrona pelo tempo decorrido, apenas omita a segunda chamada para screen e codifique o sono e mate-os no script de controle.

Você pode testar se o processo de fato suspende executando

screen -rS child

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

    
por 10.10.2012 / 16:23
12

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

uso:

kill -STOP <pid>

kill -CONT <pid>
    
por 15.01.2014 / 01:14
10

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

O Renice permite que você altere a prioridade de agendamento dos processos em execução.

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

Qualquer um pode tornar seus próprios processos mais agradáveis. Apenas root pode tornar um processo menos agradável ou alterar outros processos do usuário.

Se você definir um valor nice de processos como 19, ele só será executado quando nada mais no sistema desejar.

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

Use ps -l e observe a coluna NI para ver um bom valor de processos.

-> 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

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

-> 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

Supondo que você possa esticar "congelar" para significar "não incomodar ninguém no sistema", é possível escrever algo como:

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

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

note que tomei algumas liberdades com a saída ps -l acima para obter as colunas interessantes para aparecer bem nas caixinhas azuis:)

    
por 13.10.2012 / 04:21