Linux: Desvendando os Processos
Continuamos nossa série sobre Linux. Na última parte, abordamos permissões de acesso, e agora mergulhamos em um dos tópicos mais cruciais no Linux: os processos. Cada programa em execução no sistema, seja o servidor web Nginx, o banco de dados PostgreSQL, o Docker, o serviço SSHD, o systemd, seu shell ou até mesmo os threads do kernel, existe como um processo. Compreender como os processos são criados, como operam, interagem com o kernel e como são encerrados é fundamental para diagnosticar e gerenciar sistemas Linux. Este artigo visa fornecer, de forma concisa e acessível, as informações essenciais para iniciantes e administradores experientes, servindo como uma revisão de conhecimentos.
Importante: Para fins práticos e de aprendizado, recomenda-se o uso de uma máquina virtual com Linux.
A série foca principalmente em distribuições Ubuntu/Debian.
O que é um Processo e um Thread?
Um processo é, essencialmente, um programa em execução. Quando você inicia um contêiner Nginx, executa um script Python (python app.py) ou abre um navegador, o kernel do Linux cria um processo: aloca memória, atribui um número único (PID) e começa a executá-lo. Enquanto o programa está apenas no disco, é um arquivo executável. No momento em que é iniciado, ele se torna um processo sob o controle do kernel.
Um thread (ou fluxo de execução) pode ser entendido como uma tarefa dentro de um processo, compartilhando com ele o espaço de endereçamento e os descritores de arquivo. No kernel, ele é representado pela mesma estrutura task_struct de um processo, mas com flags específicas como CLONE_VM, CLONE_FILES e CLONE_SIGHAND. Nas utilidades como ps e htop, os threads são exibidos como LWP (Light Weight Process), compartilhando o mesmo PID e possuindo um TID (Thread ID) único. Uma falha em um thread afeta todo o processo.
Cada processo possui seu próprio ambiente, um conjunto de recursos e atributos que o kernel aloca durante sua criação:
- Memória Virtual: Cada processo tem seu próprio espaço de endereçamento. Ele não pode acessar ou modificar diretamente a memória de outros processos.
- Tabela de Arquivos Abertos: Através dela, o processo interage com arquivos, sockets, pipes, etc. Por padrão, os descritores 0 (stdin), 1 (stdout) e 2 (stderr) estão abertos. Outros descritores são abertos pelo processo conforme a necessidade.
- Diretório Atual (cwd): A pasta onde o processo está operando. Todos os caminhos relativos são baseados a partir daqui.
- Variáveis de Ambiente: Um conjunto de pares
CHAVE=VALORherdados do processo pai. São usadas para passar configurações comoPATH,HOME,LANG, e às vezes dados sensíveis como tokens e senhas. Podem ser modificadas antes do início do processo ou pelo próprio processo internamente. - UID / GID: Identificadores de usuário e grupo sob os quais o processo está sendo executado. São usados para verificar permissões de acesso a recursos.
- Código de Retorno: Um número inteiro de 0 a 255 retornado pelo processo ao finalizar. 0 indica sucesso, e 1-255 indicam erro. Este código é mantido pelo kernel até que o processo pai o capture usando
wait()ouwaitpid(). Se o pai não o captura, o processo se torna um zumbi.
Ciclo de Vida: Nascimento e Morte
Um novo processo nasce no Linux através do clone de um processo existente, utilizando as chamadas de sistema fork() e exec(). O fork() cria uma cópia exata do processo pai, atribuindo um novo PID. O exec() substitui o espaço de memória do processo clonado pelo código de um novo programa, mantendo o PID e herdando os recursos do pai.
Herança do processo filho: Descritores de arquivo abertos, variáveis de ambiente, diretório atual, UID/GID e manipuladores de sinais são herdados. O PID, a fila de sinais e estatísticas de execução não são herdados.
Um processo morre quando chama exit(). Isso informa ao kernel que o programa dentro do processo concluiu suas operações. Os recursos (arquivos, memória, sockets) são liberados, o processo entra no estado de zumbi (Z), o kernel envia um sinal SIGCHLD para o pai, que por sua vez chama wait() para capturar o código de retorno, e o zumbi é finalmente removido. Se o pai termina antes do filho, o processo órfão é adotado pelo systemd (PID 1), que cuidará de chamar wait() quando o filho terminar.
Um zumbi se torna problemático quando o processo pai não chama wait() para coletar seu código de retorno. Isso leva ao acúmulo de zumbis, esgotamento do espaço de PIDs e, eventualmente, impede a criação de novos processos no sistema.
Exemplos de comandos:
bash# Encontrar zumbis ps aux | awk '$8 == "Z"' # Notificar o pai para limpar um zumbi kill -CHLD <PPID do zumbi> # Se o pai estiver travado, matá-lo (os filhos serão adotados pelo systemd) kill -TERM <PPID>
Estados do Processo
Cada processo se encontra em um dos estados exibidos na coluna STAT do comando ps aux:
- R (Running): Em execução ou na fila para uso da CPU.
- S (Sleeping): Em espera (por entrada, rede, timer). Reage a sinais.
- D (Uninterruptible sleep): Em espera por I/O, não pode ser interrompido por sinais.
- T (Stopped): Suspenso por um sinal (
SIGSTOPouSIGTSTP). Não consome CPU. Pode ser retomado comSIGCONT. - Z (Zombie): Finalizado, mas o código de retorno não foi coletado pelo pai.
- I (Idle): Thread de kernel inativo.
Modificadores de estado:
<: Alta prioridadeN: Baixa prioridades: Líder de sessãol: Multithread+: Em primeiro plano (foreground)
Exemplo: Ssl+ indica um processo dormindo, líder de sessão, multithread e em primeiro plano.
Identificadores: PID, PPID, UID e Outros
- PID (Process ID): Número único atribuído pelo kernel a cada processo.
- PPID (Parent PID): PID do processo que criou o processo atual. Todo processo (exceto
systemd) tem um pai.
bash# Visualizar PID/PPID/Nome do processo ps -ef | head -10 # Árvore de processos (hierarquia) pstree -p # PID máximo no sistema cat /proc/sys/kernel/pid_max
Processos Especiais:
- PID 1 (
systemd): O primeiro processo em espaço de usuário. Todos os outros processos derivam dele. Adota processos órfãos e coleta códigos de retorno, prevenindo acúmulo de zumbis. Não pode ser morto, exceto por reinicialização. - PID 2 (
kthreadd): Pai de todos os threads do kernel. Cria tarefas de sistema comokworker(visíveis entre colchetes[]). Operam no espaço do kernel para tarefas de fundo.
bash# Hierarquia a partir do systemd pstree -p | head -20 # Threads do kernel ps -eo pid,comm | grep '\[' # Verificar o pai de um processo ps -o pid,ppid,comm -p <PID>
Sinais
Um sinal é uma notificação assíncrona enviada pelo kernel ou por outro processo. O processo pode capturar, ignorar ou executar a ação padrão para um sinal.
| Sinal | Número | Padrão | Uso |
|---|---|---|---|
SIGTERM | 15 | Terminar | Solicitação de término gracioso (salvar dados, fechar conexões). |
SIGKILL | 9 | Matar | Término forçado, sem chance de salvar estado. |
SIGHUP | 1 | Terminar | Para daemons (ex: recarregar configuração sem reiniciar). |
SIGINT | 2 | Terminar | Interrupção (Ctrl+C). |
SIGCONT | 18 | Continuar | Retoma um processo suspenso. |
SIGCHLD | 17 | Ignorar | Notifica o pai sobre o término de um filho. |
SIGSTOP | 19 | Parar | Suspende o processo (não pode ser ignorado ou capturado). |
Ação do processo sobre sinais: Capturar (executar um manipulador), Ignorar, ou Ação Padrão (terminar).
SIGKILL e SIGSTOP não podem ser capturados ou ignorados, sendo tratados diretamente pelo kernel.
bash# Enviar sinal por PID kill -TERM <PID> kill -9 <PID> # Equivalente a kill -KILL <PID> # Enviar sinal por nome do processo pkill -TERM nginx pkill -HUP sshd # Recarregar config do sshd # Enviar sinal por linha de comando completa pkill -f "python app.py" # Enviar sinal para um grupo de processos kill -TERM -<PGID> # Verificar se um processo está vivo (sem enviar sinal) kill -0 <PID> && echo "vivo" || echo "morto" # Script para terminar um processo de forma segura PID=1234 TIMEOUT=30 kill -TERM "$PID" for i in $(seq 1 $TIMEOUT); do kill -0 "$PID" 2>/dev/null || { echo "Processo finalizado em ${i}s"; exit 0; } sleep 1 done echo "Processo não finalizado em ${TIMEOUT}s, usando SIGKILL" kill -KILL "$PID"
/proc - Uma Janela para os Processos
A virtual filesystem /proc oferece uma interface para o kernel expor informações sobre processos e o sistema. Os arquivos em /proc não ocupam espaço em disco; são gerados dinamicamente. Eles contêm dados sobre processos em execução, uso de memória, etc.
Principais arquivos em /proc/<PID>:
cmdline: Linha de comando de execução (separada por\0).exe: Link simbólico para o arquivo executável.cwd: Link simbólico para o diretório de trabalho atual.environ: Variáveis de ambiente (separadas por\0).status: Estado, memória, UID, sinais do processo.wchan: Onde o processo está esperando (chamada de sistema).stack: Stack do kernel (requer root).
bash# Exibir cmdline do PID 1 cat /proc/1/cmdline | tr '\0' ' ' # Exibir exe do PID 1 ls -la /proc/1/exe # Exibir cwd do PID 1 ls -la /proc/1/cwd # Exibir variáveis de ambiente do PID 1 tr '\0' '\n' </proc/1/environ # Exibir status do PID 1 cat /proc/1/status cat /proc/1/status | grep -E "Name|State|Uid|VmRSS|Threads" # Exibir wchan do PID 1 cat /proc/1/wchan # Exibir stack do kernel (requer root) sudo cat /proc/1/stack
Descritores de Arquivo:
bash# Lista de descritores abertos para o PID 1 ls -la /proc/1/fd/ # Contagem de descritores abertos ls /proc/1/fd | wc -l # Comparar com o limite de arquivos abertos cat /proc/1/limits | grep "open files"
Um número de descritores próximo ao limite pode indicar um vazamento de arquivos abertos.
Memória e I/O:
VmRSS(Resident Set Size): Memória física real consumida.VmSize: Memória virtual total.VmSwap: Memória swap utilizada.
bash# Consumo de memória do PID 1 cat /proc/1/status | grep -E "VmRSS|VmSize|VmSwap" # Estatísticas de I/O do PID 1 cat /proc/1/io
Scheduler e Prioridades
O scheduler CFS (Completely Fair Scheduler) do Linux gerencia a alocação do tempo de CPU entre os processos.
Nice:
- Um valor de
-20a+19. Menor valor = maior prioridade. nicelança um comando com prioridade definida.renicealtera a prioridade de um processo em execução.
Regras de Nice: Apenas root pode diminuir o valor de nice (aumentar prioridade). Usuários comuns só podem aumentá-lo (diminuir prioridade).
bash# Executar comando com baixa prioridade nice -n 15 rsync -av /data /backup # Executar com alta prioridade (root) sudo nice -n -10 ./service # Ver nice de todos os processos ps -eo pid,ni,comm | sort -k2 -n | head -20
Políticas do Scheduler:
chrtgerencia as políticas do scheduler.SCHED_OTHER: Padrão, baseada em nice. Processos se preempam.SCHED_BATCH: Otimizada para processamento em lote, não interfere em tarefas interativas.SCHED_IDLE: Prioridade mínima, executa apenas quando o sistema está ocioso.SCHED_FIFO: Real-time, executa até ceder ou terminar. Não é preemptível.SCHED_RR: Real-time com quantum de tempo. Executa em intervalos fixos.
Para políticas real-time (FIFO, RR), a prioridade é de 1 a 99. Cuidado: Políticas real-time podem travar o sistema se um processo entrar em loop infinito.
bash# Ver política e prioridade de um processo chrt -p <PID> # Mudar política de um processo em execução sudo chrt -f -p 50 <PID>
ionice: Gerencia a prioridade de acesso ao disco.
- Classe 1 (real-time): Acesso prioritário ao disco (perigoso).
- Classe 2 (best-effort): Padrão, prioridade 0-7.
- Classe 3 (idle): Acesso apenas quando o disco está ocioso.
bash# Executar com prioridade mínima de I/O ionice -c 3 rsync -av /data /backup # Ver prioridade de I/O de um processo ionice -p <PID>
taskset: Vincula um processo a núcleos específicos da CPU.
bash# Executar em núcleos 0 e 1 taskset -c 0,1 ./myapp # Executar em núcleos 2 a 4 taskset -c 2-4 ./worker # Vincular processo existente a núcleos 0,2,4 taskset -cp 0,2,4 <PID> # Ver vinculação atual taskset -cp <PID>
OOM Killer - Quem Morre Primeiro?
Quando a memória se esgota, o kernel invoca o OOM Killer para selecionar um processo a ser encerrado, com base em uma pontuação (oom_score). Processos que consomem mais memória têm maior probabilidade de serem mortos.
bash# Processos sob ameaça (score > 100) for pid in /proc/[0-9]*/oom_score; do score=$(cat $pid 2>/dev/null) [ "${score:-0}" -gt 100 ] 2>/dev/null || continue comm=$(cat ${pid%/oom_score}/comm 2>/dev/null) echo "$score $comm" done | sort -rn | head -10 # Verificar se OOM Killer atuou dmesg | grep -i oom journalctl -k | grep "killed process" # Proteger um processo (ex: postgres) echo -500 | sudo tee /proc/$(pgrep postgres | head -1)/oom_score_adj # Tornar um processo alvo principal echo 1000 | sudo tee /proc/<PID>/oom_score_adj
ulimit e cgroups:
ulimit: Define limites de recursos para a sessão do shell e seus descendentes (arquivos abertos, memória, etc.). As configurações podem ser persistidas em/etc/security/limits.conf.cgroups: Mecanismo de kernel mais granular para limitar recursos de grupos de processos. Osystemdutilizacgroupspara gerenciar serviços.
Quando usar:
- Limites para usuário/sessão:
ulimit. - Limites para serviços
systemd:systemd+cgroups. - Limites para contêineres (Docker): via
docker-compose.yml(usacgroups).
bash# Ver todos os limites ulimit -a # Limites específicos (arquivos, processos, memória virtual, CPU) ulimit -n ulimit -u ulimit -v ulimit -t # Aumentar limite de arquivos abertos temporariamente ulimit -n 65536 # Limites de um processo específico cat /proc/1/limits # Hierarquia de cgroups systemd-cgls # Monitoramento de recursos por cgroup em tempo real systemd-cgtop # Encontrar cgroup de um processo cat /proc/1/cgroup
Monitoramento: top, htop e Outros
top: Exibe processos, uso de CPU, memória e carga do sistema. Pode ser configurado com intervalos (-d 1) ou para monitorar PIDs específicos (-p <PID>).htop: Uma versão interativa e mais amigável dotop.
Flags úteis do top:
-d <segundos>: Intervalo de atualização.-n <número>: Finalizar após N atualizações (útil em scripts).-b: Modo batch (saída para stdout).-1: Mostrar cada núcleo de CPU separadamente.-p <PID>: Monitorar PIDs específicos.-u <usuário>: Mostrar processos de um usuário.-H: Mostrar threads.-c: Mostrar linha de comando completa.-i: Ocultar processos ociosos.
Conclusão
Cobrimos os fundamentos dos processos no Linux. Para aprofundar o aprendizado, a melhor prática é configurar uma máquina virtual e experimentar os comandos e cenários apresentados neste artigo. O gerenciamento de processos é uma habilidade essencial para qualquer profissional de TI que trabalhe com sistemas Linux.
© 2026 ООО «МТ ФИНАНС»





