Introdução


O XV6 é um sistema operacional que é utilizado pelo MIT no seu curso de Engenharia de Sistemas Operacionais, por ser um sistema simples e que pode ser entendido em um semestre. O sistema foi escrito em sua maior parte em ANSI C, e pode ser utilizado em processadores da arquitetura x86. Repositório GIT do sistema

Tabela de processos

A tabela de processos do XV6 é composta por diferentes parâmetros

  • sz: Contém o tamanho do processo em memória.
  • pgdir: Diretório com a tabela de páginas do processo.
  • kstack: Ponteiro para o começo da pilha do processo no kernel.
  • state: Indica o estado atual do processo. Um processo pode ter os seguintes estados.
    • UNUSED: Significa que o espaço na tabela de processos está livre.
    • EMBRYO: É usado para indicar que o espaço na tabela de processo está sendo usado por um processo que ainda está sendo criado.
    • SLEEPING: Indica que o processo está bloqueado por algum motivo, seja por outro, ou por uma chamada de sistema.
    • RUNNABLE: Irá indicar que o processo está apto para executar.
    • RUNNING: Indica que o processo está em execução na CPU.
    • ZOMBIE: Indica que o processo terminou de executar, e está esperando para retornar algum valor , para outro processo.
  • pid: Contém a ID do processo.
  • ppid: Contém a ID do processo pai.
  • tf: Armazena o qual chamada de sistema o processo está esperando para que volte a executar.
  • chan: Canal utilizado para acordar o processo, caso ele esteja dormindo.
  • killed: Indica se o processo foi morto ou não.
  • cwd: Diretório atual do processo.
  • name: É utilizado para debugging e contém o nome do processo.

Por conta da simplicidade de implementação do XV6, a tabela de processos apresenta um tamanho fixo de X processos durante todo o tempo que o sistema estiver ligado, não podendo colocar em memória mais que essa quantia.

Criação de processos

Todo novo processo no XV6 é criado a partir de um um chamada de sistema de nome FORK. O FORK faz uma cópia da imagem atual do processo, a escreve na tabela de processo e o novo processo irá executar a partir do momento em que o FORK foi chamado. Existem 2 tipos de forks diferentes, um que irá ser utilizado para gerar o primeiro processo, o processo Init e o outro que será utilizado para criar todos os processos que não sejam o Init.

Para mudar o programa que será executado pelo processo, usa-se a chamada de sistema EXEC, que recebe o nome de um arquivo que será o novo programa que o processo executará. A chamada de sistema EXEC não altera a pid do processo nem os descritores de arquivo que estejam abertos.

Código e explicação

Escalonamento de Processos

O papel de um escalonador de processos é manter a CPU ocupada o maior tempo possível, diferentes algoritmos de diferentes complexidades e objetivos existem. Dada a baixa complexidade do sistema operacional, era de se esperar que o método de escalonamento utilizado fosse um algoritmo bem simples. O XV6 implementa o algoritmo Round Robin como método de escalonamento, que é um algoritmo que funciona como uma FIFO, o primeiro processo que chega é o primeiro a executar.

O escalonador entra em ação toda vez que é preciso trocar o processo que está em execução na CPU por algum motivo. Pode ser por conta de interrupções de relógio, o processo que estava executando espera uma chamada de sistema ser feita, o processo liberou sem tempo de execução para outro, começou algum processo de I/O, ou o processo processo precisou ser morto por conta de algum motivo.

O procedimento padrão para a troca do processo que está executando, é chamada de troca de contexto. A troca de contexto é um nome bonito para dizer "Salvar o valor atual dos registradores para armazenar o estado atual do processo, e trocar o valor dos registradores para o do novo processo que será executado". A troca de contexto é feita a partir de um código em assembly.

Código e explicação

Término de Processos

Os processos podem terminar de diferentes modos, retornando algum valor ou sendo mortos por alguém. O XV6 implementa duas chamadas de sistema para trabalhar com essas duas situações aas chamadas de sistema EXIT e KILL. A EXIT faz com que o processo termine e retorne algum valor para seu processo pai, o processo que chama a EXIT fica marcado como ZOMBIE até que seu retorno seja lido, sendo então algo feito de forma voluntária pelo processo.

A chamada de sistema KILL faz com que o processo seja morto. A implementação no XV6 não é muito boa uma vez que o parâmetro KILLED pode ser ignorado durante algum tempo, caso o processo esteja esperando uma I/O por exemplo. Ela funciona procurando o id do processo que se quer matar, e quando a encontra força o processo a sair pela chamada de sistema EXIT.

Os sistemas operacionais normalmente implementam sinais para controlar os processos, mas essa prática não é usada no XV6, pois a implementação tende a aumentar muito a complexidade de um sistema operacional.

Código e explicação

Sincronismo entre processos

Todo sistema operacional deve fornecer pelo menos algum mecanismo de sincronismo entre processos, com o XV6 não é diferente nele é implementado os métodos mais comuns de sincronimo entre processo, e esses métodos ficam disponíveis através de chamadas de sistema.

As chamadas de sistema para o sincronismo que são implementadas pelo XV6 são SLEEP, WAKEUP , WAIT e YIELD. As chamadas de sistema possuem nomes bem intuitivos, a SLEEP, como o nome já diz faz com que o processo durma, seja por decisão própria ou esperar uma I/O, a WAKEUP faz com que o processo acordar e voltar a executar, o WAIT faz com que um processo tenha que esperar o seu processo filho terminar de processar, e por fim a YIELD é uma chamada de sistema que faz com que o processo abra mão de processar durante um ciclo do escalonamento.

Código e explicação