College Online
0%

Memoria e Enderecos

Modulo 4 · Aula 1 ~20 min de leitura Nivel: Intermediario

Video da aula estara disponivel em breve

Enderecos Fisicos vs. Virtuais

Toda instrucao e dado que a CPU processa esta em algum endereco de memoria. Mas quando um programa referencia o endereco 0x4000, esse nao e necessariamente o endereco fisico na RAM. Existem dois espacos de enderecamento:

Diagrama — Traducao de Enderecos
Programa ve:                  RAM real:
+------------------+          +------------------+
| 0x0000: code     |          | 0x0000: [kernel]  |
| 0x1000: data     |   MMU    | 0x1000: [kernel]  |
| 0x2000: heap     | ------>  | 0x2000: [Proc B]  |
| ...              |          | 0x3000: [Proc A code] ← 0x0000 virtual
| 0xFFFF: stack    |          | 0x4000: [Proc A data] ← 0x1000 virtual
+------------------+          | 0x5000: [livre]   |
                              | 0x6000: [Proc B]  |
Espaco virtual do             | 0x7000: [Proc A heap] ← 0x2000 virtual
Processo A                    +------------------+

A MMU (Memory Management Unit) traduz CADA acesso
a memoria. O programa nunca ve enderecos fisicos.
i
Por que enderecos virtuais? Sem enderecos virtuais, cada programa precisaria saber exatamente onde na RAM esta carregado. Dois programas nao poderiam usar o mesmo endereco. Recompilar ou realocar programas seria necessario. Enderecos virtuais permitem que cada processo "pense" que tem toda a memoria para si, comecando do endereco 0.

Layout de Memoria de um Processo

Diagrama — Memory Layout
Enderecos altos (ex: 0x7FFF...)
+-----------------------------------+
|             Stack                 |  Variaveis locais, enderecos de
|              |                    |  retorno. Cresce para BAIXO.
|              v                    |  Tamanho tipico: 8MB (ulimit -s)
|                                   |
|         (espaco livre)            |
|                                   |
|              ^                    |
|              |                    |
|             Heap                  |  malloc()/new. Cresce para CIMA.
|                                   |  Tamanho: ilimitado (ate swap).
+-----------------------------------+
|             BSS                   |  Globais nao-inicializadas.
|                                   |  Preenchidas com zero pelo SO.
+-----------------------------------+
|             Data                  |  Globais inicializadas.
|                                   |  int x = 42; fica aqui.
+-----------------------------------+
|             Text (Code)           |  Instrucoes do programa.
|                                   |  Read-only. Compartilhavel.
+-----------------------------------+
Enderecos baixos (ex: 0x0040...)
C — Observando o layout de memoria
#include <stdio.h>
#include <stdlib.h>

int global_init = 42;        // segmento Data
int global_uninit;            // segmento BSS

int main() {
    int local_var = 10;        // Stack
    int *heap_var = malloc(sizeof(int));  // Heap

    printf("Enderecos (virtuais):\n");
    printf("  Code (main):    %p\n", (void*)main);
    printf("  Data (init):    %p\n", (void*)&global_init);
    printf("  BSS  (uninit):  %p\n", (void*)&global_uninit);
    printf("  Heap (malloc):  %p\n", (void*)heap_var);
    printf("  Stack (local):  %p\n", (void*)&local_var);

    free(heap_var);
    return 0;
}
/* Saida tipica (enderecos simplificados):
  Code (main):    0x401136
  Data (init):    0x404030
  BSS  (uninit):  0x404034
  Heap (malloc):  0x1234560
  Stack (local):  0x7ffd8a3b4c
  Note: Stack muito acima, Heap no meio, Code embaixo.
*/
Shell — Inspecionando memoria de um processo
# Ver o mapa de memoria de um processo
$ cat /proc/self/maps
00400000-00401000 r--p  /usr/bin/cat      # Text (read-only)
00401000-00404000 r-xp  /usr/bin/cat      # Text (executable)
00404000-00406000 r--p  /usr/bin/cat      # Data (read-only)
00406000-00407000 rw-p  /usr/bin/cat      # Data (read-write)
01234000-01255000 rw-p  [heap]            # Heap
7f8a00000-7f8b00000 r-xp /lib/libc.so    # Shared library
7ffd80000-7ffda0000 rw-p [stack]          # Stack

