Organização do Sistema Operativo

Constituição do Sistema Operativo

O utilizador típico de um computador não é um programador com conhecimento profundo de como a memória, processos e outros recursos do computador funcionam, e no caso do utilizador o ser, este não necessita de controlar todos os aspetos da sua máquina, assim sendo o SO tem de apresentar certas características que facilitam muito o trabalho do programador.

  • Abstração

    • O programador típico não deve precisar de se preocupar com os detalhes de comunicar com os vários periféricos (que podem estar ligados de n formas diferentes - SPI, I²C, etc. - ter m bugs que precisam de ser contornados, e w interfaces com paradigmas diferentes)
      • Estas abstrações podem ser mais ou menos complexas, e abstrações de vários níveis podem coexistir. P.ex. discos tanto são acedidos indiretamente por sistemas de ficheiros/mounts, como por ficheiros diretamente como block devices (deixando literalmente escrever todo o disco de início ao fim); interfaces de rede tanto podem ser geridas pelo SO e manipuladas como sockets como expostas diretamente a processos
  • Multitarefa

    • O utilizador quer correr várias coisas, mas nem ele nem o programador se devem ter de preocupar com fazer isto funcionar - o SO abstrai a existência de outros processos a executar em concorrência e deixa o programador de aplicação usar o computador como se fosse o único processo a executar - todas as questões de sincronizar acessos a recursos partilhados são tratadas por SO.
  • Segurança

    • O SO responsabiliza-se por controlar acessos aos vários recursos do computador (não deixa processos escrever na memória uns dos outros - exceto quando ambos concordam com shared memory, permissões do sistema de ficheiros). Desta forma, permitir que o utilizador típico de um computador tivesse acesso a estes recursos podia ser bastante destrutivo para a "segurança do computador". Desta forma, o Sistema Operativo deve ser uma interface de proteção dos recursos essenciais do computador.

Alem de que o SO deve garantir que:

  • os processos não interferem diretamente com recursos físicos do computador;
  • os processos não interferem uns com os outros.

Para responder a esta necessidade, qualquer Sistema Operativo distingue dois modos de execução:

Modo Utilizador

Processos em modo utilizador têm acesso restrito a privilégios. Isto é, não conseguem aceder diretamente a qualquer endereço de memória, periféricos, ficheiros, etc (os recursos bloqueados em modo utilizador dependem do SO). Além de certas instruções do CPU que impactam o sistema globalmente serem restritas. A maioria das aplicações que correm no nosso computador estão em modo utilizador. O espaço de endereçamento acessível a um processo neste modo está limitado e por omissão deve ser disjunto do dos outros processos (para que estes não comuniquem entre si) a menos que estejam a usar memória partilhada. Podem aceder às suas variáveis e executar operações aritméticas, entre outros, mas estão proibidas de executar operações "perigosas" sobre os recursos físicos.

Quando um processo em modo utilizador pretende aceder a um recurso lógico, pede ao Sistema Operativo através de uma chamada de sistema. É da responsabilidade do SO aceder ao recurso pretendido de forma segura e oferecer ao processo a resposta.

Modo núcleo

Modo privilegiado em que o código do Sistema Operativo é executado, de forma a poder interagir diretamente com os recursos físicos. Podemos dizer por poucas palavras que o modo núcleo funciona como executor de chamadas sistema. Permite assim aos processos que correm em modo utilizador uma biblioteca de funções sistema que lhes permitam aceder a recursos físicos de forma segura.
Só o código do SO pode correr neste modo (de outra forma, estaríamos a dar privilégios a processos que não os deviam ter).

Todas as atividades do modo núcleo são desencadeadas por exceções. Estas podem ser:

  • Assíncronas: provocadas por algo ortogonal ao programa em execução (exemplos: timer, falta de energia, etc). Estas exceções também são frequentemente designadas por interrupções;
  • Síncronas: provocadas por um acontecimento relacionado com o programa em execução (exemplos: divisão por zero, acesso a zona de memória proibida, chamada de sistema, etc);

Quanto à origem, podemos classificar as interrupções como:

  • Desencadeadas por Hardware: periféricos (teclado, rato, etc);

  • Desencadeadas por Software (traps): para chamadas a funções de sistema;

  • Existem exceções que podem ser desencadeadas por Hardware ou Software:

    • Exceções de aritmética (divisão por zero) e acesso a memória indevido.

Informação Conflituosa

