Computer Science › Como os Computadores Realmente Funcionam

Sistemas Operacionais I

0 de 24
  1. A API de Processos: fork() e exec()

    A separação do Unix entre \"crie uma cópia de mim\" (fork) e \"substitua minha memória por outro programa\" (exec): um projeto de dois passos genuinamente estranho, cuja estranheza é exatamente o que torna possíveis os shells e os pipes.

    Ler →6 seções10 min
  2. Estados de Processo e Troca de Contexto

    Um processo está sempre em exatamente um de um punhado de estados (executando, pronto ou bloqueado), e o mecanismo que permite ao SO salvar o estado de CPU de um processo e carregar o de outro é a troca de contexto, a maquinaria sobre a qual a execução direta limitada é construída.

    Ler →6 seções11 min
  3. Escalonamento de CPU: Objetivos e Métricas

    Antes de comparar políticas de escalonamento, é preciso fixar o que 'bom' significa: tempo de retorno, tempo de resposta e vazão muitas vezes competem entre si, então nenhuma política vence em todas as métricas ao mesmo tempo.

    Ler →6 seções9 min
  4. FCFS, SJF e o Efeito Comboio

    O primeiro-a-chegar-primeiro-a-ser-atendido é trivialmente justo, mas deixa uma única tarefa longa bloquear todas as tarefas curtas atrás dela (o efeito comboio), enquanto o menor-tarefa-primeiro corrige de forma comprovada o tempo de retorno médio, ao custo de precisar conhecer o futuro.

    Ler →6 seções9 min
  5. Round-Robin e Fatias de Tempo

    Dar a toda tarefa uma fatia de tempo pequena e fixa e revezar entre elas: excelente para o tempo de resposta, pior para o tempo de retorno que o SJF, e a primeira política desta disciplina que não precisa prever o futuro.

    Ler →6 seções10 min
  6. Escalonamento por Prioridade e Inanição

    Deixar algumas tarefas furarem a fila resolve o problema de trabalho urgente esperando atrás de trabalho trivial, mas abre um novo: uma tarefa de baixa prioridade pode esperar para sempre se o trabalho de prioridade mais alta nunca parar de chegar.

    Ler →6 seções10 min
  7. Escalonamento com Filas Multinível com Realimentação

    O escalonador que os sistemas operacionais reais de fato aproximam: várias filas de prioridade, tarefas rebaixadas por usarem CPU demais e promovidas periodicamente para evitar inanição, aprendendo o comportamento de uma tarefa pelo seu histórico recente em vez de perguntar de antemão.

    Ler →6 seções11 min
  8. Threads e o Espaço de Endereçamento Compartilhado

    Uma thread é um fluxo de execução escalonável de forma independente que compartilha o espaço de endereçamento do seu processo com as threads irmãs: exatamente a mecânica em nível de sistema com que o modelo de concorrência com estado compartilhado, apresentado conceitualmente em outro lugar, é de fato construído.

    Ler →6 seções10 min
  9. O Problema da Seção Crítica e a Exclusão Mútua

    O enunciado formal do perigo de condição de corrida já visto como modelo mental: uma seção crítica é qualquer código que toca estado compartilhado, e a exclusão mútua é a garantia de que no máximo uma thread está dentro dela por vez.

    Ler →6 seções9 min
  10. Locks e Primitivas Atômicas de Hardware

    Um lock só funciona se adquiri-lo for ele mesmo imune à mesma condição de corrida que ele impede, e é por isso que locks reais são construídos sobre instruções atômicas fornecidas pelo hardware, como test-and-set e compare-and-swap, e não sobre load/store comuns.

    Ler →6 seções10 min
  11. Variáveis de Condição

    Um lock sozinho não consegue deixar uma thread esperar que alguma condição se torne verdadeira sem ficar girando ocupada; uma variável de condição acrescenta exatamente isso: uma fila em que uma thread pode dormir, e um sinal que outra thread envia quando a espera acaba.

    Ler →6 seções10 min
  12. Semáforos

    Um único contador inteiro com duas operações atômicas, wait e signal, geral o bastante para implementar um lock, a sinalização de uma variável de condição ou um limite de quantas threads podem prosseguir ao mesmo tempo: a única primitiva de Dijkstra que faz o trabalho de várias.

    Ler →6 seções10 min
  13. Deadlock: Condições e Detecção

    Locks e semáforos resolvem condições de corrida, mas abrem um novo modo de falha: threads esperando umas pelas outras num ciclo, para sempre. É o deadlock, detectável construindo um grafo de alocação de recursos e rodando exatamente o mesmo algoritmo de detecção de ciclos já visto para grafos em geral.

    Ler →6 seções10 min
  14. Espaços de Endereçamento e Virtualização de Memória

    Cada processo vê seu próprio espaço de endereçamento privado e contíguo, começando no endereço zero: uma ilusão que o SO mantém sobre uma única RAM física compartilhada, e o motivo de um bug nos ponteiros de um programa não conseguir corromper a memória de outro.

    Ler →6 seções10 min
  15. Tradução de Endereços: Base e Limite

    O suporte de hardware mais simples possível para memória virtualizada: um registrador guardando onde a memória de um processo começa e outro guardando seu tamanho; todo endereço que um programa usa é realocado e conferido contra o limite automaticamente.

    Ler →6 seções9 min
  16. Segmentação e Gerenciamento de Espaço Livre

    Dividir um espaço de endereçamento em segmentos realocados de forma independente (código, pilha, heap) evita desperdiçar memória com o vão sem uso entre um heap pequeno e uma pilha pequena, ao custo da fragmentação externa, o mesmo problema de gerenciamento de espaço livre que um alocador de propósito geral enfrenta.

    Ler →6 seções10 min
  17. Paginação e Tabelas de Páginas

    Em vez de alguns segmentos grandes e de tamanho variável, picar a memória em muitas páginas pequenas e de tamanho fixo, eliminando por completo a fragmentação externa, ao custo de precisar de uma tabela de páginas para registrar onde cada página de fato fica na memória física.

    Ler →6 seções9 min
  18. O Translation Lookaside Buffer

    Consultar uma entrada da tabela de páginas na memória a cada acesso deixaria a paginação catastroficamente lenta; o TLB é uma pequena cache de hardware totalmente associativa de traduções recentes, aplicando a mesma ideia de cache já vista para dados, agora à própria tradução de endereços.

    Ler →6 seções10 min
  19. Políticas de Substituição de Páginas

    Quando a memória física está cheia e uma página nova precisa entrar, algo tem de ser despejado: FIFO, ótimo e LRU são três respostas diferentes para 'qual página', comparadas na mesmíssima sequência de referências para ver quantas faltas de página cada uma de fato causa.

    Ler →6 seções10 min
  20. Paginação sob Demanda e Thrashing

    Carregar páginas só quando elas são de fato tocadas permite que um processo rode com menos memória física do que seu espaço de endereçamento completo exigiria, até que processos demais disputem memória de menos e o sistema passe mais tempo paginando do que calculando, um colapso chamado thrashing.

    Ler →6 seções11 min
  21. Arquivos, Diretórios e Inodes

    O trabalho real de um sistema de arquivos é transformar um array plano de blocos de disco em arquivos hierárquicos com nome: um inode guarda os metadados de um arquivo e os ponteiros de bloco que localizam seus dados, enquanto um diretório é só um arquivo especial que mapeia nomes em números de inode.

    Ler →6 seções9 min
  22. Implementação de Sistemas de Arquivos e Journaling

    Uma falha no meio de uma atualização de vários blocos (um novo inode, um novo bloco de dados, um bitmap atualizado) pode deixar inconsistentes as estruturas em disco de um sistema de arquivos; o journaling corrige isso escrevendo primeiro as mudanças pretendidas num log, tornando a atualização inteira recuperável como um único passo atômico.

    Ler →6 seções11 min
  23. Projeto Final: Acompanhando um Processo do fork() à Falta de Página e ao Disco

    Todos os mecanismos desta disciplina trabalhando juntos numa única linha do tempo concreta: um shell faz fork e exec de um programa, o escalonador o escolhe, ele toca uma página que ainda não está residente, e a falta de página resultante termina numa leitura real de disco pelo sistema de arquivos.

    Ler →6 seções12 min