# Colunas: endereco, permissoes (r/w/x/p), path
# p = private (copy-on-write), s = shared

# Resumo de uso de memoria
$ pmap 1234   # mapa de memoria do PID 1234
$ free -h     # uso de memoria do sistema

Protecao de Memoria

O SO garante que um processo nao pode acessar a memoria de outro. Cada processo tem sua propria tabela de paginas, e a MMU verifica cada acesso:

!
Segmentation fault O infame "segfault" e o SO protegendo voce (e outros processos) de um acesso invalido a memoria. Sem protecao de memoria (como no MS-DOS), um programa bugado poderia corromper a memoria de qualquer outro programa ou do proprio SO.

No harness.os

A context window de um LLM e analoga ao espaco de enderecamento de um processo:

Diagrama — Context Window como Memoria
Memoria de Processo (SO)         Context Window (LLM)
========================         =========================

+------------------+             +---------------------------+
| Stack            |             | Conversa recente          |
| (variaveis       |             | (ultimas mensagens,       |
|  locais)         |             |  estado ativo)            |
+------------------+             +---------------------------+
| (espaco livre)   |             | (espaco disponivel)       |
+------------------+             +---------------------------+
| Heap             |             | Knowledge carregado       |
| (alocacao        |             | (get_knowledge(), rules,  |
|  dinamica)       |             |  workflows sob demanda)   |
+------------------+             +---------------------------+
| Data/BSS         |             | System prompt / CLAUDE.md |
| (globais)        |             | (sempre presente,         |
|                  |             |  "inicializado" no start) |
+------------------+             +---------------------------+
| Text             |             | Model weights             |
| (instrucoes)     |             | (fixo, read-only,         |
|                  |             |  compartilhado)           |
+------------------+             +---------------------------+

Stack overflow = context window cheia (compaction)
malloc()       = get_knowledge() (alocar espaco para dados)
free()         = conhecimento sai do contexto
Segfault       = hallucination (acessar "memoria" que nao existe)
Python — Context window como espaco de enderecamento
class ContextMemory:
    """Context window modelada como espaco de enderecamento."""

    def __init__(self, max_tokens=200000):
        self.max_tokens = max_tokens
        self.text = "model weights"     # fixo, nao conta
        self.data = []                   # system prompt, CLAUDE.md
        self.heap = []                   # knowledge carregado
        self.stack = []                  # conversa ativa

    def malloc(self, knowledge_chunk):
        """Carregar conhecimento = alocar no heap."""
        tokens = count_tokens(knowledge_chunk)
        if self.used() + tokens > self.max_tokens:
            raise MemoryError("Context window cheia")
        self.heap.append(knowledge_chunk)

    def used(self):
        return sum(count_tokens(x) for x in self.data + self.heap + self.stack)

Homework

  1. Compile e execute o programa de enderecos. Compare os enderecos com o /proc/PID/maps do processo.
  2. Escreva um programa que causa um segmentation fault de 3 formas diferentes: (a) dereferencia NULL, (b) escreve em memoria read-only, (c) acessa alem de um array.
  3. No harness.os, calcule o "uso de memoria" de uma sessao tipica: system prompt (~X tokens) + handoff (~Y tokens) + knowledge (~Z tokens) + conversa (~W tokens). Qual percentual da context window (200k tokens) esta "livre"?

Resumo

Verifique seu entendimento

Se dois processos diferentes acessam o endereco virtual 0x4000, eles estao acessando o mesmo byte na RAM fisica?

  • Sim, enderecos virtuais iguais sempre mapeiam para o mesmo endereco fisico
  • Nao, cada processo tem sua propria tabela de paginas, entao o mesmo endereco virtual mapeia para enderecos fisicos diferentes
  • Depende do algoritmo de escalonamento em uso
  • Sim, mas apenas se ambos estiverem na mesma fila de escalonamento