Sobes.tech
Middle

O que acontece com a memória do processo quando criamos uma cópia dele usando a chamada de sistema fork no sistema operativo Linux?

sobes.tech IA

Resposta da IA

Ao chamar fork(), o núcleo do sistema operativo cria um novo processo, um processo filho, que é quase uma cópia exata do processo pai.

Do ponto de vista da memória, o seguinte acontece:

  1. Espaço de endereços virtuais: O processo filho recebe o seu próprio espaço de endereços virtuais separado, idêntico ao do pai no momento da chamada a fork(). Isso significa que o processo filho "vê" os mesmos intervalos de endereços e tem a mesma estrutura de segmentos (código, dados, pilha, heap) que o pai.

  2. Memória física e Copy-on-Write (CoW): Inicialmente, os processos pai e filho partilham as mesmas páginas de memória física. Esta é uma otimização conhecida como "Copy-on-Write" (CoW). A memória física só é copiada quando um dos processos tenta alterar o conteúdo de uma página.

    • Se o processo pai ou filho escreve dados numa página que anteriormente era partilhada, o núcleo cria uma nova cópia dessa página de memória física para o processo que faz a escrita. O outro processo continua a usar a versão antiga da página.
    • Se os processos apenas leem dados, continuam a usar a mesma página de memória física partilhada.
  3. Descritores de ficheiros: Os descritores de ficheiros abertos são herdados pelo processo filho. Ambos os processos partilham os ponteiros para os deslocamentos no ficheiro.

  4. Outros recursos: Outros recursos, como manipuladores de sinais, diretório de trabalho atual, etc., também são copiados ou herdados.

Aqui uma ilustração simplificada:

Antes de fork():

+-------------------+
| Processo Pai      |
| +--------------+  |
| | Memória Virtual | |
| | (Pilha, Heap, ...) | |
| +--------------+  |
|      |            |
|      V            |
| +--------------+  |
| | Memória Física | |
| +--------------+  |
+-------------------+

Imediatamente após fork() (CoW):

+-----------------------+   +-----------------------+
| Processo Pai          |   | Processo Filho        |
| +-------------------+ |   | +-------------------+ |
| | Memória Virtual    | |   | | Memória Virtual    | |
| | (A mesma estrutura)| |   | | (A mesma estrutura)| |
| +-------------------+ |   | +-------------------+ |
|        |              |   |        |              |
|        V              |   |        V              |
| +-------------------+ |   | +-------------------+ |
| | Memória Física     | |   | | Memória Física     | |
| | (Algumas páginas partilhadas)| | | (Algumas páginas partilhadas)| |
| +-------------------+ |   | +-------------------+ |
+-----------------------+   +-----------------------+
          |                            |
          +----------------------------+
                Páginas físicas iniciais partilhadas

Após modificar uma página (CoW ativado):

+-----------------------+   +-----------------------+
| Processo Pai          |   | Processo Filho        |
| +-------------------+ |   | +-------------------+ |
| | Memória Virtual    | |   | | Memória Virtual    | |
| |                   | |   | |                   | |
| +-------------------+ |   | +-------------------+ |
|        |              |   |        |              |
|        V              |   |        V              |
| +-------------------+ |   | +-------------------+ |
| | Memória Física     | |   | | Memória Física     | |
| | (Páginas físicas separadas)| | | (Páginas físicas separadas)| |
| +-------------------+ |   | +-------------------+ |
+-----------------------+   +-----------------------+

É importante entender que, embora o espaço de endereços virtuais seja idêntico imediatamente após fork(), quaisquer alterações na memória de um processo (escrever em variáveis, alocar/libertar memória no heap) não afetam a memória do outro processo graças ao mecanismo CoW. São processos completamente independentes.