Sistemas Operacionais I

Part of the Computer Science curriculum.

Sort
1

O Que É um Processo?

A abstração de processo transforma uma CPU física na ilusão de muitas: a memória, os registradores e os arquivos abertos de um programa em execução empacotados numa única unidade que o SO consegue pausar, retomar e equilibrar entre muitas outras.

2

A API de Processos: fork() e exec()

A separação do Unix entre \"crie uma cópia de mim\" (fork) e \"substitua minha memória por outro programa\" (exec): um projeto de dois passos genuinamente estranho, cuja estranheza é exatamente o que torna possíveis os shells e os pipes.

3

Estados de Processo e Troca de Contexto

Um processo está sempre em exatamente um de um punhado de estados (executando, pronto ou bloqueado), e o mecanismo que permite ao SO salvar o estado de CPU de um processo e carregar o de outro é a troca de contexto, a maquinaria sobre a qual a execução direta limitada é construída.

4

Escalonamento de CPU: Objetivos e Métricas

Antes de comparar políticas de escalonamento, é preciso fixar o que 'bom' significa: tempo de retorno, tempo de resposta e vazão muitas vezes competem entre si, então nenhuma política vence em todas as métricas ao mesmo tempo.

5

FCFS, SJF e o Efeito Comboio

O primeiro-a-chegar-primeiro-a-ser-atendido é trivialmente justo, mas deixa uma única tarefa longa bloquear todas as tarefas curtas atrás dela (o efeito comboio), enquanto o menor-tarefa-primeiro corrige de forma comprovada o tempo de retorno médio, ao custo de precisar conhecer o futuro.

