next up previous contents index
Next: Apêndices Up: Usando as Funções do Previous: Preparando uma imagem de

Utilizando o Escalonador de Processos  

Nota:
Um exemplo de código utilizando o escalonador de processo pode ser encontrado no anexo [*].

As duas versões do Escalonador de Processos diferem pela forma como escolhem o próximo processo a entrar em execução.

Na versão simples, os processos são escolhidos em ordem FIFO [*], sem prioridade ou envelhecimento.

A versão intermediária conta com prioridade e envelhecimento. Cada vez que um processo entra em execução, os demais processos ``envelhecem'' em uma unidade e o processo em execução tem o seu envelhecimento zerado. Assim, a escolha do próximo processo a entrar em execução é feita escolhendo o processo que tiver o menor valor para a prioridade efetiva, ou seja, o menor resultado na subtração do seu envelhecimento de seu nice [*].

A lista de processos é uma lista encadeada, em que cada nodo possui o endereço base do processo, um flag indicando se ele já entrou em execução, o seu descritor e o seu contexto salvo e, no caso da versão intermediária, sua prioridade original (nice ) e sua idade.

Quando a troca de contexto é acionada, o próximo processo da lista é selecionado. Então, é verificado se já houve uma execução deste processo que foi interrompida.

Caso o processo nunca tenha entrado em execução, é efetuada uma operação call para o seu endereço base:

\begin{displaymath}
{\tt \_\_asm\_\_\:\_\_volatile\_\_(``call\:*\%0''::``m''(endereco)); } \end{displaymath}

Se este for um processo que já entrou em execução, então é chamado a operação longjmp [*] para o seu contexto.

As versões simples e intermediária são não-preemptivas (são colaborativas), ou seja, um processo deve pedir para sair, salvando o seu contexto e depois chamando o escalonador. Este processo de requisição para a troca de esta bem detalhado no código-fonte do caso de teste do escalonador de processos, que acompanha a distribuição.

Para que um processo seja executado dentro do escalonador de processos, o usuário deve estar atento a alguns detalhes. A tabela tab: Escalonador de Processos mostra as peculiaridades deste escalonador. É importante notar que todas as variáveis dentro do processo devem ser declaradas static.


 
Tabela: Escalonador de Processos 
Fase simples intermediaria sugestões para a versão avancada
inicialização de um processo

  • criar a variável global que irá conter o processo, do tipo BNNK_proc *
  • preparar o endereço do processo (e.g. processo1->endereco = &proc1;)
  • adicionar o processo com bnnk_addproc 
  • chamar bnnk_swapproc 

  • como na versão simples, mas preparando também a prioridade do processo (e.g. processo1->prioridade = -2;)

  • retirar esta variável global e trabalhar inteiramente dentro dos limites do processo
  • com um código de tratamento da interrupção timer , pode-se retirar a chamada a bnnk_swapproc
troca entre processos

  • deve-se salvar o contexto e chamar o escalonador (vide [*])

  • como na versão simples

  • salvar o contexto e chamar o escalonador automaticamente, tratando a interrupção timer
finalização do processo

  • antes do processo acabar, deve-se chamar bnnk_delproc  com o descritor do próprio processo

  • como na versão simples

  • o escalonador deverá tratar o termino do processo quando este retornar do call



next up previous contents index
Next: Apêndices Up: Usando as Funções do Previous: Preparando uma imagem de
rafael@safecore.net