A informação nos últimos dois parágrafos contradiz-se mutuamente. É assim que é apresentada num dos recursos da cadeira e estamos à espera de clarificação dos professores.

Visão de Alto Nível do SO

O SO deve então oferecer às aplicações uma implementação segura de:

  • Gestão de processos;
  • Input/output com periféricos;
  • Gestão de atividades paralelas dentro de um processo;
  • Gestão de memória;
  • Sistema de ficheiros;
  • Comunicação pela rede;
  • Gráficos e gestão de janelas;
  • Autenticação e segurança;
  • Etc.
Exemplo: Interação com Periférico

Para exemplificar o que acontece quando um processo faz uma chamada de sistema, vamos ver o que acontece quando um processo quer fazer algo sobre um periférico:

  • Processo pede (através de syscall) ação sobre um periférico;
  • O núcleo (através do Gestor de Periféricos) envia pedido ao periférico e bloqueia o processo;
  • Quando o pedido for servido, o periférico lança uma interrupção;
  • Consequentemente, o núcleo (mais concretamente, o Gestor de Periféricos) é ativado, entrega a resposta ao processo e torna-o executável;
Interações Assíncronas

Enviar n pedidos ao SO por syscalls para fazer coisas com recurso, que não bloqueiam.

  • Fazer um pedido ao SO para bloquear até que uma ou todas essas n operações acabem;
  • Ou um primeiro pedido - p.ex. select
    • que bloqueia até que um ou mais dos n recursos em que se queira mexer esteja pronto para interações, e só depois mandar o pedido de leitura/escrita/etc a esse recurso, que nunca bloqueia: fazendo a operação, ou diz para tentar mais tarde

Iniciação de um Sistema Operativo

Quando o nosso computador está desligado, não passa de um objeto inanimado. Contudo, quando carregamos num botãozinho, esse objeto inanimado converte-se numa caixa mágica capaz de fazer as mais diversas operações. Vamos agora ver como é que isso é possível.

Quando uma máquina recebe energia, o PC (Program Counter) aponta para um programa (firmware) na Boot ROM. Nos computadores pessoais é habitual este programa ser uma implementação de BIOS (Basic Input/Output System) ou UEFI (Unified Extensible Firmware Interface). Este programa faz algumas verificações sobre o computador (nomeadamente se está em condições de ser iniciado) e, de seguida, determina a localização do bootloader (no limite definido estaticamente no firmware, mas tanto em BIOS como UEFI há uma "ordem de arranque" que diz em que sítios procurar e com que ordem), copia-o para RAM, e passa-lhe o controlo (salta)

O bootloader, por sua vez, carrega o programa do núcleo em RAM e salta para a rotina de inicialização do núcleo. A inicialização do núcleo passa por:

  • inicializar as suas estruturas de dados;
  • copiar rotinas de tratamento de cada interrupção para RAM;
  • preencher a tabela de interrupções em RAM;
  • lançar os processos inicias do sistema, incluindo o processo de login;

Estrutura do Sistema Operativo

O Sistema Operativo não passa de um pedaço (muito grande) de código. Consequentemente, a implementação do SO vem acompanhada das preocupações normais com projetos de código grandes. Nomeadamente, a organização interna do SO deve facilitar a sua manutenção e evolução.
Abaixo vamos estudar organizações comuns em sistemas operativos que garantem estas propriedades.

Estrutura Monolítica

Estrutura Monolítica

  • Um único sistema

  • Internamente organizado em módulos

  • Estruturas de dados globais

  • Problema: como dar suporte à evolução

    • Em particular, novos periféricos
  • Solução para este caso particular: gestores de dispositivos (device drivers)

  • Problemas?

Sistemas em Camadas

Sistema em Camadas

  • Cada camada usa os serviços da camada precedente

  • Fácil modificar código de uma camada

  • Mecanismos de proteção \rightarrow maior segurança e robustez

  • Influenciou arquiteturas como Intel

Micro-núcleo

  • Propostas de investigação à separação entre:

  • Um micro-núcleo de reduzidas dimensões e que só continha o essencial do sistema operativo:

    • Gestão de fluxos de execução - threads
    • Gestão dos espaços de endereçamento
    • Comunicação entre processos
    • Gestão das interrupções
  • Servidores sistema que executavam em processos independentes a restante funcionalidade:

    • Gestão de processos
    • Memória virtual
    • Device drivers
    • Sistema de ficheiro

Micro-Núcleo

Micro-Núcleo vs Monolítico

VS


Slides: