O caso

Um navegador. Doze entradas. E o sistema de pedidos, uma só.

O Isaac abriu o gerenciador de tarefas e viu o navegador listado doze vezes. O sistema de pedidos da loja aparecia uma só, mas atendia dezenas de clientes ao mesmo tempo.

Dois programas, dois jeitos de organizar o trabalho. O que o sistema operacional entende por "um programa rodando"?

Este post parte do Kernel: é ele quem cria e acompanha tudo o que está descrito aqui.

O problema

Um programa no disco não faz nada

Um programa é um arquivo, guardado no disco. Para ele rodar, o sistema precisa carregá-lo na memória, dar a ele um pedaço do processador e acompanhar o que ele faz. E surgem duas necessidades ao mesmo tempo:

  • Isolar: dois programas não podem estragar a memória um do outro.
  • Fazer várias coisas: um mesmo programa, como o sistema de pedidos, precisa atender muitos clientes sem fazer um esperar o outro.

A solução

Processo: um programa em execução

Um processo é um programa em execução. O programa é a receita no papel, e o processo é a cozinha funcionando. O kernel guarda, para cada processo, uma ficha com tudo o que precisa saber:

  • o PID (process ID), um número que identifica o processo;
  • o estado (rodando, esperando…);
  • a memória que ele pode usar, separada da dos outros;
  • os arquivos abertos e os valores dos registradores do processador.

Essa ficha se chama bloco de controle do processo (process control block, PCB).

Como um processo nasce

Nos sistemas Unix, como o Linux e o macOS, um processo novo nasce em dois passos:

  1. O fork cria um processo filho, uma cópia do processo que o chamou (o pai). Para não copiar tudo de uma vez, o Linux usa o copy-on-write: pai e filho compartilham a memória até um deles escrever, e só aí a parte alterada é copiada.
  2. O exec troca o programa do filho por outro. É assim que o terminal abre o ls: faz um fork, e o filho executa o ls.

O que o processo está fazendo

Em cada instante, um processo está em um destes estados:

EstadoO que significa
Pronto (ready)Tem tudo para rodar e espera a sua vez no processador
Executando (running)Está usando o processador agora
Bloqueado (blocked, ou waiting)Espera algo para continuar, como a resposta do disco ou da rede

O kernel alterna os processos entre esses estados tão rápido que parece que todos rodam ao mesmo tempo. Cada troca exige guardar o estado do que sai e restaurar o do que entra: é a troca de contexto (context switch), que custa tempo.

Dentro do processo

Thread: várias linhas de execução

Uma thread é uma linha de execução dentro de um processo. Todo processo tem pelo menos uma, e pode ter várias. As threads de um mesmo processo:

  • compartilham a memória e os arquivos abertos do processo;
  • têm, cada uma, a sua pilha (stack) e os seus registradores, porque cada uma está num ponto diferente do código.

O processo é a loja do Isaac, com o seu balcão, o seu estoque e o seu caixa. As threads são os funcionários: todos trabalham na mesma loja e mexem no mesmo estoque, e cada um está fazendo uma tarefa diferente. Outra loja é outro processo: tem o seu próprio estoque, e ninguém de uma entra no estoque da outra.

Processo AMemória compartilhadacódigo · dados · heapThread 1pilha própriaThread 2pilha própriaThread 3pilha própriaTodas as threads veem a mesma memóriaProcesso BMemória própriaisoladaThread 1pilha própriaNão vê a memóriado Processo A
As threads do Processo A veem a mesma memória. O Processo B está isolado.

Como as threads dividem a memória, criar uma e trocar entre elas é mais barato do que com processos. O preço é o risco: duas threads mexendo no mesmo dado ao mesmo tempo podem se atrapalhar, um problema que vai aparecer nos posts sobre concorrência.

Não confunda

Processo × thread

Processo (process)

“Preciso de isolamento forte entre as partes?”

Exemplo
Cada aba do navegador, para que o travamento de uma não derrube as outras.
Foco
Memória própria, mais caro de criar, e a falha de um não afeta os outros.

Thread

“Preciso de várias tarefas que trabalhem nos mesmos dados?”

Exemplo
O sistema de pedidos, atendendo vários clientes com uma thread para cada pedido.
Foco
Compartilha a memória, é mais leve, e a falha de uma pode derrubar o processo todo.

Na prática

Onde isso aparece

Navegador (processos por aba)

Os navegadores modernos usam processos separados para isolar as abas e as extensões.

No computador do Isaac: as doze entradas do navegador.

Servidor com threads (thread pool)

Um servidor mantém um grupo de threads prontas, e cada pedido usa uma delas.

Na loja: o sistema de pedidos atendendo dezenas de clientes.

Observar processos e threads (ps, top)

No Linux, ps -eLf lista os processos e as suas threads, e top mostra o que está usando o processador.

SituaçãoEscolha
Programas que não podem se atrapalhar, ou código de terceirosProcessos
Muitas tarefas que leem e escrevem os mesmos dadosThreads
Uma falha não pode derrubar o restoProcessos
A criação precisa ser rápida e barataThreads

Termos-chave

Seis termos para fixar

Toque no cartão para ver a definição.

Teste rápido

Três perguntas, estilo prova

01

O que as threads de um mesmo processo compartilham?

02

Num sistema Unix, o que a chamada fork faz?

03

Uma thread acessa uma região inválida da memória e o programa é encerrado. O que acontece com as demais threads do processo?


Processo e thread respondem a duas necessidades diferentes: o processo isola um programa dos outros, e a thread permite que um programa faça várias coisas com os mesmos dados. Escolher entre eles é escolher entre isolamento e economia, e é isso que explica por que o navegador usa processos e o servidor do Isaac usa threads.