Definição
Os processos são considerados um conceito fundamental na computação. Para uma definição mais didática: “Um processo é, basicamente, um programa em execução […] na essência, um contêiner que armazena todas as informações necessárias para executar um programa” (TANEMBAUM, 2023).
Em outros critérios, os processos são instâncias dinâmicas de programas em execução. Isto é: uma vez que programas computacionais são um conjunto de instruções ordenadas para a realização de tarefas, os processos são as instâncias realizadoras destas instruções. Desta forma, um programa pode possuir um ou mais processos atrelados a si.
Caso você esteja utilizando um sistema GNU/Linux, você pode visualizar os processos que estão sendo executados neste exato momento, utilizando o comando ps aux:

Isolamento de Processos
Atualmente, os processos de um sistema operacional moderno são executados em ambientes isolados em múltiplos aspectos. Ou seja:
- São identificados por um PID (Process ID) único, associados a um grupo ou usuário do sistema (ex.: PID “6582”). Em sistemas GNU/Linux, é possível obter o PID de um processo utilizando o comando
pidof <nome-do-processo>. A mérito de exemplo, o processo principal e os subprocessos do firefox:

- Possuem seu próprio espaço de endereçamento virtual (onde o processo “enxerga” a memória como se fosse exclusiva).
- Dispõem de recursos do sistema próprios (File descriptors, Handles, Permissões de Acesso, Portas de Rede, etc).
- Não acessam o hardware diretamente: para isso, utilizam chamadas de sistema (systemcalls) direcionadas ao Kernel.
- Possuem recursos de IO (Input/Output) segregados (ex.: arquivos e dispositivos como teclados, mouse, etc).
Como provavelmente já é possível notar, o motivo da criação do isolamento de processos tem a ver com questões de segurança.
Sistemas antigos, como o MS-DOS, executavam apenas um processo por vez, portanto, não havia qualquer necessidade na execução isolada desses processos, pois não haviam riscos de um processo interferir na execução de outro.
No entanto, com o advento de sistemas operacionais “multitask” atuais, em que são executados diversos processos “ao mesmo tempo” (isto é: compartilham um mesmo processador - CPU - e demais recursos), por meio de comutação¹, foi necessária a implementação desses ambientes isolados para cada processo.
A importância disso é simples: imagine, por exemplo, se um processo em execução realiza uma operação de escrita em uma região de memória pertencente a outro processo? As consequências disso podem variar de comportamentos indefinidos (“undefined behaviors”) e deadlocks, a crashes gerais de sistema.
Componentes de um Processo
Como mencionado anteriormente, cada processo possui seu próprio espaço de endereçamento virtual. Dentro deste espaço, existem regiões bem definidas, cada uma com uma responsabilidade específica:
Program Code (“Text Segment”)
- Contém as instruções em código de máquina compiladas do programa.
- É somente leitura (read-only), o que impede que o processo modifique suas próprias instruções em tempo de execução.
- Pode ser compartilhado entre múltiplas instâncias do mesmo programa (ex.: dois terminais abertos executam o mesmo binário, mas cada um é um processo distinto).
Data Section
- Armazena variáveis globais e estáticas (ex.:
static int xem C). - Subdivide-se em dois segmentos:
- Dados inicializados: variáveis com valores pré-definidos em código (ex.:
int y = 10;), armazenadas no segmento Data. - Dados não inicializados: variáveis sem valor inicial explícito, zeradas pelo sistema antes da execução, armazenadas no segmento BSS.
- Dados inicializados: variáveis com valores pré-definidos em código (ex.:
- Ambos persistem durante toda a vida do processo.
Pilha (Stack)
- Gerencia o mecanismo de chamadas de funções de forma automática.
- A cada chamada de função, um novo stack frame é empilhado, contendo:
- Variáveis locais.
- Parâmetros recebidos.
- O endereço de retorno (para onde a execução deve voltar após a função terminar).
- Cresce e diminui dinamicamente durante a execução, na direção de endereços menores de memória.
Heap (Área de Alocação Dinâmica)
- Responsável pela alocação de memória em tempo de execução (ex.:
malloc()em C,newem C++). - Ao contrário da Stack, não é gerenciada automaticamente: em linguagens como C/C++, o programador é responsável por liberar a memória alocada (via
free()/delete). Em linguagens de alto nível como Java ou Python, um garbage collector cuida disso. - Cresce na direção de endereços maiores, no sentido oposto à Stack.
Estrutura de Memória de um Processo
Reunindo os componentes acima, a organização do espaço de endereçamento virtual de um processo em Linux segue a seguinte estrutura:
Endereço Alto
┌──────────────────────────────────────────────────────────────────┐
│ ░░░ ESPAÇO DO KERNEL ░░░ │
│ ┌───────────────────┬─────────────────┬────────────────────┐ │
│ │ Direct Mapping │ vmalloc() │ Código/Dados │ │
│ │ (física → virtual)│ Dinâmico │ do Kernel │ │
│ └───────────────────┴─────────────────┴────────────────────┘ │
├══════════════════════════════════════════════════════════════════╡
│ ▓▓▓ ESPAÇO DO USUÁRIO ▓▓▓ │
│ │
│ ┌────────┬─────────────────────────────────────────────────┐ │
│ │ STACK │ Frames de função · Variáveis locais │ │
│ │ │ Endereços de retorno ↓ cresce │ │
│ └────────┴─────────────────────────────────────────────────┘ │
│ │
│ ~ ~ ~ (espaço livre) ~ ~ ~ │
│ │
│ ┌────────┬─────────────────────────────────────────────────┐ │
│ │ HEAP │ Alocação dinâmica em tempo de execução │ │
│ │ │ malloc() · new() · free() ↑ cresce │ │
│ └────────┴─────────────────────────────────────────────────┘ │
│ ┌────────┬─────────────────────────────────────────────────┐ │
│ │ BSS │ Segmento de dados não inicializados │ │
│ │ │ Variáveis globais/estáticas zeradas pelo SO │ │
│ └────────┴─────────────────────────────────────────────────┘ │
│ ┌────────┬─────────────────────────────────────────────────┐ │
│ │ DATA │ Segmento de dados inicializados │ │
│ │ │ Variáveis globais/estáticas com valor definido │ │
│ └────────┴─────────────────────────────────────────────────┘ │
│ ┌────────┬─────────────────────────────────────────────────┐ │
│ │ TEXT │ Segmento de código (read-only) │ │
│ │ │ Instruções em código de máquina compiladas │ │
│ └────────┴─────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘
Endereço Baixo
Estados de Processos
Um processo pode transitar por diversos estados durante sua execução:
- New: O processo está em fase de criação.
- Ready: Preparado para execução, no aguardo de alocação de CPU.
- Running: Executando as instruções do programa.
- Waiting: Em pausa. Aguardando eventos externos (Inputs/Outputs).
- Terminated: Execução completa. Recursos sendo desalocados.
Para visualizar os estados de um processo do tipo service, em sistemas GNU/Linux que utilizam systemd, é possível utilizar o comando systemctl status <nome-do-processo>.

Espero que este post tenha te auxiliado, de alguma forma, a ter uma melhor compreensão sobre processos em Sistemas Operacionais Modernos. Na Parte II desta linha sobre Processos, entraremos em maiores detalhes, como por exemplo, dos diferentes tipos de processos: services, daemons, etc. Além disso, vamos abordar o conceito de “inter-process communication”.
Quaisquer dúvidas, críticas ou sugestões, basta enviar um e-mail para: [email protected].
¹: "… a computação multitarefa permite que cada processador comute entre tarefas que estão sendo executadas sem ter que esperar que cada tarefa finalize. Dependendo da implementação do sistema operacional, a comutação pode ser realizada quando tarefas realizam operações de entrada/saída, quando uma tarefa indica que ela pode ser comutada, ou quando há interrupções de hardware."
REFERÊNCIA BIBLIOGRÁFICA
TANEMBAUM, Andrew S., Sistemas Operacionais Modernos. 5. ed. Porto Alegre: Bookman, 2023. 27 p.
Postado por: bl4nk_