6

Round-Robin e Fatias de Tempo

Dar a toda tarefa uma fatia de tempo pequena e fixa e revezar entre elas: excelente para o tempo de resposta, pior para o tempo de retorno que o SJF, e a primeira política desta disciplina que não precisa prever o futuro.

7

Escalonamento por Prioridade e Inanição

Deixar algumas tarefas furarem a fila resolve o problema de trabalho urgente esperando atrás de trabalho trivial, mas abre um novo: uma tarefa de baixa prioridade pode esperar para sempre se o trabalho de prioridade mais alta nunca parar de chegar.

8

Escalonamento com Filas Multinível com Realimentação

O escalonador que os sistemas operacionais reais de fato aproximam: várias filas de prioridade, tarefas rebaixadas por usarem CPU demais e promovidas periodicamente para evitar inanição, aprendendo o comportamento de uma tarefa pelo seu histórico recente em vez de perguntar de antemão.

9

Threads e o Espaço de Endereçamento Compartilhado

Uma thread é um fluxo de execução escalonável de forma independente que compartilha o espaço de endereçamento do seu processo com as threads irmãs: exatamente a mecânica em nível de sistema com que o modelo de concorrência com estado compartilhado, apresentado conceitualmente em outro lugar, é de fato construído.

10

O Problema da Seção Crítica e a Exclusão Mútua

O enunciado formal do perigo de condição de corrida já visto como modelo mental: uma seção crítica é qualquer código que toca estado compartilhado, e a exclusão mútua é a garantia de que no máximo uma thread está dentro dela por vez.

11

Locks e Primitivas Atômicas de Hardware

Um lock só funciona se adquiri-lo for ele mesmo imune à mesma condição de corrida que ele impede, e é por isso que locks reais são construídos sobre instruções atômicas fornecidas pelo hardware, como test-and-set e compare-and-swap, e não sobre load/store comuns.

12

Variáveis de Condição

Um lock sozinho não consegue deixar uma thread esperar que alguma condição se torne verdadeira sem ficar girando ocupada; uma variável de condição acrescenta exatamente isso: uma fila em que uma thread pode dormir, e um sinal que outra thread envia quando a espera acaba.

