Introdução aos sistemas operativos
Recursos, abstrações, núcleo, chamadas de sistema, interrupções e arranque.
Ao guardar um texto enquanto a música toca, o editor e o leitor de música disputam CPU, memória e dispositivos. O sistema operativo gere esses recursos e protege os dados de cada programa. O editor pede uma escrita sem precisar de controlar o disco diretamente; a música pode continuar enquanto essa escrita espera pelo dispositivo.
Recursos e abstrações
O núcleo, ou kernel, é a parte privilegiada do sistema que gere CPU, memória e dispositivos. Uma distribuição inclui também bibliotecas, comandos, serviços e interfaces. A shell é um programa de utilizador, não o núcleo.
| Recurso físico | Abstração usada pelo programa | Decisão do sistema |
|---|---|---|
| CPU | Processo e thread | Quem corre e quando |
| RAM | Espaço de endereçamento virtual | Que acessos são válidos e onde estão os dados |
| Disco | Ficheiro e diretório | Onde ficam os blocos e quem pode aceder |
| Dispositivo ou canal | Descritor | Como ler, escrever e esperar |
A abstração esconde pormenores sem apagar diferenças, porque o dispositivo continua a impor condições. read pode ler um ficheiro ou um pipe, mas lseek não reposiciona um pipe.
O sistema procura eficiência, acesso adequado aos recursos e proteção. Estes objetivos competem, por isso dar CPU a um processo durante muito tempo reduz trocas de contexto mas atrasa uma aplicação interativa.
Multiprogramação, concorrência e paralelismo
Um programa alterna rajadas de CPU e operações de I/O. Se bloquear à espera do disco, a CPU pode executar outro programa. Manter vários processos disponíveis para aproveitar esses intervalos chama-se multiprogramação.
A partilha de tempo, ou time sharing, também interrompe processos que ainda poderiam continuar. Cada um recebe uma parte do tempo da CPU, permitindo interação sem esperar pelo fim dos restantes.
Concorrência significa que os períodos de execução de várias tarefas se sobrepõem, ou seja uma CPU pode alternar entre elas. Paralelismo significa execução simultânea, por exemplo em dois núcleos. Uma condição de corrida pode existir com uma única CPU, porque a interrupção entre duas operações já permite entrelaçamentos.
Modo utilizador e modo núcleo
O hardware distingue modos de execução. Em modo utilizador, uma aplicação não pode reprogramar livremente o temporizador nem escolher uma tabela de páginas para ler memória de outro processo. Essas operações exigem privilégio.
Para pedir uma operação protegida, o programa faz uma chamada de sistema, ou seja pede ao núcleo que execute por ele. O percurso típico é:
- O programa chama uma função da biblioteca que prepara o número da operação e os argumentos.
- Uma instrução própria transfere o controlo para uma entrada do núcleo.
- O núcleo verifica os argumentos e as permissões, executa o pedido ou regista que é preciso esperar.
- O resultado chega ao programa, que continua em modo utilizador quando puder correr.
strlen calcula um comprimento em memória e não precisa de entrar no núcleo. open precisa de consultar o sistema de ficheiros e as permissões, por isso entra no núcleo. printf pode guardar texto num buffer da biblioteca antes de write o enviar ao núcleo. Uma chamada de função C e uma chamada de sistema não são a mesma coisa.
Uma mudança de modo também não implica uma troca de contexto entre processos. O mesmo processo pode entrar no núcleo e voltar. Numa troca de contexto, o sistema guarda o estado necessário para retomar uma tarefa e carrega o de outra, incluindo registos e informação de escalonamento.
Interrupções e exceções
Uma interrupção de hardware anuncia um evento externo ao fluxo corrente de instruções, como a conclusão de uma leitura ou um tick do temporizador. Uma exceção resulta da instrução que está a executar, como acesso a uma página ausente. Uma entrada de chamada de sistema é intencional e síncrona.
O processador guarda estado e desvia a execução para um tratador. O núcleo identifica o evento, trata-o e decide o que pode correr a seguir. Não tem de retomar imediatamente o processo interrompido.
Uma falta de página pode ser recuperável, porque o endereço é válido mas os dados ainda não estão na RAM. Escrever numa página sem permissão pode terminar o processo. Por isso não interpretes toda a exceção como um erro fatal.
Um pedido que bloqueia
O editor A pede uma leitura cujos dados ainda não estão disponíveis. A passa de a correr para bloqueado, à espera dos dados. O escalonador escolhe B entre os processos prontos. Quando os dados de A chegam, a interrupção torna-o pronto. A só volta a correr quando for escolhido.
Não foi possível carregar a animação. Abre o vídeo ou acompanha a descrição abaixo.
Pronto significa que só falta obter CPU. Bloqueado significa que falta um evento. Um processo bloqueado não deve receber fatias apenas para repetir a mesma espera.
Para rever a relação entre programa, processo e núcleo, tens este panorama complementar de Rodrigo Dias:
Organização do núcleo
Num núcleo monolítico, vários serviços, como sistemas de ficheiros e drivers, executam no espaço privilegiado do núcleo. Isso permite comunicação por chamadas internas, mas um erro numa dessas partes pode afetar todo o sistema.
Um micronúcleo mantém um conjunto menor de funções privilegiadas e coloca outros serviços em processos separados. Estes comunicam por mensagens. A separação pode limitar o efeito de falhas, mas acrescenta comunicação e transições. Tamanho, modularidade e velocidade dependem da implementação, não só do nome da arquitetura. MINIX é um exemplo didático de organização por serviços; Linux usa um núcleo monolítico com módulos.
Arranque
O firmware inicializa o hardware e encontra uma entrada de arranque. O carregador coloca o núcleo em memória e entrega-lhe o controlo. O núcleo prepara memória, dispositivos e estruturas de processos, depois inicia o primeiro processo de utilizador. Esse processo inicia serviços e sessões.
A shell aparece perto do fim deste percurso. Não carrega o núcleo. Quando escreves um comando, a shell analisa o texto e normalmente cria um filho para executar o programa pedido. Um comando interno como cd precisa de alterar a própria shell: mudar apenas o diretório de um filho não mudaria o da shell que continuas a usar.
Exercícios
Modo, espera e CPU
A está a correr numa CPU e B está pronto. Compara dois pedidos de A: open de um ficheiro cujos metadados estão disponíveis sem espera e read bloqueante de um pipe vazio que tem um escritor aberto. Ignora sinais e erros.
- Em qual dos casos é necessário entrar no núcleo?
- É obrigatório trocar de processo em ambos?
- No segundo caso, chegam bytes enquanto B corre. Que estado passa A a ter? O evento obriga a interromper B?
Pista
Solução
Ambos os pedidos entram no núcleo para executar uma operação protegida. No primeiro, o núcleo pode devolver o resultado ao mesmo processo: mudar de modo não obriga a trocar de processo.
No segundo, A fica bloqueado porque o pipe não tem dados nem EOF. O escalonador pode escolher B. Quando chegam os bytes, A passa a pronto. Falta obter CPU; a política de escalonamento decide se B é preemptado ou continua. A conclusão da I/O e a escolha da CPU são eventos diferentes.
Confere a tua resposta:
- Separei mudança de modo de troca de processo.
- Segui a transição para bloqueado e depois pronto.
- Identifiquei a decisão que ainda falta para voltar a correr.

