Acesso ao disco

Este projeto faz parte do PPOS v2.

Este projeto tem por objetivo implementar operações de entrada/saída (leitura e escrita) de blocos de dados sobre um disco rígido virtual. A execução dessas operações estará a cargo de uma tarefa gerente de disco, que cumpre a função de driver (piloto) de acesso ao disco.

O disco virtual

O disco virtual simula o comportamento lógico e temporal de um disco rígido real, com as seguintes características:

O código que simula o disco está em hardware/disk.c e sua interface de acesso está definida em hardware/disk.h; estes arquivos não devem ser modificados.

O acesso ao disco deve feito somente através das definições presentes em disk.h. O código presente em disk.c implementa o comportamento interno do disco virtual e pode ser abstraído.

Interface de acesso ao disco

O acesso ao disco pelas tarefas é feito através das funções definidas em kernel/block.h e implementadas (pelo aluno) em kernel/block.c, usando a interface oferecida pelo disco virtual em hardware/disk.h:

Iniciar o subsistema

void block_init(char *disk_image)

Esta função, chamada na inicialização do PPOS (em kernel/ppos.c) inicia o subsistema de acesso ao disco. Ela recebe como parâmetro o nome do arquivo que armazena o conteúdo do disco virtual.

Informações sobre o disco

int block_size()
 
int block_blocks()

Estas duas funções retornam respectivamente o tamanho de cada bloco do disco virtual (em bytes) e o número de blocos do mesmo.

Leitura e escrita de blocos

As tarefas podem ler e escrever blocos de dados no disco virtual através das seguintes chamadas:

int block_read(int block, void* buffer)
 
int block_write(int block, void* buffer)

Parâmetros:

Estas funções são bloqueantes: cada tarefa que solicita uma leitura/escrita no disco deve ser suspensa até que a operação solicitada seja completada, liberando o processador para outras tarefas.

As requisições de acesso ao disco são mantidas em uma fila específica, gerenciada por uma tarefa “gerente de disco”. Essa tarefa submete as requisições ao disco e trata as interrupções geradas pelo mesmo ao concluir cada operação.

Neste projeto, as solicitações de leitura/escrita devem ser atendidas na ordem em que foram feitas, de acordo com a política de escalonamento de disco FCFS (First Come, First Served).

Tarefa

Este projeto consiste em implementar no arquivo kernel/block.c:

Arquivos

Os seguintes arquivos são relevantes para este projeto:

Sugestão de implementação

As funções block_read e block_write devem seguir +/- o seguinte comportamento:

block_read / block_write
{
    monta um pedido de acesso ao disco
    insere o pedido na fila de pedidos
    acorda o gerente de disco
    suspende a tarefa atual
}

A função de tratamento da interrupção do disco deve ser acionada a cada ocorrência da IRQ do disco; seu comportamento é bem simples:

trata_irq_disco
{
    ocorreu_irq = true
    acorda o gerente de disco
}

A tarefa gerente de disco é responsável por tratar os pedidos de leitura/escrita das tarefas e as operações concluídas pelo disco. Ela deve ser acordada (com task_awake) sempre que alguma tarefa pedir uma operação de leitura/escrita no disco ou quando o disco gerar uma IRQ informando que a última operação solicitada foi concluída.

Ela é uma tarefa de sistema, similar ao dispatcher, e tem o seguinte comportamento:

disk_manager_body
{
    repetir
    {
        se ocorreu_irq
        {
            ocorreu_irq = false
            acorda a tarefa cujo pedido foi atendido
        }
 
        se o disco estiver livre e houver pedidos na fila
        {
            retira um pedido da fila (usando FCFS)
            submete o pedido ao disco
        }
 
        suspende a tarefa atual
    }
}
A fila de pedidos de acesso ao disco é uma estrutura de dados compartilhada, que pode ser acessada de forma concorrente pelo gerente de disco e pelas funções de leitura e escrita. Há risco de condições de disputa em seu acesso, portanto ela deve ser acessada com exclusão mútua (usando semáforo) para garantir sua integridade.

Outras informações