• Nenhum resultado encontrado

1 INTRODUÇÃO 29 1.1 MOTIVAÇÃO

5. IMPLEMENTAÇÃO DO MODELO

5.1 Características Gerais

Neste trabalho foi desenvolvido um sistema operacional de tempo real (HellFire OS[1]) portável e totalmente preemptivo, baseado em uma arquitetura kernel monolítico, porém modular. Este sistema operacional implementa o modelo de tarefas descrito no Capítulo 4, e atualmente possui algumas ferramentas para o desenvolvimento e simulação de aplicações embarcadas de tempo real. O sistema operacional pode ser configurado de acordo com a aplicação a ser executada, e parâmetros como o número máximo de tarefas no sistema, tamanho de pilha das tarefas, tamanho da memória

heap (pode ser alocada dinamicamente), política de escalonamento, opções para debug, logging e

migração de tarefas podem ser customizados. Essa customização permite que o tamanho da imagem binária final1 do sistema operacional seja otimizada, tornando possível a execução do sistema em

arquiteturas com tamanho de memória reduzido. Algumas das funcionalidades disponibilizadas ao desenvolvedor incluem:

• Sistema operacional preemptivo (tarefas podem opcionalmente cooperar);

• Gerenciamento dinâmico de tarefas (adicionar, remover, bloquear, resumir, alterar parâmetros,

fork());

• Chamadas de sistema (informações sobre deadlines, uso de processador, memória, energia, parâmetros de tarefas, tempos de trocas de contexto);

• Diferentes políticas de escalonamento para tarefas com prioridade fixa e dinâmica; • Exclusão mútua e semáforos;

• Mailboxes;

• Alocação, liberação e gerência dinâmica de memória;

• Verificações de integridade do sistema de forma automática; • LibC customizada;

1A imagem binária final do sistema é composta pelo sistema operacional e repositório local de tarefas que executam

no mesmo. Esta imagem é carregada na memória de um nodo, permitindo que após a inicialização o sistema operacional execute as tarefas.

• Biblioteca para emulação de ponto flutuante com precisão simples (com funcionalidades adi- cionais como conversões, cálculos de raiz quadrada e funções trigonométricas);

• Comunicação entre tarefas por trocas de mensagem ou memória compartilhada (primitivas bloqueantes e não bloqueantes);

• Migração de tarefas; • Gerência de migração;

Periféricos são acessados através de entrada e saída mapeada em memória ou por portas de entrada e saída. O mapa de periféricos pode ser configurado na camada de abstração de hardware (HAL) para uma solução específica de hardware, o que facilita a portabilidade do sistema operacional para outras arquiteturas. Atualmente, existem portes para as arquiteturas MIPS (multiprocessador), x86 e ARM (monoprocessador).

Figura 5.1 – Estrutura em camadas do sistema operacional Hellfire OS

A Figura 5.1 apresenta a estrutura do sistema operacional. Todas as funções dependentes de arquitetura são implementadas na HAL (camada 1). O kernel do sistema é implementado sobre esta camada (camada 2). Alguns device drivers de baixo nível são implementados nesta camada, onde possuem acesso privilegiado a estruturas internas do sistema e ao hardware. Uma biblioteca reduzida de funções padrão da linguagem C (LibC), assim como a API do sistema operacional são implementadas sobre o kernel (camada 3). Tanto as tarefas quanto o sistema operacional compartilham a biblioteca padrão, o que permite redução na utilização de memória. As tarefas de usuário são implementadas na camada 4, e utilizam da API disponibilizada. Nesta camada também são implementados os device drivers que executam em nível de usuário (como o controle de comunicação e gerência de migração), que possuem os mesmos parâmetros de tarefas de usuário, ou seja, são regidos pela mesma política de escalonamento.

Rotinas de tratamento de interrupção, salvamento e recuperação de contexto são depen- dentes de arquitetura e dessa forma foram escritas em linguagem de máquina. Essas rotinas fazem

parte da camada de abstração de hardware. Apenas uma parte desta camada é descrita em lin- guagem de máquina, sendo o restante de todo o software descrito em linguagem C. É importante salientar que esta camada pode ser facilmente portada para outras arquiteturas, devido a modula- ridade do sistema operacional. Os endereços dos periféricos acessíveis por software são ilustrados da Figura 5.2. A definição destes endereços faz parte da HAL específica para a implementação dos nodos utilizados na arquitetura, que consistem em processadores Plasma [76] modificados. Detalhes sobre a organização interna dos nodos serão apresentados na Seção 5.8.

Figura 5.2 – Endereço dos periféricos acessíveis por software

Um fluxo de execução básico do sistema é apresentado na Figura 5.3. Este fluxo não apresenta estados onde tarefas são mapeadas e excluídas durante a execução entre outros detalhes, por questões de simplicidade.

O fluxo de execução é descrito a seguir. Estruturas de dados do sistema operacional (e

hardware específico) são inicializadas. Após esta inicialização, os tratadores de interrupção são

registrados e habilitados. Neste momento, tarefas iniciais são adicionadas ao sistema e a execução é iniciada. O sistema fica em espera até o acontecimento de um evento de interrupção. Neste momento a rotina de serviço de interrupções é chamada, o contexto básico do processador é salvo e um tratador para a interrupção é invocado de acordo com a origem da interrupção. Em um evento de timer, o tratador de interrupções para escalonamento é chamado, o contexto da tarefa é salvo e o escalonador é invocado. Após o escalonamento, o contexto da tarefa escolhida é restaurado, e sua execução é continuada. Se durante a execução de uma tarefa, a mesma abrir mão de sua fatia de tempo de processador (modo cooperativo), o tratador de interrupções para escalonamento é chamado diretamente. Outras interrupções são tratadas da mesma maneira que interrupções de

timer, entretanto não ocorre reescalonamento de tarefas. Após a execução do kernel driver, a rotina

Inicialização do OS Inicialização e registro de interrupções Habilitação de interrupções Mapeamento de tarefas iniciais OS_start() Execução Tratador de interrupções do timer cooperação Rotina de serviço de interrupções interrupção não mascarável Outro tratador de interrupções Kernel driver Restauração de contexto da tarefa Verificação de integridade do sistema Escalonamento retorno de escalonamento cooperativo retorno de escalonamento preemptivo sistema ok Geração de GPF sistema

instável retorno irq

interrupção genérica interrupção

timer