13

Semáforos

Um único contador inteiro com duas operações atômicas, wait e signal, geral o bastante para implementar um lock, a sinalização de uma variável de condição ou um limite de quantas threads podem prosseguir ao mesmo tempo: a única primitiva de Dijkstra que faz o trabalho de várias.

14

Deadlock: Condições e Detecção

Locks e semáforos resolvem condições de corrida, mas abrem um novo modo de falha: threads esperando umas pelas outras num ciclo, para sempre. É o deadlock, detectável construindo um grafo de alocação de recursos e rodando exatamente o mesmo algoritmo de detecção de ciclos já visto para grafos em geral.

15

Espaços de Endereçamento e Virtualização de Memória

Cada processo vê seu próprio espaço de endereçamento privado e contíguo, começando no endereço zero: uma ilusão que o SO mantém sobre uma única RAM física compartilhada, e o motivo de um bug nos ponteiros de um programa não conseguir corromper a memória de outro.

16

Tradução de Endereços: Base e Limite

O suporte de hardware mais simples possível para memória virtualizada: um registrador guardando onde a memória de um processo começa e outro guardando seu tamanho; todo endereço que um programa usa é realocado e conferido contra o limite automaticamente.

17

Segmentação e Gerenciamento de Espaço Livre

Dividir um espaço de endereçamento em segmentos realocados de forma independente (código, pilha, heap) evita desperdiçar memória com o vão sem uso entre um heap pequeno e uma pilha pequena, ao custo da fragmentação externa, o mesmo problema de gerenciamento de espaço livre que um alocador de propósito geral enfrenta.

18

Paginação e Tabelas de Páginas

Em vez de alguns segmentos grandes e de tamanho variável, picar a memória em muitas páginas pequenas e de tamanho fixo, eliminando por completo a fragmentação externa, ao custo de precisar de uma tabela de páginas para registrar onde cada página de fato fica na memória física.

19

O Translation Lookaside Buffer

Consultar uma entrada da tabela de páginas na memória a cada acesso deixaria a paginação catastroficamente lenta; o TLB é uma pequena cache de hardware totalmente associativa de traduções recentes, aplicando a mesma ideia de cache já vista para dados, agora à própria tradução de endereços.

20

Políticas de Substituição de Páginas

Quando a memória física está cheia e uma página nova precisa entrar, algo tem de ser despejado: FIFO, ótimo e LRU são três respostas diferentes para 'qual página', comparadas na mesmíssima sequência de referências para ver quantas faltas de página cada uma de fato causa.

21

Paginação sob Demanda e Thrashing

Carregar páginas só quando elas são de fato tocadas permite que um processo rode com menos memória física do que seu espaço de endereçamento completo exigiria, até que processos demais disputem memória de menos e o sistema passe mais tempo paginando do que calculando, um colapso chamado thrashing.

22

Arquivos, Diretórios e Inodes

O trabalho real de um sistema de arquivos é transformar um array plano de blocos de disco em arquivos hierárquicos com nome: um inode guarda os metadados de um arquivo e os ponteiros de bloco que localizam seus dados, enquanto um diretório é só um arquivo especial que mapeia nomes em números de inode.

23

Implementação de Sistemas de Arquivos e Journaling

Uma falha no meio de uma atualização de vários blocos (um novo inode, um novo bloco de dados, um bitmap atualizado) pode deixar inconsistentes as estruturas em disco de um sistema de arquivos; o journaling corrige isso escrevendo primeiro as mudanças pretendidas num log, tornando a atualização inteira recuperável como um único passo atômico.

24

Projeto Final: Acompanhando um Processo do fork() à Falta de Página e ao Disco

Todos os mecanismos desta disciplina trabalhando juntos numa única linha do tempo concreta: um shell faz fork e exec de um programa, o escalonador o escolhe, ele toca uma página que ainda não está residente, e a falta de página resultante termina numa leitura real de disco pelo sistema de arquivos.