DCC605: Sistemas Operacionais
2014/2

TP2: Controle de Memória

Liberado: Terça, 23 de setembro.
Entrega: Terça, 28 de outubro.

Introdução

Neste trabalho iremos implementar funções de controle de memória em um sistema operacional para uma arquitetura de memória fictícia.

Parte 1: Entendendo o simulador do controlador de memória virtual

Antes de começar a implementar as funções necessárias para controle de memória no seu sistema operacional, estude o código fonte do simulador de memória virtual disponível nestes links [vmm.c, vmm.h]. A documentação do seu trabalho deve conter respostas para todas as perguntas nos comentários do código fonte do simulador. Em particular, voce deve documentar como endereços virtuais são convertidos para endereços físicos pelo controlador.

Parte 2: Inicializando seu sistema operacional

Antes de começar a executar processos e fazer o controle da memória, seu sistema operacional tem a chance de inicializar variáveis e a memória do computador. Você deve colocar seu código de inicialização dentro de uma função os_init definida como abaixo:

void os_init(void);

Dentre as operações que precisam ser realizadas por os_init estão (1) a inicialização de uma estrutura de dados que identifica os quadros livres na memória física e (2) a inicialização do controlador de memória para execução do primeiro processo.

Parte 3: Execução do primeiro processo

Após a execução da função os_init seu sistema operacional deve estar pronto para executar o primeiro processo (comumente chamado de init). Seu sistema operacional deve ser capaz de atender pedidos de alocação de memória realizados pelo processo bem como tratar falhas de páginas.

As operações realizadas por processos serão lidas de um arquivo e simuladas de acordo com a função main no simulador disponível neste link [main.c]. As linhas do arquivo podem conter quatro tipos de operação:

Note que as operações read e write são enviadas diretamente ao controlador de memória e utilizam a última tabela de páginas configurada pelo sistema operacional. Abaixo seguem alguns exemplos de arquivos de teste:

Arquivo 1:

# falha de segmentação em leitura de endereço não alocado:
read 0x0

Arquivo 2:

alloc 0x0
# leitura de posição não inicializada (lixo):
read 0x0
write 0x0 1
# lendo o valor 1
read 0x0
# falha de segmentação em escrita em endereço não alocado:
write 0x2000 2

Arquivo 3:

# erro de alocação de memória:
# (endereço não é múltiplo do tamanho dos quadros)
alloc 0x40

Arquivo 4:

alloc 0x200
write 0x200 0x3
free 0x200
# segfault:
read 0x200

Nesta parte do trabalho você deve implementar as funções os_alloc para alocar memória ao processo atual, os_free para liberar memória alocada por um processo, e os_pagefault para tratar falhas de página. Estas funções têm o seguinte cabeçalho:

void os_alloc(uint32_t virtaddr);
void os_free(uint32_t virtaddr);
void os_pagefault(uint32_t virtaddr, uint32_t perm, uint32_t pte);

Nas partes 3 e 4 você pode assumir que existem quadros livres para atender as requisições de alocação de memória. Você irá implementar memória virtual para contornar falta de quadros de memória na Parte 5.

Parte 4: Execução de múltiplos processos

Nesta parte do trabalho iremos dar suporte à execução de múltiplos processos compartilhando a memória. Cada processo deve ter seu próprio espaço de endereçamento virtual, independente dos espaços de endereçamento dos outros processos em execução. Para a criação de processos, o arquivo de entrada para o simulador suporta também o seguinte comando:

Seu sistema operacional deve implementar a função os_swap para trocar processos, com o seguinte cabeçalho:

void os_swap(uint32_t pid);

Sua função os_swap deverá implementar controle de processos. Em particular, seu sistema operacional precisa controlar onde está a tabela de páginas de cada processo. O arquivo de teste abaixo testa a execução de dois processos com espaços de endereçamento disjuntos:

swap 1
alloc 0x200
alloc 0x300
write 0x200 0x1
write 0x201 0x2
write 0x202 0x3
write 0x300 0x1
swap 2
alloc 0x200
write 0x200 0x10
write 0x201 0x20
write 0x202 0x30
swap 1
# lendo 0x1:
read 0x200
read 0x201
read 0x202
read 0x300
swap 2
# lendo 0x10:
read 0x200
# proximo acesso a memoria causa um segfault:
read 0x300

Parte 5: Memória virtual

Até este ponto assumimos que existia um quadro livre sempre que o sistema operacional precisava de um novo quadro de memória. Esse pode não ser o caso quando processos alocam muita memória.

Nesta parte do trabalho você irá estender seu sistema operacional com um sistema de memória virtual. Quando não houver quadros livres na memória principal, seu sistema operacional deverá liberar espaço na memória principal copiando páginas da memória principal no disco.

Proponha um mecanismo para controle de memória virtual na arquitetura simulada. Implemente seu mecanismo usando as funções dccvmm_dump_frame e dccvmm_load_frame disponíveis no controlador de memória. Seu mecanismo provavelmente precisará guardar informações sobre cada quadro da memória física, por exemplo, a qual processo um quadro está alocado.

Seu sistema operacional deve implementar uma política de reposição de páginas. Implemente pelo menos uma das seguintes políticas de reposição de página: reposição aleatória, round-robin, ou LRU (menos recentemente utilizada). Para simplificar, você pode assumir que sempre existe espaço no disco para o sistema de memória virtual.

Requisitos

Seu sistema operacional deve atender os seguintes requisitos:

Documentação

Sua documentação deve conter respostas para as perguntas nos comentários do código, como descrito na Parte 1. Sua documentação também deve detalhar pelo menos:

Extras

O primeiro grupo que reportar cada erro no código do simulador ou inconsistência no enunciado receberá 2 pontos extras por erro reportado (máximo de 6 pontos extras por grupo).