Sei sulla pagina 1di 438

Sistemas Operacionais

Faculdade de Informática - PUCRS


Prof. Celso Maciel da Costa
Introdução

2
Introdução

„ Sistemas operacionais
– O que são?
» programas que controlam todos os recursos do
computador e fornecem a base para o
desenvolvimento dos programas de aplicação
– O que fazem?
» virtualizam os recursos de hardware
» gerenciam os recursos de hardware

3
Introdução

„ Partes básicas de um sistema


– hardware
– sistema operacional
– programas de aplicação
– usuários

4
Introdução

„ Tipos de Sistemas Operacionais


– Batch
– Time sharing
– Tempo real
– Distribuídos
– Paralelos

5
Introdução

„ Primeiros Sistemas
– Totalmente manuais
„ Sistemas Operacionais Batch
– Evolução dos sistemas iniciais (seqüenciamento
automático de jobs, multiprogramação,..)
– Normalmente possui como entrada uma
seqüência de jobs a serem processados
– O resultado do processamento é uma saída,
normalmente impressa
6
Introdução

Sistemas monoprogramados

Monitor

usuário

7
Introdução

Sistemas multiprogramados

SO

usuário1
usuário2
.
.
.

8
Introdução
Sistemas
monoprogramados

Sistemas
multipro-
gramados

9
Introdução

„ Sistemas Operacionais Batch(cont.)


– Grande problema:
» O usuário não interage com o sistema
» O programa é preparado e encaminhado para
execução
» Os resultados poderão demorar (minutos, horas, ...)
– A idéia básica é a de centralização do
processamento em CPD’s
– A tendência atual é para a distribuição
10
Introdução
„ Sistemas Operacionais Time Sharing
» Surgiram no início dos anos 60
» Se tornaram populares nos anos 70
» Existe uma comunicação on line entre o usuário e o
sistema
» O usuário submete requisições ao sistema, e recebe
as respostas imediatamente
» A interação é feita com o uso de terminais
» O sistema possui um Interpretador de Comandos,
que lê a linha de comando contendo o nome do
programa a ser executado
11
Introdução

„ Sistemas Operacionais Time Sharing (cont.)


– Após a execução de um comando, o
Interpretador de Comandos volta a ler o
terminal
– O usuário imediatamente compila e executa o
seu programa
– Muitos usuários compartilham o uso do
computador

12
Introdução

„ Sistemas Operacionais de tempo Real


– Usados para controlar um dispositivo em uma
aplicação dedicada
– Sensores coletam dados que são enviados ao
computador
– Os dados são analisados e são enviados sinais
de resposta
– Em muitas aplicações o tempo de resposta é
vital
13
Introdução
„ Sistemas Operacionais Distribuídos
» Avanço tecnológico (microprocessadores,
tecnologias de redes rápidas,..) aproximou as
máquinas paralelas e as redes de computadores
» Um SOD é formado por um conjunto de nodos
(processador/memória/periféricos?), sendo que em
cada nodo existe um núcleo de sistema operacional)
» A comunicação entre os diferentes nodos se faz por
troca de mensagens (ambientes sem
compartilhamento de memória) ou por operações
read remoto e write remoto (com memória virtual
compartilhada)
14
Introdução

„ Sistemas Operacionais Distribuídos x


Paralelos
» Distribuídos: Projetados para muitos usuários
trabalharem conjuntamente (compartilhamento de
recursos)
» Paralelos: Possui como objetivo obter velocidade na
resolução de um único problema

15
Introdução
Visão Esquemática do funcionamento de um SO
Chamadas de sistema
Usuário

SO

Hardware
Interrupções
16
Organização de
Sistemas Operacionais

17
Organização dos SO

„ Principais funções
– Gerência de Processos
– Gerência de memória
– Escalonamento
– Gerência de recursos (contabilização)
– Proteção (controle de acesso)

18
Organização dos SO

„ Monolíticos
„ O SO é organizado como uma coleção de processos
seqüenciais cooperantes, que recebem as solicitações
dos usuários (chamadas de sistema), as executam e
devolvem um resultado

Usuário Usuário ...

rotina
---
---
---

19
Organização dos S.O.

„ Hierárquica
– o sistema operacional é organizado como uma
hierarquia de níveis
– Ex. THE, construído pelo Dijkstra em 1968

20
Organização dos S.O.

„ Máquinas virtuais
– o kernel do sistema implementa não a
multiprogramação, mas máquinas virtuais
– Ex. VM/370 da IBM

21
Organização dos SO
Micro Kernel
• Modelo cliente/servidor
• Clientes (programas de aplicação) solicitam serviços
• Os serviços são implementados num nível acima do kernel, por
servidores

usuario servidor usuario servidor ...

serviço
resposta
kernel

22
Windows NT

„ Micro kernel
„ Baseado no modelo cliente/servidor
„ Subsistemas de ambientes (Servidores)
„ Executivo

23
Windows NT

Cliente
Cliente Cliente
Os/2
Win32 POSIX

Servidor
Subsistema Servidor Servidor
de Ambientes Os/2
Win32 POSIX
(Processos Servidores)

Modo Usuário

Modo Kernel

EXECUTIVO

24
Windows NT

„ Servidores
– Subsistemas protegidos
– Processos independentes
– Cada um com sua própria memória
– Comunicação por troca de mensagens (LPC)
– Cada subsistema fornece uma API específica de
um SO
– Servidores: POSIX, OS/2, DOS, Win16, Win32
25
Windows NT

„ Servidor Win32
– Torna disponível aos usuários a API win32
– Fornece a interface gráfica do NT
– Controla as entradas e saídas do Win32
– Controla as entradas e saídas dos demais
servidores

26
Windows NT

„ Executivo
– É o kernel do sistema NT
– Funções:
» Gerenciar de objetos
» Gerenciar processos
» Implementar LPC
» Gerenciar memória
» Tratar interrupções, escalonar processos
» Gerenciar I/O
27
Arquitetura do Sistema

28
Minix

„ Compatível com Unix V7


„ Escrito em C
„ Roda em PC
„ Escrito por Tanenbaum

29
Estrutura interna do Minix

Init user user ...

MM FS NetS

disk TTY clock system


task task task task ...
Process management

30
Unix

„ Visão Geral
– Arquitetura
– Shell
– Sistema de Arquivos
– Núcleo

31
Unix

Shell

núcleo

hardware

32
Unix - Arquitetura do Sistema
Programas Biblioteca
Nível Usuário
Nível Núcleo
Interface

Sub-sistema de Comunicação
arquivos Sub-sistema
de gerência
Cache Scheduling
de processos
Carac. Blocos
Ger. Memória
Drivers

Hardware
33
Revisão de Aspectos
Básicos

34
Revisão de Aspectos Básicos
Interrupções
„ Interrupções
– permite que módulos interrompam processamento
normal do processador
» gerado pelo programa
„ divisão por zero, referência a memória fora do espaço
permitido, etc.
» timer
» entrada e saída - sinalização de final de operação de E/S ou
condição de erro
» falha de hardware

35
Revisão de Aspectos Básicos
Interrupções
„ Tipos de interrupções
– externas ou internas
„ Externas
– Originadas por periféricos ou eventos exteriores
(tempo real)
Funcionamento geral de um periférico
while ( true )
{
receber ordem da CPU
executar a ordem
sinalizar a CPU
}

- os periféricos sinalizam a CPU


com o mecanismo de interrupção 36
Revisão de Aspectos Básicos
Interrupções
„ Internas
– relógio
– erro
– software (chamada do sistema)

„ Relógio
– permite a gerência do tempo pelo sistema
operacional
» scheduling
» disparo de um programa em um tempo determinado
» contabilidade

37
Revisão de Aspectos Básicos
Interrupções
„ Erro
– overflow
– violação de memória
– instrução inválida
– etc.

„ Software
– instrução especial (int, trap, ...)
– o programa para de executar
– o sistema operacional começa
– a executar o serviço solicitado pelo programa

38
Revisão de Aspectos Básicos
Interrupções
„ Processamento de interrupções
– dispositivo interrompe processador
– processador acaba execução da instrução atual
– processador testa existência de interrupção
– transferência de controle
» processador salva estado atual
» carrega contador de programa com endereço da rotina de
tratamento
» transfere controle para a rotina de tratamento
– rotina de tratamento executa … acaba
– restaura estado anterior
– retorna a execução da rotina interrompida 39
Introdução
Visão Esquemática do funcionamento de um SO
Chamadas de sistema
Usuário

SO

Hardware
Interrupções
40
Funções de um
Sistema Operacional

41
Funções de um SO

„ Gerência de processos
„ Gerência de memória
„ Gerência de I/O
„ Gerência de Arquivos
„ Sistema de Proteção
„ Comunicação
„ Interpretador de Comandos

42
Funções de um SO

„ Gerência de processos
– processo é um programa em execução
– entidade ativa, tem um program counter associado
– um processo executa sequencialmente até sua terminação
– dois processos podem estar executando mesmo programa -
duas sequencias independentes de execução
– sistema consiste de coleção de processos
» alguns do SO, outros do usuário
» processos executando de maneira concorrente, disputando CPU

43
Funções de um SO

„ Gerência de processos
SO é responsável por
– criação e deleção de processos
– suspensão e retomada de processos
– prover mecanismos para sincronização de processos
– prover mecanismos para comunicação de processos
– prover mecanismos para tratar deadlock

44
Funções de um SO

„ Gerência de memória
– programas são carregados em memória, executando em
processos
– para maximizar o uso de CPU, vários processos são mantidos
em memória, chaveando o contexto entre eles
– Sistema operacional deve
» controlar quais regiões de memória são utilizadas e por qual processo
» decidir qual processo deve ser carregado para memória, quando
espaço for disponível
» alocar e desalocar espaço de memória

45
Funções de um SO

„ Gerência de I/O
– SO deve “esconder” as peculiaridades de
dispositivos de hardware específicos
– device drivers para os dispositivos específicos
fazem parte do SO
– atividades
» instalação e desinstalação lógica de dispositivo
» leitura, gravação

46
Funções de um SO

„ Gerência de Arquivos
– oferece a abstração de arquivos (e diretórios)
– atividades suportadas
» criação e deleção de arquivos e diretórios
» primitivas para manipulação
» mapeamento para memória secundária

47
Funções de um SO

„ Sistema de Proteção
– controla acesso de processos ou usuários aos
recursos do sistema
» proteção de memória, CPU, operação dual
» controle de acesso

48
Funções de um SO

„ Comunicação remota
– facilidades para envio/recepção e protocolos de
comunicação
– atividades
» criar, deletar conexões
» mandar e receber mensagens

49
Funções de um SO

„ Interpretador de Comandos
– interface com o usuário
» modo texto
„ interpretador de linha de comando
„ shell do unix
» gráfico
„ machintosh
„ windows

50
Chamadas de Sistema

51
Chamadas de sistema

„ interface entre o programa que está


executando e o sistema operacional
– funções do SO disponíveis aos programas
„ geralmente implementadas com o uso de
instruções de baixo nível

52
Chamadas de sistema

„ Controle de processos
– criar, terminar
– carregar, executar
– espera por evento, sinalização
– espera tempo
– alocar e liberar memória

53
Chamadas de sistema

„ Manipulação de arquivos
– criar, deletar
– abrir, fechar
– ler, escrever
– posicionar

54
Chamadas de sistema

„ Manipulação de dispositivos
– alocar dispositivos, liberar dispositivo
– ler, escrever
„ Manutenção de informação do sistema
– e.g.: ler, setar a hora
„ Comunicação
– criar, deletar canais de conexão
– transferir informação
55
execução em
modo usuário

chamada de
sistema retorno

execução em selecionado
modo núcleo

bloqueio
pronto
desbloqueio

Transição de estados de um processo em uma chamada de sistema

56
Biblioteca
Programa

read ( int fd, char *b, int l )

{

msg m;
read ( fd, $b, 20)
m->td = fd;
m->b = b;
m->l = l;
m->op = READ;
move m, regA;
trap #12;
}
57
Vetor interrupções

do_read: desabilitar int


salvar contexto

do_read

58
Chamadas de sistema - Unix
„ divididas em dois grandes grupos:
– controle de processos, manipulação de arquivos
Programas Biblioteca
Nível Usuário
Nível Núcleo
Interface

Sub-sistema de Comunicação
arquivos Sub-sistema
de gerência
Cache Scheduling
de processos
Carac. Blocos
Ger.
Drivers Memória

59
Hardware
Chamadas de sistema - Unix
Manipulação de arquivos

. open . pipe

. close . link

. read . unlink

. write . lseek

. create

60
Chamadas de sistema - Unix
Controle de processos

. fork

. wait

. exit

. exec

. kill

. signal

61
Chamadas de sistema

„ Implementação
– Depende do computador
– Exemplo:
» instrução especial transfere o controle para o SO
» chamada de uma rotina especial para executar o
serviço

62
Chamadas de sistema

„ Passagem de parâmetros
– através de registradores
» Problema: o número de parâmetros é limitado ao
número de registradores
– através de um bloco de memória
» o endereço do bloco de memória é passado em um
registrador

63
Processos
Concorrentes

64
Processos Concorrentes

„ Em sistemas com multiprogramação


– uso da CPU compartilhado entre os diferentes
programas
– ilusão de paralelismo ( pseudo-paralelismo)
„ um processo é um programa em execução, incluindo os
valores dos registradores, o valor do PC, o valor das
variáveis, etc.
„ cada processo tem sua própria CPU virtual

65
running

selecionado
interrupção

ready blocked
evento

Grafo de transição de estados de processos

66
Escalonamento

„ Filas de escalonamento
– Sistemas Uniprocessador
„ um processo running
„ demais processos aptos a executar esperam pela CPU
» fila ready: contém os processos aptos a rodar
» filas de dispositivos: contém os processos esperando
I/O
» filas de eventos: contém os processos bloqueados a
espera de eventos (ex. passagem de tempo)

67
Escalonamento

„ Filas de escalonamento(cont.)
– Sistemas multiprocessadores
» memória comum
„ Uma única fila de processos aptos à rodar;
„ Uma fila para cada processador;

» memória distribuída
„ uma fila em cada processador

68
Exemplos de Implementação de
Filas
Ready: Last

Desc0 Desc5 Desc9


First

Disco0 First Desc7 Desc13

Last

Disco1 First

Last Desc12

69
Process Control Block
„ Representação de um processo para o SO:
– estado do processo: ready, running, blocked ...
» Estado também pode ser representado através da fila em que o processo se
encontra
– program counter
– registradores da CPU
– informação de esclonamento: depende do algoritmo - prioridades, ponteiros
para filas ...
– Informação para gerência de memória: valor de registradores base e limite,
páginas, ...
– Informação de contabilização: tempo de CPU utilizada, limites, ...
– informação de estado de I/O: lista de dispositivos alocados ao processo,
arquivos abertos, ...

70
Escalonamento da CPU
„ Multiprogramação
– Vários programas na memória
– CPU compartilhada pelos mesmos
– A execução de um programa é uma seqüência
de execução e espera por I/O
– Quando o programa faz I/O a CPU é entregue a
outro programa
„ Escalonamento
– É a troca da CPU entre os vários programas na
memória prontos para executar
71
Escalonadores
„ Implementam a Política de Escalonamento
– Escalonadores de Longo Termo
» Sistemas Batch
„ programas submetidos são armazenados em disco
„ o escalonador de Longo Termo seleciona programas do
disco e os carrega na memória para execução
„ Não existem em sistemas interativos (Unix, Dos,
Windows, ...)
– Escalonadores de Pequeno Termo (Escalonadores da
CPU
» seleciona um processo, entre os aptos, e o dispara
– Diferença: Freqüência de execução
72
Escalonadores

„ Dispatcher
– Entrega a CPU para o processo selecionado
pelo Escalonador de Pequeno Termo
(Escalonador da CPU)
» carrega os registradores gerais (da pilha, do
descritor,..) nos registradores de máquina
» carrega o Program Counter (dispara a execução)

73
Algoritmos de Scheduling

„ Critérios para escolha de algoritmos


– utilização de Cpu: mantê-la ocupada o máximo de
tempo possível
– No. de jobs executados por unidade de tempo
(throughput) (Ex. jobs grandes => 1 por hora, jobs
pequenos => muitos por segundo)
– tempo ocorrido desde a submissão de um job até seu
término (turnaround time) (geralmente limitado por i/o)

74
Algoritmos de Scheduling

„ Critérios para escolha de algoritmos.


(cont.)
– tempo de espera (waiting) (tempo na fila
ready)
– tempo de resposta (sistemas interativos)
(tempo de turnaround pode não ser o melhor
critério)

75
Algoritmos de Scheduling

„ Objetivos de um algoritmo.
– maximizar utilização da CPU
– maximizar No. de programas executados por
unidade de tempo
– minimizar tempo de turnaround
– minimizar tempo de resposta (melhor
minimizar a variância do que a média em
sistemas time-sharing)

76
Algoritmos de Scheduling

„ Algoritmo 1: First-Come-First-Served
– “Primeiro processo que requisita a CPU é o
primeiro que a recebe”
» 1. Processo pronto para executar entra no final
da lista ready
» 2. Quando a CPU é liberada é alocada para o
primeiro da lista

77
Algoritmos de Scheduling

„ Algoritmo 1: First-Come-First-Served

Ex.: Job Tempo


1 24
2 3
3 3

Chegada: 1, 2, 3
Job1 Job2 Job3
0 24 27 30
78
Algoritmos de Scheduling

„ Algoritmo 1: First-Come-First-Served
Tempo de turnaround
Job 1 : 24
Job 2 : 27
Job 3 : 30
Média : (24+27+30) = 27
1 Job CPU bound
Muitos Jobs I/o bound

Baixa performance.
79
Algoritmos de Scheduling

„ Algoritmo 1: First-Come-First-Served
Como seria o tempo de turnaround para chegadas:
Job 2
Job 3
Job 1 ??
Média: ?

E o waiting time ?

80
Algoritmos de Scheduling
„ Algoritmo 1: First-Come-First-Served
– CPU Bound prende a CPU
– Todos os outros Jobs tem seu I/O completado e
esperam na fila ready
– enquanto esperam, dispositivos estão desocupados
– CPU Bound requisita I/O
– os outros Jobs executam rapidamente, requisitam
I/O
– CPU Bound recebe o processador

– particularmente problemático para sistemas time- 81


sharing
Algoritmos de Scheduling

„ Algoritmo 2: Shortest-Job-First
– Associa a cada processo o seu próximo tempo de
ocupação de CPU
– Quando a CPU esta livre é atribuída ao processo
com o menor tempo de CPU
Ex.:
Processo Próximo tempo Proc4 Proc1 Proc3 Proc2
1 6
2 8
3 7
0 3 9 16 24
4 3 . Executando processos pequenos antes diminui
mais seus tempos de espera do que aumenta os
tempos de espera dos processos grandes
82
Algoritmos de Scheduling

„ Algoritmo 2: Shortest-Job-First
– waiting time: 7
– waiting time se fosse FCFS: 10.35

83
Algoritmos de Scheduling

„ Algoritmo 2: Shortest-Job-First
– Problema do SJF
» Determinar próximo tempo de CPU para cada
processo

Sistemas Batch (Long Term Scheduler)


Tempo limite do processo

Scheduling da CPU (Short Term)


?
Estimar o tempo

84
Algoritmos de Scheduling

„ Algoritmo 2: Shortest-Job-First
– Determinar próximo tempo de CPU para
cada processo
– estimar tamanho do próximo cpu burst com
base nos tempos passados de cpu
τn+1 = α tn + (1-α) τn
» tn : último tempo de cpu amostrado
≈ τn : último valor previsto
≈ τn+1 : valor previsto para próxima vez
≈ α : fator de peso entre amostrado e passado 85
Algoritmos de Scheduling

„ Algoritmo : baseado em Prioridades


– cada job tem uma prioridade associada
– cpu alocada ao job de maior prioridade
– caso de prioridades =s, adota FCFS
– SJF é um caso especial
» onde burst de cpu estimado é o inverso da
prioridade

86
Algoritmos de Scheduling

„ Algoritmo : baseado em Prioridades


» existe um campo de variação (0..7), (0..N)
» Alguns sistemas 0 é a maior, outros 0 é a menor
» podem ser internas ou externas
„ internas: espaço de memória necessária arquivos
abertos, etc. (Ex.: sistema Pascal)
„ externas: externas ao sistema operacional Ex.: tipo do
programa, tamanho, fatores políticos, etc.

87
Algoritmos de Scheduling

„ Algoritmo : baseado em prioridades


– e processos de baixa prioridade
– Problemas ?

88
Algoritmos de Scheduling

„ Algoritmo : baseado em prioridades


– Problemas: postergação indefinida
– Solução: de tempos em tempos incrementar
a prioridade do processo.
– Ex.: de prioridades (0.. 127) => mais alta
– incrementar um processo com prioridade 0
de 1 a cada 15 minutos ==> 32 horas para
rodar

89
Algoritmos de Scheduling

„ Algoritmos Preemptivos.
– FCFS, SJF, prioridades:
» não preemptivos, como descritos
» processo somente perde o processador quando
termina ou quando requisita I/O
– Questão: que fazer quando chega na fila
ready um processo com prioridade maior do
que o que está rodando?

90
Algoritmos de Scheduling
„ “Preemptar ou não Preemptar”.
– Preemptar:
» um processo chegando na fila ready tem sua
prioridade comparada com a do processo que
está rodando.
» se for maior: ganha a cpu
» se for menor: fica na fila
– Em sistemas time-sharing o Scheduler deve
ser peemptivo ou não?
» Resposta: Sim, para evitar que um processo
possa prender a CPU por muito tempo.
91
Algoritmos de Scheduling
„ “Preemptar ou não Preemptar”.
– Ex.: de Preempção (SJF)

Processo Chegada Tempo


1 0 8
2 1 4
3 2 9
4 3 5
proc1

2 4 1 3

0 1 5 10 17 26
preempção
92
Algoritmos de scheduling

– Ex.: de Preempção (SJF) (cont.)


» Tempo médio de execução:
„ processo 1 17 - tempo de chegada (0) = 17
„ processo 2 5 - tempo de chegada (1) = 4
„ processo 3 26 - tempo de chegada (2) = 24
„ processo 4 10 - tempo de chegada (3) = 7
„ tempo médio = (17+4+24+7)/4 = 13

93
Algoritmos de Scheduling

„ Ex.: Sem Preempção (SJF) (cont.)

1 2 4 3

0 8 12 17 26
(8-TC)+(12-TC) +( 26-TC) + (17-TC) onde TC=tempo de chegada

(8+11+24 + 14)/4 = 57/4 = 14.25

94
Algoritmos de Scheduling

„ Round-Robin:
– Sistemas time-sharing
– quantum ou time slice (10-100 miliseg.)
– lista ready é uma fila circular
Ex.:
processo tempo
1 24
2 3
1 2 3 1 1 1 1 1
3 3

Time-slice:4 4 7 10 14 18 22 26 30
Média: 47/3 ~16
95
Algoritmos de Scheduling

„ Round-Robin
– Overhead: salvamento de contexto depende
de :
» velocidade de memória
» número de registradores
» existência de instruções especiais: ex. mover
todos os registradores
– tempo típico: 10-100 microsegundos

96
Algoritmos de Scheduling
„ Round-Robin
– Quantum: 12 unidades
– tempo de execução do processo: 10 unidades
NÃO TEM OVERHEAD
- Quantum de 6 unidades
- Tempo de execução: 10 unidades

1 TROCA DE CONTEXTO

Quantum muito grande ==> FCFS


97
Algoritmos de Scheduling

„ Múltiplas filas
– processos são classificados em grupos
– uma fila para cada grupo
– cada fila pode ter seu próprio algoritmo
– cada fila pode ter prioridade absoluta sobre as
demais filas com prioridades menores
– alternativa: haver um slice entre as filas

98
Algoritmos de scheduling

„ Múltiplas filas com reavaliação


– os processos se movem entre as filas
– parâmetros:
» no. de filas
» método para aumentar processos nas filas
» método para diminuir processos nas filas
» método para determinar em que fila o processo deve
entrar

99
Scheduling no sistema Pascal
Concorrente
„ três filas de prioridades
– alta: prioridade 0
– média: prioridade 1
– baixa: prioridade 2
„ prioridade 2: qdo. o processo é criado
„ prioridade 1: qdo. o processo pede I/O
„ prioridade 0: qdo. o processo pede acesso a
um monitor
100
UNIX

Scheduling
UNIX - Diagrama de Estados de Processo

102
Estados de processos no UNIX

„ Criação de um processo:
– processo pai executa fork
– filho é criado e entra no estado created
– quando decidido sobre sua alocação entra no
estado ready to run, em memória ou swaped

103
Estados de processos no UNIX

„ Criação de um processo:
– processo 1, init, é criado no início do sistema
– quando um usuário interativo entra no sistema, o
processo init cria um processo para tratar do
usuário
– este processo do usuário atende os pedidos do
usuário, criando outros processos

104
Estados de processos no UNIX

„ Escalonamento do processo recém criado:


– escalonador escolhe processo para executar
– processo escolhido sai de ready to run e passa
para kernel running
– processo acaba processamento da chamada fork
feita pelo pai
– retorna para o modo user running
– prossegue execução

105
Estados de processos no UNIX

„ Chamada de sistema:
– quando processo executa chamada de sistema
» sai do modo user running e passa para kernel running
» no caso de pedido de IO processo entra no modo
asleep
– quando IO está pronto
» interrupção acontece e o processo bloqueado é
passado para ready to run
» antes de retornar a user running, o processo
interrompido pode perder o processador (ser
preemptado) 106
Estados de processos no UNIX
„ Interrupção e preempção:
– relógio do sistema pode interromper, ou IO fica
pronto e interrompe
– o processo entra no modo kernel running
– o tratador de interrupções acaba o tratamento da
mesma
– antes de retornar para user running,
núcleo pode preemptar o processo em favor de
outro com maior prioridade
– primeiro processo entra no modo preempted
107
(mesmo que ready to run)
Estados de processos no UNIX
„ Preempção:
– só pode acontecer quando o processo está para
retornar para user running
– chamada de sistema de um processo (kernel
running) não pára no meio em favor de outro
processo
– como algumas chamadas de sistema são
“pesadas” - o sistema não é adequado para
tarefas tempo real

108
Estados de processos no UNIX

„ Saída de processo:
– quando processo completa, ele faz chamada de
sistema exit
– processo passa para kernel running e então para
zombie
– eventos externos podem indicar que processo
tem que sair (exit)

109
Scheduling no UNIX

„ Round robin com múltiplos níveis e


feedback
„ vários níveis de prioridades
„ níveis básicos:
– kernel
– usuário
estes são ainda subdivididos

110
Scheduling no UNIX

„ Níveis do kernel
– prioridades altas, não interrompíveis
» processos não perdem CPU por tempo (preemptados)
» ex.:swaper, waiting for disk IO, waiting for buffer,
waiting for inode,
– prioridades baixas, interrompíveis
» ex.: waiting for tty input, …output, waiting for child
exit
„ Níveis do usuário
– user level 0, …, user level n 111
Scheduling no UNIX

„ Política:
– políticas normais: fairness
– incentivar a liberação de recursos

112
Scheduling no UNIX
„ Política de prioridades para processos no
modo núcleo
– associa prioridade ao processo antes de ir para
estado asleep
– relaciona valor fixo de prioridade à razão do
processo ir para asleep
– quando processo é escalonado
» considera a prioridade do modo kernel
» entra em kernel running
» quando passa para user running, restaura prioridade
do processo para modo usuário 113
Scheduling no UNIX
„ Política de prioridades para processos no
modo núcleo
– níveis de prioridade
» associados de forma que maior prioridade dada a
processos com maior probabilidade de liberar
recursos
» evitar gargalos no sistema

114
Scheduling no UNIX
Níveis de prioridades Processos

swapper
Não Waiting for disk io
Priori- interrom- Waiting for buffer
dades píveis
Waiting for inode
no modo
kernel Waiting for tty input
prioridade

Interrom- Wait for tty output


píveis Wait for child exit
Waiting for inode

Priori- User level 0


dades User level 1
no modo

usuário
115
User level n
Scheduling no UNIX

„ Política de prioridades para processos no


modo usuário
– em cada segundo, clock interrompe 60 vezes
– contador de uso de CPU é incrementado a cada
vez
– a cada segundo:
» ajusta o uso recente da CPU
„ decay(CPU) : uso de CPU = uso de CPU/2
„ recalcula prioridades dos processos ready to run
– priority = uso de CPU/2 + prioridade base do
116
processo de usuário
Scheduling no UNIX
Proc A Proc B Proc C
Priority CPU Priority CPU Priority CPU

60 0 60 0 60 0
1
2

60
75 30 60 0 60 0
1
2
...
30 60
67 15 75 30 60 0
1
2

60
63 7 67 15 75 30
8
9
..
67
76 33 63 7 67 15
8
9

67 117
68 16 76 33 63 7
Scheduling no UNIX
Proc A Proc B Proc C
Priority CPU Priority CPU Priority CPU

60 0 60 0 60 0
1
2

decay 60
75 30 60 0 60 0
1
60 + CPU/2 2
...
decay 30 60
67 15 75 30 60 0
1
60 + CPU/2 2

60
63 7 67 15 75 30
8
9
..
67
76 33 63 7 67 15
8
9

67 118
68 16 76 33 63 7
Scheduling no UNIX

„ Extensão: Fair share Scheduler


– Dividir capacidade computacional da máquina
– Grupos
» processos pertencem a grupos
» além de contabilizar uso da CPU por processo,
contabiliza por grupo
„ decay(CPU) : uso de CPU = uso de CPU/2
„ decay(Group) : uso de CPU do grupo =
uso de CPU do grupo/2
„ recalcula prioridades dos processos ready to run
– priority = uso de CPU/2 + uso de CPU do grupo /2
119
+ prioridade base do processo de usuário
Scheduling no UNIX
Proc A Proc B <- mesmo grupo -> Proc C
Priority CPU Group Priority CPU Group Priority CPU Group

60 0 0 60 0 0 60 0 0
1 1
2 2
… ...
60 60
90 30 30 60 0 0 60 0 0
1 1 1
2 2 2
… ... ...
60 60 60
74 15 15 90 30 30 75 0 30
16 16
17 17
… ...
75 75
96 37 37 74 15 15 67 0 15
16 1 16
17 2 17
... … ...
75 60 75
78 18 18 81 7 37 93 30 37
19 19
20 20
… ...
78 78 120
98 39 39 70 3 18 76 15 18
MINIX

Scheduling
Processos

Layer
User User User
4 Init process process process ... User processes

Memory File Network


3 manager system server ... Server processes

Disk Tty Clock System Ethernet


2 task task task task task ... I/O tasks

1 Process management

Kernel

122
Scheduling

Rdy_head Rdy_tail

2 USER_Q 3 5 4 USER_Q 2

1 SERVER_Q FS MM SERVER_Q 1

0 TASK_Q Clock TASK_Q 0

123
Scheduling

„ TASK_Q
– fila de prioridade máxima
– o(s) processo(s) não perdem o processador por
tempo.

124
Scheduling

SERVER_Q
Fila de prioridade média na qual executam os servidores
do sistema. Os processos nesta fila não perdem o
processador por tempo.

125
Scheduling

USER_Q
fila de prioridade mais baixa na qual executam os
processos dos usuários. O algoritmo usado nesta fila é o
round-robin.

126
proc.c - Principais funções

„ void pick_proc()
– decide qual processo deverá ser executado no
momento. Percorre as filas de processos a
procura de um processo a ser executado
conforme a prioridade.

127
proc.c - Principais funções

void ready(struct proc *rp)


•adiciona o processo rp em uma das filas de processos
para torná-lo runnable.
•Esta função verifica em qual fila o processo se encaixa e
adiciona-o no final da fila correspondente.

128
proc.c - Principais funções

void unready(struct proc *rp)


•retira o processo rp da sua fila de processos.
•Esta função descobre a qual fila pertence o processo rp,
procura-o na fila e retira-o, tirando a sua condição de
runnable.

129
proc.c - Principais funções

void sched()
•escalona a fila de processos do usuário.
•esta função retira o processo indicado pela rdy_head na
fila de processos de usuário,
•faz com que rdy_head aponte para o próximo processo e
•aloca o processo anterior (rodando) no final da fila do
usuário.

130
proc.c - Principais funções

void sched()
rdy_head rdy_tail

USER_Q 3 5 4 USER_Q
. .
. .
. .

rdy_head rdy_tail

USER_Q 5 4 3 USER_Q

131
Multiprocessor Scheduling

„ Sistemas multiprocessadores
– fracamente acoplados, ou clusters
» cada sistema tem memória própria e canais de IO
– processadores especializados
» como processadores de IO
» existe um processador mestre de propósito geral que
controla os escravos
– processadores fortemente acoplados
» conjunto de processadores que compartilham
memória principal sob controle integrado de um
132
sistema operacional
Multiprocessor Scheduling

„ Fortemente acoplados - homogeneos


– tratar processadores como recurso conjunto e
associar processos a processadores sob
demanda
– associação estática ou dinâmica
» estática: processo roda no mesmo processador
» dinâmica: em diferentes CPU burts processo pode
ocupar diferentes processadores

133
Multiprocessor Scheduling

„ Abordagens mestre-escravo e pares


– mestre escravo:
» funções do kernel rodam sempre em um processador
» outros processadores rodam só processos de usuário
» mestre faz escalonamento
» se escravo precisa serviço (chamada de sistema), faz
pedido ao mestre
» desvantagens:
„ mestre pode ser gargalo de desempenho
„ falha do mestre pára sistema
134
Multiprocessor Scheduling

„ Abordagens mestre-escravo e pares


– pares:
» SO executa em qualquer processador
» cada processador faz escalonamento para si da fila
ready comum
» mais complicado:
„ garantir que dois processadores não escolham mesmo
processo
„ sincronização no acesso a estruturas comuns

135
Processos
Concorrentes

136
Processos Concorrentes

„ Processos pesados
– Processos tradicionais
– Possuem uma thread inicial que começa a sua
execução (ex. main de um programa C)
– Normalmente carregados do disco para
execução
– Executam um código seqüencial

137
Controle de Processos

„ Processos leves (threads)


– Criados para permitir paralelismo
– cada um roda um código seqüencial
– Possuem sua própria pilha de execução e o seu próprio program
counter
– Compartiham o uso do processador
– Podem criar processos (threads) filhos
– Compartilham o mesmo espaço de endereçamento (dados globais)
– Podem estar em um dos estados ready, running, blocked

138
Controle de Processos

„ Hierarquia de processos
– um grafo de processos é uma árvore cujos
nodos correspondem a um processo
» uma aresta de um nodo Pi para um nodo Pj significa
que Pj foi criado por Pi
» Pi é o pai de Pj
» Pj é filho de Pi
» cada processo possui um pai, exceto o inicial
(ancestral)
» cada processo pode ter muitos filhos
139
Controle de Processos

P1

P2 P3

P5 P6
P4

Árvore de processos

140
Controle de Processos

„ Operações em processos
– criação de processos
» possibilidades de execução:
„ o pai executa concorrente com o filho
„ o pai espera que o filho acabe
» possibilidades de compartilhamento de dados
„ pai e filho compartilham todas as variáveis
„ pai e filho compartilham um subconjunto das variáveis do
pai

141
Controle de Processos

„ Exemplos
– UNIX
» filho é duplicata do pai
» execução concorrente de pai e filho
– DEC VMS
» carga de código do novo processo na criação
– NT
» ambos modelos

142
Controle de Processos
„ Término de processos
– um processo termina quando acaba a execução
de seu último comando
» pede ao SO para removê-lo com a chamada exit
– em circunstâncias especiais um processo pode
acabar antes de executar o seu último comando
– um processo pode causar a morte de outros
processos com primitivas especiais

143
Controle de Processos
„ abort (id), kill (id)
– id é a identificação do processo à terminar
– abort e kill são chamadas pelo pai do processo
id
– para poder matar, o pai necessita conhecer a
identidade do filho, que retorna na operação de
criação.
– id = fork()
» retorna em id a identificação do processo criado

144
Especificação de Concorrência

„ Construções fork e join


– Connway 1963
– Dennis e Van Horn 1966
– primeiras notações de linguagem para
especificar concorrência

145
Especificação de Concorrência

P0

fork

P1 P2

Construção fork

146
Especificação de Concorrência
FORK

P1 ;
fork l ;
.
.

l: p3 ;

- fork produz duas execuções concorrentes no programa


- uma começa no rótulo “l”
- a outra continua no comando seguinte ao fork
- divide uma computação em duas independentes

147
Especificação de Concorrência
„ JOIN
– combina várias execuções concorrentes em uma
– cada execução deve requisitar um join com as
demais
– algumas computações terminam antes de outras
– as que executa o join antes terminam, a última
continua
– existindo três computações, as duas primeiras
terminam, enquanto à última é permitido
continuar
– join tem um parâmetro que especifica o número
de computações
– deve ser executada atomicamente 148
Especificação de Concorrência

join com parâmetro

count = count - 1 ;
if count != 0
then quit ;

149
Especificação de Concorrência
Exemplo:
s1

s2 s3

s4

s5 Grafo de precedência de
s6
execução dos comandos
s1 a s7

s7

150
Especificação de Concorrência
s1;
count = 3 ;
fork l1 ;
s2 ;
s4 ;
fork l2 ;
s5 ;
go to l3 ;
l1: s3 ;
go to l3 ;
l2: s6 ;
go to l3 ;
l3: join count ;
s7 ;

Exemplo de programa usando fork/join

151
Especificação de Concorrência
„ Fork no sistema Unix
– Forma: id = fork() ;
– Duplica o processo que executa a chamada
– Ambos executam a instrução seguinte à chamada de
sistema
– Id, no retorno da chamada, contém no processo pai, o
identificador do processo filho criado
– Para o processo filho o valor da variável id será zero
– Pode-se selecionar o trecho de código que será
executado pelos processos com o comando if
– Não existe o comando join (a sincronização é feita com
wait()) 152
Exemplo de programa com fork
no Unix
main() {
int id ;

id = fork () ;
if (id != 0) {
printf(“Eu sou o pai\n”) ;
wait(0) ;
}
else
printf(“Eu sou o filho\n”) ;
}
153
Especificação de Concorrência
„ fork/join
– desestruturam um programa
– são semelhantes à comandos go to
– tornam difícil a compreensão do
programa

154
Especificação de Concorrência

„ Comando concorrente
– Dijkstra 1965
– construção de mais alto nível
– Forma:
» parbegin s1, s2, ... sn parend ;
„ todos os comandos entre o parbegin e o parend são
executados concorrentemente
„ o comando seguinte ao parend somente é executado
após todos os anteriores terem terminado

155
Programa que copia um arquivo f para um
arquivo g usando comando concorrente

var
f, g file of T ;
r, s of T ;
begin
reset (f)
read (f, r) ;
while (not EOF ) do
begin
s=r;
parbegin
write (g, s) ;
read (f, r) ;
parend ;
end ;
write (g, r) ;
end ;

156
Grafo de precedência apresentado anteriormente
programado com parbegin/parend

s1
s1 ;
parbegin
s3 ;
begin s2 s3
s2 ;
s4 ;
parbegin
s5 ; s4
s6 ;
parend ;
end ; s5 s6
parend ;
s7 ;
s7
157
Especificação de Concorrência

„ Comparação entre comando concorrente e


fork/join
– fork/join é mais poderosa
– comando concorrente é estruturado
– comando concorrente pode ser mais
facilmente adicionado a uma linguagem de
programação

158
Simulação de comando concorrente com fork/join

count = n ;
fork l2 ;
fork l3 ;
.
parbegin .
s1; .
s2; fork ln ;
s3; s1 ;
s4 ; go to lj ;
... l2: s2 ; go to lj ;
Sn; l3: s3 ; go to lj ;
parend; .
.
.
ln: sn ;
lj: join count ;

159
Exercício

s1

s2 s3

s4 ?

s5 s6 s8

s7

160
Resposta

s1 count1 = 2;
count2 = 3;
s1;
fork P1;
s2 s3 s2;
s4;
fork P2;
s5;
s4 go to P4;
P2: fork P3;
s6;
go to P4;
s5 s6 s8 P1: s3;
P3: join count1;
s8;
P4: joint count2;
s7 s7;

161
Multithreading

162
Processos Concorrentes

„ Processos leves (threads)


– cada um roda um código seqüencial
– Possuem sua própria pilha de execução e o seu próprio program
counter
– Compartiham o uso do processador
– Podem criar processos (threads) filhos
– Compartilham o mesmo espaço de endereçamento (dados globais)
– Podem estar em um dos estados ready, running, blocked

163
Threads e Processos pesados

164
Processos pesados
„ Acesso protegido a processador, outros
processos, arquivos, e recursos de IO

165
Threads
„ Têm estado de execução (running, ready, etc.)
„ Salva contexto da thread quando não executando
„ Tem stack de execução por thread
„ Acessa endereços de memória e recursos do
processo pesado que pertence
– todas threads pertencentes ao processo pesado
compartilham
– quanto uma thread altera um valor compartilhado, todas
percebem esta mudança
– arquivo aberto por uma thread está disponível a outras

166
Modelos de Processos Mono e
Multithreaded

Thread Control Block contém informações de prioridade 167


e de estado da thread
Benefícios de Threads vs
Processos Pesados
„ menor tempo para criar thread que
processo
– processo pesado: carregar código
– thread: código já em memória
„ menor tempo para terminar …
„ menor tempo para chavear contexto entre
duas threads (do mesmo processo) do que
chavear processos pesado diferentes
168
Benefícios de Threads
„ Exemplo: servidor de arquivos em uma LAN
„ servir vários pedidos em curto período
„ mais eficiente criar e destruir threads por
pedido que processos pesados
„ em máquinas SMP threads podem executar
paralelamente em diversos processadores

169
Benefícios de threads

„ Aplicação consiste de várias partes


independentes que não precisam rodar em
seqüência
„ cada parte - uma thread
„ quando uma thread estiver bloqueada por
IO, execução pode chaver para outra thread
da mesma aplicação - ao invés de chavear
para outro processo

170
Benefícios de Threads

„ Compartilhamento de memória e arquivos:


comunicação possível entre elas sem
invocar chamada de sistema
„ Necessidade de sincronizar atividades das
diversas threads para não causar
inconsistência nos dados compartilhados

171
Estados de Threads

„ Três estados chave: running, ready, blocked


„ Não tem estado swapped
– não existe swap de thread mas sim de todo
processo pesado
„ Terminação do processo pesado termina
todas as threads do mesmo

172
Threads a nível de usuário
User-Level Threads (ULT)
„ Núcleo do sistema trata
somente processos pesados
„ Gerência de threads feita por
aplicação utilizando uma
biblioteca
„ Chaveamento de threads não
requer privilégios do modo
kernel
„ escalonamento é específico da
aplicação
„ Ex.: biblioteca Pthreads
(ex.: sobre linux)
173
Bibliotecas de threads

„ Código para:
– criar e destruir threads
– passar mensagens entre threads
– escalonar a execução de threads
– salvar e retomar contexto

174
Atividades do Kernel para
threads a nível de usuário
„ Núcleo não trata threads mas processos
pesados
„ Quando thread faz chamada de sistema, todo
processo pesado será bloqueado
„ … para a biblioteca de threads, a thread
rodando estará ainda no estado running
„ … o estado das threads é independente do
estado do processo pesado

175
Vantagens e desvantagens de
threads a nível de usuário
„ Vantagens „ Desvantagens
– Chaveamento de – Maioria das chamadas de
sistema são bloqueantes - e o
threads não envolve kernel bloqueia todo processo
kernel: não troca de pesado - apesar de outra thread
modo do processo poder continuar
– Escalonamento pode – O núcleo só associa processos
pesados a processadores - duas
ser dependente da
threads do mesmo processo
aplicação: escolha de pesado não podem rodar em
algoritmo processadores diferentes
– Pode rodar em qualquer
SO, precisa da
biblioteca
176
Threads a nível de núcleo -
Kernel-Level Threads (KLT)
„ Gerência de threads feita no
núcleo
„ ao invés de uma biblioteca de
threads -> interface (chamadas)
para facilidades de threads
„ núcleo mantém informação de
contexto para threads e processos
pesados
„ chaveamento entre threads
envolve o núcleo
„ escalonamento baseado em
threads
„ Ex: Windows NT and OS/2 177
Vantagens e desvantagens
de thread no núcleo
„ Vantagens „ Desvantagens
– núcleo pode escalonar – chaveamento de threads
simultaneamente várias dentro do mesmo
threads do mesmo processo pesado
processo pesado em envolve o núcleo
diferentes processadores – impacto significante
– bloqueio a nível de thread
e não todo processo
pesado
– rotinas do SO podem ser
também multithreaded

178
Abordagem combinada
„ Criação de thread no modo
usuário
„ escalonamento e
sincronização no modo
usuário
„ programador pode ajustar
número de threads a nível
de núcleo
„ combinar melhor das
abordagens
„ Exemplo: Solaris

179
Solaris
„ Threads a nível de usuário - User-level threads
– invisíveis ao SO
– são a interface de programação
– uso de biblioteca
„ Threads do núcleo
– a unidade que pode ser despachada em um
processador e suas estruturas mantidas pelo núcleo
„ Processos leves: Lightweight processes (LWP)
– cada LWP suporta uma ou mais treads do usuário
(ULT) e mapeia para exatamente uma thread a nível
de núcleo (KLT)
– LWP são visíveis pela aplicação
180
Processo 2 é equivalente a abordagem ULT
Processo 4 is equivalente a abordagem KLT
181
Solaris
„ Várias Threads em um LWP
– > ULT
„ Uma thread por LWP
– -> KLT
„ Várias threads em várias LWPs
– criação, escalonamento e sincronização de threads a nível
de usuário
– número de LWPs conforme aplicação
– threads podem executar em paralelo em diferentes CPUs
– chamada de sistema bloqueante não pára toda task

182
Solaris
„ Várias Threads em um LWP
– > ULT
„ Uma thread por LWP
– -> KLT
„ Várias threads em várias LWPs
– criação, escalonamento e sincronização de threads a nível
de usuário
– número de LWPs conforme aplicação
– threads podem executar em paralelo em diferentes CPUs
– chamada de sistema bloqueante não pára toda task

183
Solaris: user-level thread states

(attached to a LWP)

184
Solaris: Lightweight Process
States

LWP states are independent of ULT states


(except for bound ULTs) 185
Programação Concorrente

„ Exemplos de programas concorrentes


parbegin
R := max(a, b);
S := max(c,d);
parend;
% nenhuma variável compartilhada pelos
dois processos, independentes

186
Programação Concorrente

„ Exemplos de programas concorrentes(cont.)


j := 10;
parbegin
print j;
j := 20;
parend;
» j é compartilhada pelos 2 processos; dependentes
» qual o valor impresso por print j? 10 ou 20?

“indeterminado”
187
#include <thread.h>
thread_t tid1,tid2;
int a ;
void * p0 (){
int i ;
for(i=0; i<1000000; i++)
{
a = a + 2 ;
}
}
void * p1 (){
int i ;
for (i=0; i<1000000; i++) {
a = a + 5 ;
}
}
main(){
int result ;
result=thr_create(NULL,0, p0,NULL,THR_NEW_LWP,&tid1);
result=thr_create(NULL,0, p1,NULL,THR_NEW_LWP,&tid2);
thr_join((thread_t)0,NULL,NULL);
thr_join((thread_t)0,NULL,NULL); 188
}
Seção crítica
Produtor-consumidor com buffer limitado

int buffer [n] ;


int i=0, j=0 ;
int k ;

parbegin
produtor::
repeat
“ produz um novo elemento k”
while (( i + 1) mod n = j) do {} % buffer cheio
bufffer[i] := k ;
i = i + 1 mod n ; % uso circular do buffer
until false; % loop infinito

189
Seção crítica
Produtor-consumidor com buffer
limitado(cont.)
consumidor:
repeat
while i = j do {} ; % buffer vazio
y =buffer[j];
j = j + 1 mod n;
...
“consome o item em y”
until false;
parend

190
Seção crítica

„ Produtor/consumidor com lista encadeada


type ITEM = ...
BUFFER = record
INFO: ITEM;
NEXT: pointer para buffer
var P: pointer para buffer;
C: pointer para buffer;
FIRST: pointer para buffer
NETXP, NEXTC: ITEM;

191
parbegin
PRODUCER::
new(P);
P.INFO := NEXTP;
P.NEXT := FIRST;
FIRST := P;
end;
CONSUMER::
while FIRST = NILL do skip;
C := FIRST;
FIRST := FIRST.NEXT;
NEXTC := C.INFO;
DISPOSE(C);
end;
parend;

192
4
4 3 2 1
5
FIRST = ^4
Dada a situação acima e a seqüência de passos abaixo
CONSUMER: C := FIRST => C = 4
PRODUCER: P.NEXT := FIRST => P.NEXT = 4
PRODUCER: FIRST := P => FIRST = 5
CONSUMER: FIRST : = FIRST.NEXT => FIRST = 4

– estado final:
» o elemento adicionado (5) foi perdido
» C e FIRST estão com o mesmo valor
» FIRST aponta para elemento consumido

193
Seção Crítica de Código

„ Causa do problema:
acesso “simultâneo” à lista por PRODUCER e
CONSUMER
„ Código de acesso é uma
SEÇÃO CRÍTICA (SC)
„ Solução: execução da SC de forma
mutuamente exclusiva

194
Seção Crítica de Código
„ Definição geral do problema da seção
crítica
– sistema com N processos, N > 1
– cada processo pode ter um código próprio
– os processos compartilham dados variáveis, de
qualquer tipo
– cada processo possui SC’s, onde atualizam os dados
compartilhados
– a execução de 1 SC deve ser de forma mutuamente
exclusiva no tempo
195
Seção Crítica de Código
„ Forma da solução: protocolo de entrada e
saída na SC
entry-section
código-seção-crítica
exit-section
– entry-section: garante que somente 1 processo
executa SC
– exit-section: permite que outro processo entre
na SC
196
Seção Crítica de Código

„ Requisitos para solução do problema da SC


– prover exclusão mútua
– progresso
» processos fora da SC não devem bloquear outros
processos
» somente os processos querendo entrar na SC
devem participar da seleção do próximo a entrar
» a seleção não deve ser postergada
indefinidamente

197
Seção Crítica de Código

„ Requisitos para solução do problema da


SC(cont.)
– espera limitada
» um processo espera um tempo limitado na entry-
section
– velocidades indeterminadas
» não se faz suposições sobre a velocidade relativa
dos processos

198
„ Soluções por SW para 2 processos
– algoritmo 1

var
TURNO: integer; % variável compartilhada; 0 ou 1
EU, OUTRO: integer; % constantes locais, com valores opostos (0,1 e 1,0)
repeat
while TURNO ≠ EU do skip; % mutexbegin
código-da-seção-crítica;
TURNO := OUTRO % mutexend
resto-do-código;
until false;

– resolve ?

199
#include <thread.h>
thread_t tid1,tid2;
int turn = 0 ;
int shared ;

void * p0 (){
int i ;
for(i=0; i<10; i++)
{
while(turn != 1 ) {} /* entra se turn = 1 */
shared =shared + 50 ;
printf("Thread1: INCREMENTEI \n");
turn = 0 ;
}
}
void * p1 (){
int i ;
for (i=0; i<10; i++) {
while(turn != 0 ) {} /* entra se turn = 0 */
printf("Thread2: SHARED: %d \n",shared);
turn = 1 ;
}
}
main(){
int result ;
result=thr_create(NULL,0, p0,NULL,THR_NEW_LWP,&tid1);
result=thr_create(NULL,0, p1,NULL,THR_NEW_LWP,&tid2);
thr_join((thread_t)0,NULL,NULL);
thr_join((thread_t)0,NULL,NULL);

200
„ Soluções por SW para 2 processos
– algoritmo 2
var
var flag[0..1] of boolean % variável compartilhada, inicializado com false
repeat
while flag[j] do skip; % mutexbegin
flag[i] := true ;
código-da-seção-crítica
flag[i] := false % mutexend
resto-do-código;
until false;

– resolve ?

201
#include <thread.h>
thread_t tid1,tid2;
int shared ; int flag [2];
void * p0(){
int i ;
for(i=0; i<1000000; i++){
while(flag [1] == 1 ) {} /* entra se flag [1] = 0 */
flag[0] = 1 ;
shared =shared + 5 ;
flag [0] = 0 ; }
}
void * p1(){
int i ;
for (i=0; i<1000000; i++) {
while(flag [0] == 1 ) {} /* entra se flag [0] = 0 */
flag [1] = 1 ;
shared = shared + 2 ;
flag [1] = 0 ;
}
}
main(){
int result ;
shared = 0 ; flag [0] = 0 ; flag [1] = 0 ;
result=thr_create(NULL,0,p0,NULL,THR_NEW_LWP,&tid1);
result=thr_create(NULL,0,p1,NULL,THR_NEW_LWP,&tid2);
thr_join((thread_t)0,NULL,NULL); thr_join((thread_t)0,NULL,NULL);
printf(“O valor de shared e : %d\n”, shared) ; 202
}
„ Soluções por SW para 2 processos
– algoritmo 3
var
var flag[0..1] % variável compartilhada, inicializado com false
repeat
flag[i] := true ;
while flag[j] do skip; % mutexbegin
código-da-seção-crítica;
flag[i] := false % mutexend
resto-do-código;
until false;

– resolve ?

203
„ Soluções por SW para 2 processos
– algoritmo 3
var
var flag[0..1] % variável compartilhada, inicializado com false
repeat
flag[i] := true ;
while flag[j] do skip; % mutexbegin
código-da-seção-crítica;
flag[i] := false % mutexend
resto-do-código;
until false;

– propriedades
» satisfaz exclusão mútua
» não satisfaz requisito PROGRESSO;
T0: P0 faz flag[0] = true
T1: P1 faz flag[1] = true =====> P0 e P1 ficam em um loop eterno204
#include <thread.h>
#thread_t tid1,tid2;
int shared ;
int flag [2];
void * p0(){
int i ;
for(i=0; i<1000000; i++) {
flag[0] = 1 ;
printf("Thread0%d\n", shared) ;
while(flag [1] == 1 ) {} /* entra se flag [1] = 0 */
shared =shared + 5 ;
flag [0] = 0 ;
}
}
void * p1(){
int i ;
for (i=0; i<1000000; i++){
flag [1] = 1 ;
printf("Thread1%d\n", shared) ;
while(flag [0] == 1 ) {} /* entra se flag [0] [0] = 0 */
shared = shared + 2 ;
flag [1] = 0 ;
}
}
main(){
int result;
shared = 0 ; flag [0] = 0 ;flag [1] = 0 ;
result=thr_create(NULL,0,p0,NULL,THR_NEW_LWP,&tid1);
result=thr_create(NULL,0,p1,NULL,THR_NEW_LWP,&tid2);
thr_join((thread_t)0,NULL,NULL); thr_join((thread_t)0,NULL,NULL);
printf(“O valor de shared e %d\n", shared) ;
}

205
„ Soluções por SW para 2 processos
– algoritmo de Peterson
var flag[0..1] of boolean; % variável compartilhada, inicializada com false
var turn of integer;
repeat
flag[i] := true ;
turn := j ;
while flag[j] and turn = j do nop; % mutexbegin
código-da-seção-crítica;
flag[i] := false; % mutexend
resto-do-código;
until false;

– resolve ?

206
„ Soluções por SW para 2 processos
– algoritmo de Peterson
var flag[0..1] of boolean; % variável compartilhada, inicializada com false
var turn of integer;
repead
flag[i] := true ;
turn := j ;
while flag[j] and turn = j do nop; % mutexbegin
código-da-seção-crítica;
flag[i] := false; % mutexend
resto-do-código;
until false;

– propriedades
» satisfaz exclusão mútua
» satisfaz a condição de progresso
207
» Satisfaz a condição de espera limitada
#include <thread.h>
thread_t tid1,tid2;
int turn ; int shared ; int flag [2];
void * p0(){
int i ;
printf("Thread P0\n");
for(i=0; i<10000; i++){
flag[0] = 1 ;
turn = 0 ;
while(flag [1]==1 && turn == 0 ) /* entra se flag[1]=0 ou turn=0 */
shared =shared + 5 ;
flag [0] = 0 ;
}
}
void * p1(){
int i ;
printf("Thread P1\n");
for (i=0;i<10000; i++) {
flag[1] = 1 ;
turn = 1 ;
while(flag [0]==1 && turn == 1) /* entra se flag[0]=0 ou turn =1*/
shared =shared + 2 ;
flag [1] = 0 ;
}
}
main(){
int result,i ; shared = 0 ; turn = 0 ;
flag [0] = 0 ; flag [1] = 0 ;
result=thr_create(NULL,0,p0,NULL,THR_NEW_LWP,&tid1);
result=thr_create(NULL,0,p1,NULL,THR_NEW_LWP,&tid2);
thr_join((thread_t)0,NULL,NULL);thr_join((thread_t)0,NULL,NULL);
printf(" O valor de shared e: %d\n", shared) ;
}

208
„ Soluções por SW para 2 processos
– algoritmo de Dekker
var flag[0..1] of boolean; % variável compartilhada, inicializada com false
var turn of integer;
repeat
flag[j] := true ;
turn := j ;
repeat nop until not(flag[j]) or turn = i do nop; % mutexbegin
código-da-seção-crítica
flag[i] := false; % mutexend
resto-do-código;
until false;

propriedades
» satisfaz exclusão mútua
» satisfaz a condição de progresso
» Satisfaz a condição de espera limitada 209
„ Soluções por SW para N processos
– algoritmo da padaria
» na entrada da padaria, cliente recebe número
» cliente com menor número é servido
» clientes podem receber mesmo número
„ número de processo menor tem preferência

210
„ Soluções por SW para N processos
– algoritmo da padaria: variáveis compartilhadas
var choosing: array [0..n-1] of boolean;
number: array [0..n-1] of integer;
– algoritmo da padaria: estrutura do processo Pi
repeat
choosing[i]:= true;
number[i]:= max(number[0], number[1], ..., number[n-1])+1;
choosing[i]:=false;
for j:=0 to n-1
do begin
while choosing[j] do skip;
while (number[j] ≠ 0) and (number[j],j)<(number[i],i) do skip;
end;
código-da-seção-crítica
number[i] = 0;
resto-do-código;
211
until false;
(a,j)<(b,i) if a<b or a=b and j<i
„ Soluções de Hardware
– Instruções Especiais
» TAS: Testa e modifica o conteúdo de uma variável de
forma não interrompível
» Swap: Troca o conteúdo de duas variáveis de forma
não interrompível

212
„ Soluções de Hardware - tas
int lock = 0; % global
int tas (){
r = lock ;
lock = 1 ;
return (r) ;
}

213
„ Soluções de Hardware - tas
pi() {
for(;;) {
while(tas(lock)) {}
“seção crítica”
lock = 0 ;
}
}

214
„ Soluções de Hardware - swap
int lock = 0; % global inicializada com false
swap (lock, key){
int r ;
r = lock ;
lock = key ;
key = r ;
}

215
„ Soluções de Hardware - swap
pi() {
int key = 1 ;
for(;;) {
repeat
swap(lock, key) ;
until key = false ;
“seção crítica”
lock = 0 ;
}
}
216
„ Soluções
de Hardware - possível
implementação
– Instruções especiais disponíveis no modo
supervisor
– Uso correto das instruções
» oferecer enter_region e exit_region
– tsl: Testa e modifica o conteúdo de uma variável
de forma não interrompível
– Swap: Troca o conteúdo de duas variáveis de
forma não interrompível

217
„ Soluções de Hardware - tas
int lock = 0; % global
enter_region (){
/* implementada como chamada de sistema
(salva contexto, entra no modo supervisor) */
L: tsl register, #lock /* copia o valor de lock para register
seta valor do lock - atomicamente */
cmp register, #0 /* compara com 0 */
jne L /* se não for 0 a SC está ocupada, loop */
ret
}

218
„ Soluções de Hardware - tas
leave_region (){
move lock, #0 /* atribui 0 a variável lock - libera a SC */
ret
}

219
„ Soluções de Hardware – tsl
pi() {
for(;;) {
enter_region() ;
“seção crítica”
leave_region() ;
}
}
220
„ Soluções de Hardware - swap
int lock = 0; % global inicializada com false
enter_region() {
/* implementada como chamada de sistema
(salva contexto, entra no modo supervisor) */
L: swap #lock, #key /* troca o conteúdo de lock e key -
atomicamente */
cmp #key, 0 /* compara o conteúdo de key com 0 */
jne L /* se for 0 a SC está ocupada, loop */
rte
}

221
„ Soluções de Hardware - swap

leave_region() {
move #lock, 0 /* libera a SC */
rte
}

222
„ Soluções de Hardware – swap
pi() {
for(;;) {
int key = 1 ;
enter_region() ;
“seção crítica”
leave_region() ;
}
}
223
Semáforos

„ Dijkstra - 1965
– Um semáforo s é uma estrutura de dados,
formada por um contador e um apontador para
uma fila de processos bloqueados no semáforo
– Somente pode ser acessado por duas operações
atômicas (P e V)
– As modificações no valor do semáforo são
executadas atomicamente

224
Semáforos

„ Cont.
– Se dois processos tentam, simultaneamente,
executar P(s) ou V(s), essas operações irão ser
executadas seqüencialmente, em uma ordem
arbitrária
– Semáforos podem ser usados para exclusão
mútua com n processos, quando inicializados
com o valor 1

225
Semáforos
„ Cada processo Pi

repeat
P(mutex) ;
“seção crítica”
V(mutex)
“seção não crítica”
until false ;

226
Semáforos
„ Uso de Semáforos para sincronizar
processos
– Ex.: p1: comando s1; p2: comando s2
– Condição: somente executar s2 depois de s1 ter
terminado
semaphore sync = 0 ;
processo p1 processo p2
--- ---
s1 ; P(sync) ;
V(sync) ; ---

227
Semáforos
„ Implementação
P(s): s.value = s.value - 1 ;
if (s.value < 0 ) {
“adicionar o processo na lista s.l”
block(p) ; /*bloqueia o processo p*/
}
V(s): s.value = s.value + 1 ;
if (s.value < =0 ) {
“remover o processo “p” da lista s.l”
wakeup(p) ; /*acorda o processo p*/
}

228
Semáforos
„ Problema clássico: buffer limitado
– conjunto de “n”buffers”
– cada buffer com capacidade para um ítem
– semáforos usados:
» mutex: para exclusão mútua
» empty: contador do número de buffers vazios
» full: contador do número de buffers cheios

Int buffer [20] ;


semaphore mutex, empty, full ;
info info-p, info-c ;
full = 0 ; empty = 20 ; mutex = 1 ;

229
main() {
parbegin{
produtor: repeat
“produz um ítem”
info-p = item ;
p(empty) ;
p(mutex) ;
“adicionar info-p ao buffer”
v(mutex) ;
v(full) ;
until false ;
consumidor: repeat
p(full) ;
p(mutex) ;
“remover o item para info-c”
v(mutex) ;
v(empty) ;
until false ;
}
}
230
Programação com threads no
Solaris

Thr-create ( void* stack-base, size-t stack-size,


void * start-newtime, void * arg,
long flajs, thread-t * new-thread);

thr-join (thread-t wait-for, thread-t* deported,


void ** status) ;

thr-self ( );
retorna a identificação da thread criada

231
Semáforos
Operações
Sema-init ( sema-t * sp, unsigned int count, int type, void * arq);

sp: identificador do semáforo


count: valor a ser atribuído ao semáforo
type:
usync_process: sincronizar threads neste e em outros processos
usync_threads- sincronizar threads neste processo
arq: sem uso

sema-wait ( sema-t * sp );
sema-post (sema-t * sp);
sema-trywait (sema-t * sp );
sema-destroy (sema-t * sp);

232
Exemplo de programa
* include < thread.h >
thread_t th0, th1;
void * t0 ( );
void * t1 ( );
main ( ) {
int r, I ;
thr-create ( null, 0, t0, NULL, THR_NEW_LWP, &th0);
thr-create ( null, 0, t1, NULL, THR_NEW_LWP, &th0);
thr_join [( thread_t ) 0, null, null);
thr_join [( thread_t ) 0, null, null);
printf(“ eu sou o main\ m”);
}
233
Void * t0 ( ){
int k = 0;
for (;; )
{
print f (“thread: % d % d \ m”, thr_self ( ), K );
k ++ ;
}
}
void * t1 () {
int k = 0 ;
for (;;)
{
print (“thread: % d % d \ m” , thr_self ( ), K );
k ++ ;
}
}

234
Exemplo de programa
* include < thread.h >
thread-t t0, t1 ;
void * thread-0 ( );
void * thread-1 ( );
int k = 0;
main ( ) {
int r, f;
r = thr_create ( null,0, thread0, NULL, THR_NEW_LWP, &t0 );
r = thr_create ( null, 0, thread1, NULL, THR_NEW_LWP, &t1 );
thr_join [(thread-t ) 0, null, null );
thr-_oin [( thread-t ) 0, null, null );
print f ( “eu sou o main \n “ );
}

235
Exemplo de programa
Void * thread-0 ( ) {
for (;; ) {
k = k + s;
}
}
void * thread-1 ( ) {
for ( ;; ) {
print + ( “valor de k = %d\n”, k );
}
}

236
Exercício
„ Escrever um programa que define e
inicializa, com valores quaisquer,
duas matrizes. A seguir, cria duas
threads, th0 e th1, para identificar e
imprimir o maior elemento de cada
uma das matrizes. Th0 opera sobre a
matriz m0 e th1 opera sobre a matriz
m1.
237
PTHREADS
Regiões Críticas (pthreads )

„ pthread_create(&th, NULL, proc, &args) ;


„ pthread_exit(void *value_ptr) ;
„ pthread_join(pthread_t thr, void **ptr) ;
„ pthread_mutex_t mutex1;
„ pthread_mutex_init(&mutex1, NULL) ;
„ pthread_mutex_lock(mutex1) ;
„ pthread_mutex_unlock(mutex) ;
Variáveis condição (pthreads )
pthread_cond_t cond1;
pthread_cond_init(&cond1, NULL) ;
pthread_cond_wait(&cond1, &mutex1) ;
pthread_cond_timewait(&cond1, &mutex1, time) ;
pthread_cond_signal(&cond1) ;
pthread_cond_broadcast(&cond1) ;
Variáveis condição (pthreads )
EX.
pthread_mutex_lock(&my_lock);
while(not condition)
pthread_cond_wait(&w, &my_lock);
“executar comandos”
pthread_mutex_unlock(&my_lock);
Variáveis condição (pthreads )

EX.
pthread_mutex_lock(&my_lock);
“executar comandos”
pthread_cond_signal(&w);
pthread_mutex_unlock(&my_lock);
Construções de Alto Nível
( Brinch Hansen, Hoare ) 72 - 74

„ Regiões Críticas
„ Regiões Críticas Condicionais
„ Monitores
Regiões Críticas ( 72 )
„ Uso de Semáforos:
Type semaphore = 0;
p ( mutex );
secão crítica
v ( mutex );

Type semaphore = 1;
p ( mutex );
secão crítica
p ( mutex );

Type semaphore = 1;
v ( mutex );
secão crítica.
P ( mutex );
Regiões Críticas ( 72 )
„ Variável V:
– Somente pode ser acessada dentro de
um comando region
– garante exclusão mútua

Var
shared T V;

po() { po() {
region V do s0; region V do s1;
} }
Regiões Críticas ( 72 )
„ Exemplo de Região Crítica:
– Var free: shared array [ 1..N ] of
Boolean;
Procedure acquire ( var index: integer )
Begin
region free do
for index: = 1 to N do
if ( free[ index ] then
begin
free[ index]: = false;
exit ;
end ;
index: = -1 ;
end;
Regiões Críticas ( 72 )
„ Implementação da Região Crítica
com Semáforos:
– para cada declaração: var shared T V
;
» o compilador gera um semáforo
– para cada comando Region v do S ;
» o código gerado pelo compilador é o
seguinte:

P ( mutex );
S;
V ( mutex );
Regiões Críticas ( 72 )

„ Alinhamento de Regiões Críticas:


– P0: region x do region y do s1;
– P1: region y do region x do s2;

Deadlock
Região Crítica Condicional
(Hoare) 72
„ Region V when b do S;
– b: expressão booleana avaliada quando o
processo entra na região crítica.
– Se b é verdadeira, o comando S é executado
– senão:
» o processo libera a exclusão mútua e é
suspenso até que a expressão booleana se
torne verdadeira
Exemplo de Programa Usando Região
Crítica Condicional:
Var
buffer = shared record
elemento: array [ 0…N] integer
count, in, out : integer;
end;
Produtor:
region buffer when count < N do
begin
elemento [ in ]: = inf;
in: = in + 1 mod N;
count: = count + 1;
end;

Consumidor:
region buffer when count > 0 do
begin
inf: = elemento [out ];
out: = out + 1 mod N;
. Count : = count -1 ;
end;
Região Crítica Condicional
(Hoare) 72

„ Operação Await ( exb ):


– permite a um processo se bloquear
dentro de uma região crítica a espera de
uma condição
Region V do begin
S1;
await ( b );
S2 ;
end ;
„ Implementação de Região Crítica Condicional
com Semáforos:
Var mutex, wait: semaphore;
count, temp: intefer;
P ( mutex );
if ( not b ) then {
count : = count + 1 ;
V ( mutex ) ;
P ( wait ) ;
while ( not b ) do {
temp: = temp + 1 ;
if ( temp < count ) then
V ( wait ) ;
else
V ( mutex ):
P ( wait ) ;
}
count : = count - 1 ;
}
“comandos”
if ( count > 0 ) then {
temp : = 0 ;
V ( wait ) ;
}
else
V ( mutex ) ;
Monitor
( Brinch Hansen, Hoare ) 73, 74

– É um modelo que permite o


compartilhamento de dados
– possui valores que representam o estado do
objeto e as procedures que manipulam os
valores
– as procedures são executadas de forma
mutuamente exclusiva
– variáveis especiais ( condição ) permitem a
um processo se bloquear a espera de uma
condição (wait)
– a condição é sinalizada por um outro
processo (operação signal)
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Visão Esquemática de um Monitor:

Filas de
entrada

Dados
compartilhados

operações

Código de
inicialização
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Variáveis Condição:
– ex.: var x, y : condition ;
– x.wait:
» o processo que executa essa operação é suspenso até
que um outro processo execute a operação x.signal
– x.signal:
» acorda um único processo
» se não existem processos bloqueados, a operação
não produz efeitos
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Se a operação x.signal é executada por um
processo P0 e existe um processo P1 bloqueado,
P0 e P1 podem executar
„ se P1 é acordado, P0 e P1 ficam ativos
simultaneamente no monitor
„ Possibilidades:
– a) P0 acorda P1 e espera que P1 libere o
monitor, ou se bloqueia a espera de outra
condição
– b) P1 espera que P0 libere o monitor, ou
espera por outra condição
„ Brinch Hansen (Pascal Concorrente):
– P0 executa signal e libera o monitor ( o signal
é a última instrução da procedure )
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Programa Pascal Concorrente:
type resource = monitor
var
free : boolean ;
x : queue ;
procedure entry request ;
begin
if not free them
delay ( x ) ;
free : = false ;
end
procedure entry release ;
begin
free : = true ;
continue ( x ) ;
end
begin
ree : = true;
end.
„ Programa Pascal Concorrente:
Type user = process ( r = resource );
begin
r.request ;


r.release ;
end;
Type user1 = process ( r = resource );
begin
r.request ;


r.release ;
end;

Begin
var
p0 : user ;
p1 : user1 ;
m : resource ;
init po ( m ) ;
init p1 ( m ) ;
end.
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Implementação de Semáforo:
Type semaphore = monitor ;
var busy = boolean ;
nonbusy : condition ;
procedure entry P
begin
if busy than
nonbusy.wait ;
busy = free ;
end;
Procedure entry V
begin
busy = false ;
nonbusy.signal ;
end ;
begin
busy = false ;
end.
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Implementação de Semáforo n bin:
Type semaphore = monitor ;
var nproc = int ;
non_busy : condition ;
procedure entry P
begin
nproc--;
if nproc<0 then
non_busy.wait ;
end;

Procedure entry V
begin
nproc++;
non_busy.signal ;
end ;
procedure semaInit(int I)
begin
nproc = i;
end.
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Solução para o Problema dos
Filósofos:
Type philosophers = monitor
var
state : array [ 0…4 ] of ( thinking, hungry, eating ) ;
self : array [ 0…4 ] of condition ;
procedure entry pickup ( I = 0…4 )
begin
state [ 1 ] = hungry ;
test ( I ) ;
if state [ I ] =/ eating them self [I ]. Wait ;
end ;
procedure entry putdown ( I : 0…4 )
begin
state [ I ] = thinking ;
test ( I-1 mod5 ) ;
test ( I + 1 mod5 ) ;
end;
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Solução para o Problema dos
Filósofos:
Procedure test ( k : 0…4 )
begin
if ( state [ k-1 mod5 ] =! eating
and state [ k ] = hungry
and state [ k + 1 mod 5 ] =! eating ) them
begin
state [ k ] = eating ;
self [ k ] . Signal ;
end ;
end ;
begin
for I = 0 to 4 do
state [ I ] = thinking ;
end.
Monitor
( Brinch Hansen, Hoare ) 73, 74
„ Implementação de Monitor com
Semáforo:
– cada monitor é representado por um semáforo mutex
inicializado com 1. P( mutex ): entrar no monitor
V ( mutex ): liberar monitor
– semáforo next inicializado com 0 para um processo
sinalizador se bloquear
– next count : contém o No. de processos bloqueados em
next
P ( mutex ) ;
“ corpo da procedure entry”
if next-count > 0 them
v ( next ) ;
else
V ( mutex ) ;
Monitor
( Brinch Hansen, Hoare ) 73, 74

– Para cada variável condition, associar


um semáforo x-sem e uma variável
inteira x-count

X.wait : x-count = x.count + 1 ; X.signal : if x-count > 0 them


if next-count > 0 them begin
V ( next ) ; next-count = next-count + 1 ;
else V ( x-sem ) ;
V ( monitor ) ; P ( next ) ;
P ( x-sem ) ; next-count = next-count - 1 ;
x-count = x-count-1 ; end ;
Software de entrada e
saída

265
Software E/S

„ Uma das principais funções do SO é


controlar os dispositivos de E/S
– Para isso deve:
» emitir comandos para os dispositivos
» tratar interrupções
» tratar erros
» prover uma interface entre os dispositivos e o resto
do sistema

266
Software E/S

„ Estruturação do software de E/S


– quatro níveis
» tratamento de interrupções
» drivers dos dispositivos
» software do SO independente do dispositivo
» software ao nível do usuário

267
Software E/S

„ Tratamento de interrupções
– quando uma interrupção ocorre, uma procedure
específica é ativada de modo a desbloquear o
driver
– o efeito de uma interrupção é que um processo
que estava previamente bloqueado está agora
apto a rodar

268
Software E/S

„ Drivers dos dispositivos


– todo código dependente do dispositivo está em
um driver do dispositivo
– o trabalho do driver é aceitar requisições e
providenciar para que sejam executadas
– se o driver esta disponível, a requisição é
processada imediatamente, caso contrário,
entrará em uma fila de requisições

269
Software E/S

„ Execução de uma requisição para um disco


– determinar o posicionamento do braço no
cilindro próprio
– determinar as operações que são requeridas:
» Ex. leitura, escrita, etc.
– escrever as operações nos registradores do
controlador

270
Software E/S
„ Software independente do dispositivo
– Funções básicas
» desenvolver as funções de E/S que são independentes do
dispositivo
» prover interface uniforme para o nível usuário
– Funções:
» mapeamento do nome simbólico no driver apropriado
» interface uniforme para os drivers
» identificação dos dispositivos
» prover tamanho de bloco independente do dispositivo
» etc.

271
Software E/S

„ Software à nível do usuário


– Rotinas de biblioteca
» read
» write
» open
» close
» etc.

272
Software E/S

Processos do
usuário

Software independente
do dispositivo

Tratamento de
interrupções

Hardware

Níveis lógicos de um sistema de entrada e saída

273
Software E/S
„ Exemplo de requisição para um dispositivo
blocado
– Tipo: operação
– dispositivo: menor número
– posição: endereço do dispositivo
– número de processo: requisitante da e/s
– endereço: do processo requisitante
– contador: bytes a transferir

„ Resposta
– número do processo: requisitante
– status: bytes transferidos ou erro
274
Software E/S
Estrutura principal de um driver

message msg; /* buffer de msg */

IO_task ()
{
int r, caller ;
initialize ;
while (true) {
RECEIVE(any, &msg) ;
caller = msg.source ;
switch (msg.type) {
case read: r = do_read(); break ;
case write: r = do_write()); break;
case other: r = do_other(); break;
default: r = error;
}
}
}
275
Gerência de Memória

276
Gerência de memória

„ Memória:
» central em sistemas de computador
» CPU e sistema de I/O interagem com a memória
» é um conjunto (array) de bytes ou palavras, cada um
com seu próprio endereço
» CPU faz busca e armazenamento na memória
» um programa deve ser carregado na memória para
ser executado

277
Gerência de memória

„ Memória

memória sistema
CPU
I/o

278
Conceitos Básicos

„ UCP
– é composta de circuitos eletrônicos
– coordena e controla todas as operações do
sistema
– é formada por processador e memória
» processador:
„ unidade de controle (UC)
„ unidade lógica-aritmética (ULA)
» memória
„ unidade de armazenamento de instruções e dados
279
UCP
Unidade aritmética e
unidade de controle lógica

Memória
0
1
2
3
4
5
...
N

Registradores
especiais

Representação esquemática da UCP 280


Conceitos Básicos

„ Unidade de controle
– controla todas as operações do computador
– é formada por:
» registrador de controle
» registrador de instrução
» decodificador
» relógio
» sequenciador

281
Conceitos Básicos

„ Registrador de controle (contador de


programa - PC)
– contém o endereço de memória da próxima
instrução a executar
„ Registrador de instrução (RI)
– contém a instrução que está sendo executada a
cada momento
– cada instrução contém:
» código da operação
282
» operandos ou endereços de memória dos mesmos
Conceitos Básicos

„ Decodificador
– extrai e analisa o código de operação da
instrução que está em execução (que está no RI)
– emite os sinais necessários para a sua execução
„ Relógio
– proporciona uma sucessão de impulsos elétricos
a intervalos constantes que sinalizam os
instantes de inicio de execução dos passos que
constituem cada instrução
283
Conceitos Básicos

„ Sequenciador
– gera ordens sincronizadas pelos impulsos do
relógio que fazem com que a instrução
carregada no RI seja executada passo a passo

284
Conceitos Básicos

„ Memória Principal
– é a parte da UCP que armazena instruções e
dados necessários para que um programa seja
executado
– é constituída por células ou posições de
memória numeradas de forma consecutiva
– é volátil
– permite acesso direto

285
Conceitos Básicos

„ Memória Principal (cont.)


– palavra de memória: conjunto de células de
memória que podem ser lidas ou escritas de
uma só vez
– em geral é endereçada por byte
– possui dois registradores para as operações de
leitura e gravação: Registrador de endereço de
memória e Registrador intermediário (buffer)

286
Conceitos Básicos
„ Memória Principal (cont.)
– Registrador de endereço de mémória
» contém o endereço de memória onde se encontra ou
onde vai ser gravada a informação (instrução ou
dado)
– Registrador Intermediário (buffer)
» leitura: recebe a informação da memória
» escrita: contém a informação a ser gravada
– Seletor: seleciona a célula de memória cujo
endereço se encontra no registrador de
endereços para a transferência (leitura/escrita) 287
Registrador de Registrador
endereço de memória intermediário (buffer)

Seletor Memória principal

...

...

32
33
...

Visão esquemática da memória principal de um computador


288
Conceitos Básicos

„ Execução de um programa
– o programa deve estar na memória
– as instruções são executadas uma a uma
„ Fases do processamento de uma instrução
– Busca
» a instrução é levada da memória para a unidade de
controle
– Execução
» realização das ações internas contidas na instrução
289
Conceitos Básicos
» Fase de Busca de uma instrução
„ a unidade de controle (UC) envia uma microordem para que
o conteúdo do program counter (PC), seja transferido para o
registrador de endereço de memória (MAR)
„ o seletor transfere o conteúdo do endereço de memória
constante no MAR para o registrador intermediário de
memória (MBR)
„ a instrução é transferida do MBR para o registrador de
instrução (RI)
„ o decodificador interpreta a instrução que acaba de chegar
no RI
„ o program counter se auto-incrementa (com o uso da
unidade aritmética e lógica)

290
Conceitos Básicos
„ Ex. Instrução de três operandos
– possui o código da operação e três operandos:
os dois primeiros contém os operandos, e o
terceiro o lugar onde será armazenado o
resultado da operação.
– EX. ADD a, b, c

operador operando1 operando2 operando3

291
Conceitos Básicos

» Fase de Execução de uma instrução (com três


operandos)
„ o end. do primeiro operando do RI é transferido para o
MAR
„ o seletor faz a leitura da posição de memória apontada por
MAR e deposita seu conteúdo no MBR
„ esse valor é transferido para o registrador de operando 1
(RO1) da unidade aritmética e lógica

292
Conceitos Básicos

» Fase de Execução de uma instrução (com três


operandos)
„ o end. do segundo operando é transferido do RI para o
MAR
„ o seletor faz a leitura da posição de memória apontada por
MAR e deposita seu conteúdo no MBR
„ esse valor é transferido para o registrador de operando 2
(RO2) da unidade aritmética e lógica
„ o sequenciador envia uma micro-ordem para a unidade
aritmética e lógica para que seja executada a operação, e o
resultado fica armazenado no registrador de resultados
(RR)

293
Conceitos Básicos

» Fase de Execução de uma instrução (com três


operandos)
„ O conteúdo do registrador de resultados (RR) é transferido
para o registrador intermediário de memória (MBR)
„ é transferido do registrador de instrução (RI) para o
registrador de endereço de memória (MAR) o endereço de
memória onde o resultado deverá ser armazenado
„ o reultado é transferido do MBR para o endereço
constante no registrador de endereço de memória (MAR)

294
Gerência de memória

„ Memória física e Memória virtual:


– Física:
» é a memória do hardware
» começa geralmente no endereço físico 0 e continua
até um endereço qualquer
» certas posições são reservadas pelo hardware para
objetivos especiais (ex. vetor de interrupções)

295
Gerência de memória
„ Memória física e Memória virtual (cont.)
– Virtual:
» é a memória que o processo enxerga
» é o espaço virtual de um processo
» o maior endereço virtual é limitado pela arquitetura
da máquina (No. de bits usados para endereçar). EX.
„ PDP-10 (18 bits)==>256 k
„ PDP-11 (16 bits)==> 64 k
» o espaço virtual pode ser maior que o espaço físico,
especialmente se é usada paginação/segmentação
» um processo pode acessar qualquer parte de seu
espaço virtual
296
Gerência de memória

„ memória física e memória virtual (cont.)


– Virtual:
» um processo pode acessar qualquer parte de seu
espaço virtual
0
código
dados

pilha
n

297
Gerência de memória

„ Tradução de endereço:
– processo trata com endereços virtuais
– em todo acesso deve haver uma tradução de
endereços
– isto significa que a tradução não deve ser feita
por software - desempenho

298
Gerência de memória

„ Tradução de endereço (cont.)


0 13 k 0 10 k
proc a proc b
tradução de endereço

memória física
tradução de endereço
kernel
0 19 k

299
Gerência de memória

„ Monoprogramação
– existe um único processo na memória em
execução e ao mesmo é permitido usar toda a
memória
„ Multiprogramação
– existem vários processos na memória aptos à
executar e um em execução

300
Gerência de memória

„ Monoprogramação:
– esquema mais simples possível
– um processo por vez na memória
– o processo pode usar toda a memória
– a memória é dividida entre o sistema
operacional e o processo do usuário

301
Gerência de memória

„ Monoprogramação (cont.)
operating device
user system in drivers in
progam Ram Rom
user
user
program
operating program operating
system in system in
Ram Ram

Formas de organizar a memória com o sistema operacional


e um programa de usuário
302
Sistemas que suportam
Multiprogramação
„ Proteção de hardware:
A. registradores limite
0 limite limite
monitor inferior superior

usuário 1 end sim sim


limite CPU > < mem.
usuário 2 inferior
não não
usuário 3 limite superior
usuário 4 trap para
128 k o sistema operacional

303
Sistemas que suportam
Multiprogramação
„ Proteção de hardware: (cont.)
b: registradores base e limite
limite base

end sim
CPU
< + mem.
não

trap para o
sistema operacional
304
Sistemas que suportam
Multiprogramação
„ Proteção de hardware:
– com registradores limite muitos processos
podem residir na memória simultaneamente
– divisão da memória entre os processos
(partições fixas, partições variáveis)

305
Sistemas que suportam
Multiprogramação
„ Partições Fixas
– tamanho fixo das partições,
– ex.: memória de 32K, dividida em:

10K - monitor residente


04K - processos pequenos
06K - processos médios
12K - processos grandes

– quando o processo entra no sistema, é colocado em


uma fila de processos
306
Sistemas que suportam
Multiprogramação
„ Partições Fixas (cont.)
– o scheduler verifica sua necessidade de
memória, que partições estão disponíveis e
carrega o processo em uma das partições
– o grau de multiprogramação é determinado pelo
No. de partições

307
Sistemas que suportam
Multiprogração
„ Partições Fixas: (cont.)
– alocação de memória para os processos
» a) classificá-los de acordo com suas necessidades de
memória (especificada pelo usuário ou pelo sistema)
» b) cada região tem sua própria fila
...... 2K 1K 2K f2

............... 3K 4K f6

....... 7K 11K 8K f 12

308
Sistemas que suportam
Multiprogramação
„ Partições Fixas (cont.)
– alocação de memória para os processos
» c) uma única fila
monitor
5K 2K 3K 7K 7K .........
2K

6K

12K

309
Sistemas que suportam
Multiprogramação
„ Fragmentação
– interna: tamanho da partição maior que o
tamanho do processo
– externa: partição não usada é menor que o
tamanho do processo esperando

310
Sistemas que suportam
Multiprogramação
„ Partições variáveis
– o sistema operacional mantém uma tabela
indicando que partes da memória estão
disponíveis e quais estão ocupadas
– inicialmente toda a memória esta disponível,
considerada como um bloco único
– quando um processo chega e necessita memória
é pesquisado um bloco com tamanho suficiente
para contê-lo

311
Sistemas que suportam
Multiprogramação
„ Partições variáveis (cont.)
– quando um processo termina libera sua
memória, que é reincorporada ao conjunto
disponível
– características:
» existem blocos livres de diferentes tamanhos
» se um bloco é muito grande para um processo, é
dividido em dois, um alocado para o processo e o
outro retorna para os blocos livres

312
Sistemas que suportam
Multiprogramação
„ Partições variáveis (cont.)
– características:
» quando um processo termina libera a memória, sendo esta
colocada no conjunto de blocos livres
» se o bloco liberado é adjacente à outo livre, podem ser
agrupados formando um único
– Que bloco alocar?
» first-fit: o primeiro com tamanho suficiente
» best-fit: o menor com tamanho suficiente
» worst-fit: o maior

313
Sistemas que suportam
Multiprogramação
„ O software determina a diferença entre
Partições Fixas e Partições Variáveis
„ dois registradores contém os limites
(superior e inferior)
» quando um processo é selecionado, o dispatcher
carrega os valores nos registradores
– a utilização de memória é geralmente melhor
no mvt que no mft

314
Sistemas que suportam
Multiprogramação
„ Compactação:
– unir os blocos de memórias disponíveis em um
único bloco
– somente possível se o sistema suporta
relocação dinâmica, em tempo de execução
(registradores base e limite)

315
Sistemas que movimentam processos
entre a memória principal e o disco
„ Swapping
– O esquema de gerência de memória de sistemas
monousuário foi usado por dois dos primeiros
sistemas timesharing: CTSS e Q-32
– memória dividida em duas partes:
» 1. monitor residente
» 2. processo do usuário sendo executado
correntemente

316
Swapping

„ Swapping (cont.)
– quando o processo executando perde o
processador:
» conteúdo da memória do usuário é gravado no disco
» novo processo é lido para a memória

“Swapping”

317
Swapping

„ Swapping: (cont.)
Disco

limite monitor
swap out
usuário
área do 1
usuário
swap in usuário
2
“swapping”

memória
318
Swapping

„ memória auxiliar:
– swapping requer memória auxiliar
– normalmente um disco
– deve ser grande o bastante para acomodar cópia
de todas as “imagens de memória dos processos
dos usuários”
– lista “ready” contém processos que estão em
disco e que estão aptos para rodar

319
Swapping

„ memória auxiliar: (cont.)


– uma variável indica o processo que está em
execução
– quando o scheduling decide executar um
processo chama o dispatcher
„ Dispatcher:
– verifica se o processo selecionado está na
memória

320
Swapping

„ Dispatcher: (cont.)
– se não estiver, faz swap out do processo na
memória
– faz swap in do processo selecionado
– restaura os registradores
– transfere o controle para o processo selecionado

321
Swapping

„ Tempo de swap
– maior parte do tempo de swap é o tempo de
transferência
– proporcional ao tamanho de memória a ser
transferida

322
Swapping

„ Tempo de swap: (cont.)


– o S.O deve ser informado com exatidão do
tamanho da memória do usuário
– o tempo de transferência diminui com o
aumento da velocidade de transferência dos
dispositivo

323
Paginação

„ Endereço gerado pela CPU contém duas


partes:
– No. da página: (p)
» endereça uma tabela de páginas
– deslocamento: (d)
» combinado com o endereço base da página define o
endereço físico de memória

324
endereço lógico endereço físico

CPU p d f d
memória
física

Tradução de endereço
325
Paginação

„ tradução de endereço:
– memória física: dividida em frames
– memória lógica: pages
– um programa para ser executado tem suas
pages carregadas em quaisquer frames
disponíveis
– o tamanho da página é definido pelo hardware

326
Paginação
„ Tradução de endereço: (cont.)
ex.: memória física = 32 words
P : 4 words
total de páginas : 8
u: endereço lógico
P: tamanho da página
p: número da página
d: deslocamento
4 words
p = u div P
d = u mod P
327
Paginação

„ tradução de endereço: (cont.)


endereço lógico
0 - p = 0 div 4 = 0 (page)
d = 0 mod 4 = 0 (deslocamento)
1 - p = 1 div 4 = 0 (page)
d = 1 mod 4 = 1 (deslocamento)
4 - p = 4 div 4 = 1 (page)
d = 4 mod 4 = 0 (deslocamento)
15 - p = 15 div 4 = 3 (page)
d = 15 mod 4 = 3 (deslocamento)
328
Paginação

„ scheduling:
– quando o processo chega, o scheduling verifica
o No. de páginas de que ele precisa
– verifica na lista de frames disponíveis se existe
um número suficiente
– existindo, aloca para o processo o No. que ele
necessita

329
Paginação 0
0 a
4 ijkl
1 b
2 c o 5
1 6 8 mnop
3 d
4 e 2 1
memória 12
5 f
lógica
6 g 3 2
7 h 16
8 i
tabela de
9 j páginas 20 abcd
10 l
11 m 24 efght
12 n memória
13 o física 28
14 p
15 q

330
Paginação

„ implementação da tabela de páginas:


– conjunto de registradores:
» recarregados como qualquer outro
» carregados/modificados por instruções especiais
» somente se a tabela de páginas é pequena
– na memória principal (um registrador-page
table base register-(ptbr) aponta para a tabela de
páginas)
» o tempo de acesso a uma posição de memória é o
problema
331
Paginação

„ implementação da tabela de página: (cont.)


– acessar end. i
» acessar tabela de páginas (uso do ptbr+ No.page
desloc.) (1o. acesso à memória)
» produz um No. de frame, combinado com
deslocamento produz end i
» acessar a posição i na memória física (2o. acesso)
» dois acessos para acessar uma palavra

332
Paginação

„ implementação da tabela de página: (cont.)


– hardware especial: (memória associativa,
memória endereçável pelo conteúdo)
» mais rápida que a memória
» contém poucas entradas da tabela de páginas
» um endereço lógico gerado pela CPU é comparado
com todas as entradas da tabela de páginas
simultaneamente, a qual contém número de
página/número de frame (na memória associativa)

333
Paginação

„ implementação da tabela de páginas: (cont.)


– hardware especial: (memória associativa,
memória endereçável pelo conteúdo)
» se o número da página é encontrado, o No. da frame é usado
imediatamente para acessar a memória
» se o número da página não é encontrado, é feito um acesso a
tabela de páginas, na memória principal, para obter o No. da
frame que é usado para acessar a memória
» o No. da página e o No. da frame são colocados na memória
associativa, de modo a ser encontrado rapidamente na próxima
referência

334
Paginação

„ compartilhamento de páginas:
– particularmente importante em sistemas time-
sharing
– permite compartilhamento de código
„ proteção:
» um bit de proteção em cada página
» o bit define se a página é read-only ou read-
write
335
Paginação
ED1 ED1 0
3 3
ED2 1 D1
4 ED2 4
ED3 2 D3
6 ED3 6 3 ED1
D1 1 D2 7 4 ED2
P1 P2 5
6 ED3
7 D2
ED1 3
4 8
ED2 9
ED3 6
8 10
D3
P3
compartilhamento
de
código
336
Segmentação

„ um programa é um conjunto de:


– subrotinas
– funções
– estruturas de dados (tabelas, etc.) referidos pelo
nome
– cada um é um segmento de tamanho variável
– segmentação é um esquema de gerência de
memória que suporta esta visão

337
Segmentação (cont.)

– cada segmento tem um nome e um tamanho


(end. é especificado pelo nome do segmento e
pelo deslocamento)
– compilador pascal cria segmentos para:
» variáveis globais
» código de cada procedure
» código de cada function
» variáveis locais de procedures
» variáveis locais de functions

338
Segmentação
segment table
s
limite base

CPU (s d)

d yes
< +
memory

trap; addressing error

segmentation hardware
339
Segmentação

„ Hardware:
– end => No. seg e deslocamento
» a tab. seg é um array de par de registradores base e
limite
– Implementação:
» registradores:
„ ex.: pdp-11/45 => 8 registradores de segmento

340
Segmentação

– Implementação: (cont.)
» registradores:
„ endereço de 16 bits

15 0
13 12
s d

No. 3 bits => 8seg.


desloc.
segmento 13 bits => 8K desloc.
muitos segmentos??
341
Segmentação

„ Hardware: (cont.)
– tabela de segmentos na memória
» uso de dois registradores:
„ STBR: segment table base register
„ STLR: segment table length register
» endereço: (s,d)

deslocamento
segmento

342
Segmentação

„ Hardware: (cont.)
– tabela de segmentos na memória (cont.)
» para um endereço lógico (s,d)
a. s < STLR ? não => erro
b. s + STBR
c. endereço = (end. base do segmento) + d
» requer dois acessos à memória (como na paginação)

343
Segmentação

„ Hardware: (cont.)
– uso de memória associativa para manter as
entradas da tabela de segmentos mais
recentemente usadas
» proteção:
„ bits de proteção para cada entrada na tabela de segmentos
„ existência de segmentos na tabela read only (código),
tentativa de escrita verificada pelo hardware
„ limites de um array (se for um segmento) verificados pelo
hardware

344
Sistemas Operacionais

Arquivos
Arquivos

„ Entidades lógicas mapeadas pelo S.O. em


dispositivos físicos
„ Contém informações definidas pelo
proprietário (dados e programas)
„ Possui um nome e é referenciado pelo mesmo
„ O sistemas operacional possui suporte
(chamadas de sistema) para manipulação de
arquivos.
346
Tipos de Arquivos

„ Regulares : contém informações dos usuários


„ Diretórios : são arquivos mantidos pelo
sistema e que possuem a estrutura do sistema
de arquivos
„ Caractere especial : são arquivos relacionados
ao I/O serial (terminais, impressoras, linhas de
comunicação, etc)
„ Bloco especial : são relacionados ao I/O de
blocos (discos)
347
Arquivos Regulares
16 bits
Nro mágico
„ Ex : executável UNIX Text size

header
» n mágico identifica arquivo como Data size
Bss siz
executável
S. table sre
Entry point
/////////////
/////////////
Text
Data
Relocação
T. símbolos

348
Operações sobre arquivos

„ create seek
„ delete get attributes
„ open set attributes
„ close rename
„ read
„ write
„ append

349
Chamadas de sistema

„ Exemplo de programa que utiliza chamadas de sistema


/* abre src e cria dest */
/* copia source para destino */
#include <sys/types.h> src = open(argv[1],O_rdONLY);
#include <fcntl.h> if(src<0) exit();
#include <stdlib.h> dst = create(argv[2],MODE);
#include <unistd.h> if(dst<0) exit();

#define DUP_SIZE 4096 /* unidade de R/W */ /*copia do arquivo*/


#define MODE 0666 /* modo de RW-RW-RW- */
while(1){
main (int argc, char *argv[]) in = read(src,buf,BUF_SIZE);
{ if(in<=0) break;
int src,dst,in,out; out = write(dst,buf,in);
char buf[BUF_SIZE]; if(out<=0) break;
if(argc!=3) exit(); }
close(src);
close(dst);
}
350
Diretórios

„ Contém informações que permitem acessar


aos arquivos
„ Possui várias entradas, uma por arquivo
„ Informações sobre cada arquivo:

nome data de criação


tipo data da última
tamanho modificação
proprietário lista de blocos usados
proteção
351
Organização de diretórios

„ Cada entrada contém o nome e os atributos


do arquivo
„ Cada entrada contém o nome do arquivo e
um ponteiro para uma estrutura de dados
com os atributos

352
Organização de diretórios

games atrib Estrutura de dados


mail atrib contendo os atributos
progs atrib

games
mail
progs

353
Quantidade de diretórios

„ Um único diretório contendo os arquivos de


todos os usuários
„ Um diretório por usuário

354
Quantidade de diretórios

root
root

A
A B C

B
...
D E F G
C
355
Quantidade de diretórios

„ Normalmente existe um diretório por


usuário
„ Cada usuário pode criar diretórios

356
Quantidade de diretórios

A B C

A1 B1 B2 C1 C2 C3

Sistema de arquivos hierárquico 357


UNIX

„ Estrutura hierárquica
– Ex : abrir o diretório /usr/ast/cap1
I-node 6
root Bloco 132
/usr
1 . modo 6 .
1 .. tamanho 1 ..
4 bin data
7 dev 132 7
14 lib … 26 ast
9 etc …
6 usr …
8 tmp …

358
UNIX

I-node 26 I-node 64
/ast Bloco 406 cap1
modo 26 . modo
tamanho 6 .. tamanho
data 64 cap1 data
406 11 cap2 191
… 102 cap3 …
… 81 cap4 …
… …
13 cap5
… …

359
Nomes

„ Absolutos: consiste do caminho desde o root até o


arquivo
„ Relativo: utilizado juntamente com o conceito de
diretório corrente. Todos os nomes de arquivo que
não começam com o separador (/,\), são
considerados relativos ao diretório corrente. Ex.
Se o diretório corrente é mail, o comando cp
usu1 usu1_message copia o arquivo
/usr/spool/mail/usu1 para o arquivo
/usr/spool/mail/usu1_message
360
Operações em diretórios

„ Create
„ delete
„ list
„ rename

361
Armazenamento de Arquivos

„ Alocação Contígua
– Ex: arquivo com 150k, blocos de 1k, seriam
alocados 150 blocos consecutivos ao arquivo
» simples de implementar
» o arquivo pode ser lido de maneira eficiente
– Problemas: determinar o tamanho do arquivo a
priori
– fragmentação externa

362
Armazenamento de arquivos

„ Lista encadeada
– Ex: bloco de 1k, 1022 bytes armazenam
informações, 2 bytes endereçam o próximo
bloco
– Problema : ? - acesso randômico

363
Lista encadeada com tabela na
memória
„ Cada apontador de bloco de disco é
armazenado em uma tabela na memória
„ Para identificar um bloco não é necessário
nenhum acesso a disco (acesso randômico)

364
Armazenamento de arquivos
„ Lista encadeada com tabela na memória
0
Bloco físico
1
2 10
3 11 Arquivo A
4 7
5
6 3
7 2
8
9
Arquivo B
10 12
11 14
12 0
13
14 0
15 365
Armazenamento de arquivos

„ Nós-I - nós índice


– associa a cada arquivo uma tabela
– nó-I - tem atributos do arquivo endereços de
blocos
– primeiros blocos - endereço no nó-I
– arquivos grandes
» bloco indireto simples
» bloco indireto duplo
» bloco indireto triplo
366
Armazenamento de arquivos

„ UNIX
– cada arquivo possui uma tabela (i-node) no
disco
– cada i-node possui informações sobre o arquivo
e o endereço de 10 blocos (os primeiros)
– possui um bloco de indireção
– possui um bloco de dupla indireção
– possui um bloco de tripla indireção

367
Armazenamento de arquivos

„ Indireção: se bloco possui 1M, e são necessários 4


bytes para endereçar um bloco, contém 256
blocos: tamanho do arquivo: 266 blocos
„ Dupla Indireção: aponta para um bloco que
contém 256 ponteiros (de 256 blocos cada)
tamanho do arquivos:
. 266 + 2562 = 65.802 blocos
„ Tripla Indireção: 16 Gigabytes

368
Compartilhamento de arquivos

„ O diretório contém a lista dos blocos que


pertencem ao arquivo
– é feita uma cópia dos blocos para o diretório do
arquivo “link”
– Problema: não existe compartilhamento,
mudanças em uma versão não são vistas em
outra

369
Compartilhamento de arquivos

„ Soluções
– 1a. Solução: os blocos não fazem parte do
diretório, mas sim de estruturas de dados
associadas aos descritores. O diretório aponta
para essa estrutura de dados
– 2a. Solução: “link” simbólico - o diretório
contém o nome do arquivo “linkado”

370
Problema da primeira solução

C C B

Owner: C Owner: C
count: 1 count: 2

arquivo arquivo

371
Problema da primeira solução

„ Se C deleta o arquivo:
B

problema
Owner: C
count: 1

arquivo 372
Compartilhamento de arquivos

„ Segunda solução
– não existe o problema de deleção do arquivo
por parte do proprietário
– Problema: número de acessos a disco pode ser
elevado
– Vantagem: link de arquivos em máquinas
diferentes

373
Problemas dos “links”

„ Ex: copiar um diretório completo para gerar


um backup (um arquivo “link” será copiado
mais de uma vez)

374
Gerência de blocos livres

„ Lista de blocos livres


– consiste em manter uma lista linkada de blocos
livres
– Ex: Bloco de 1k, 2 bytes para identificar bloco
livre, cada bloco contém 512 entradas. Quantos
blocos são necessários para manter a lista de
um disco de 80M?

375
Gerência de blocos livres

„ Mapa de bits
– um disco com n blocos necessita um mapa de n
bits
– blocos livres representados por 1, ocupados por
0.
– Quantos blocos de 1k são necessários para um
disco de 80M?

376
Deadlock

377
Deadlock
Modelo de sistema
Î Um sistema consiste de um número finito de recursos a ser
distribuído entre um número de processos competindo pelos
mesmos
Recursos
Î São quaisquer entidades que puderem ocasionar bloqueio de
processos. Um bloqueio ocorre quando um recurso não está
disponível e é requisitado por um processo. Ex. de recursos:
Î Dispositivos de E/S
Î Memória
Î região crítica 378
Deadlock
Deadlock
Î É uma situação na qual processos estão bloqueados à espera
de recursos que jamais serão liberados

Exemplo clássico de deadlock


Î P1: ... R (R1); ... R(R2); ... L(R1,R2)
Î P2: ... R (R2); ... R(R1); ... L(R1,R2)

O deadlock ocorre quando os dois processos


adquirem o primeiro recurso que necessitam
379
Deadlock
Tipos de recursos
Î Serialmente reusáveis
Î Constituídos de um número fixo de unidades idênticas,
cada uma podendo ser utilizada de forma independente das
demais. Após uma unidade ter sido utilizada por um
processo, pode ser reutilizada por outro, de forma serial.
Cada unidade pode estar em um dos seguintes estados:
Î alocada
Î disponível

380
Deadlock
Recursos consumíveis
Î São constituídos por um número variado de unidades que
são criadas e consumidas dinamicamente pelos processos. Os
processos que produzem as unidades são denominados
produtores e os processos que consomem as unidades são
denominados consumidores.
Î São características dos sistemas de processos cooperantes
(trocas de mensagens, sinas de sincronização)

381
Deadlock
Condições necessárias para a ocorrência de
dealock
Î Quando um processo que já tem um recurso puder requisitar
um outro recurso
Î Quando os recursos não puderem ser confiscados
temporariamente para serem alocados a outros processos
Î Quando for possível a formação de um ciclo no qual cada
processo está bloqueado à espera de recursos que estão
alocados para outros processos de mesmo ciclo

382
Deadlock
Representação
R2
R1 alocação P1
requisição
P2 alocação
R1
P1 P2

R1 P2 possui uma unidade de R1

P1 P2
P1 requisita duas unidades de R1
R1
P1 P2
383
P1 adquire duas unidades deR1
Deadlock
Métodos para tratamento de deadlock
1- Detectar
2- Eliminar as condições necessárias
3- Evitar
4- Recuperar

384
Deadlock
Detecção de deadlocks
Î É possível, pela análise dos grafos, determinar se existe um
deadlock.
“ Existe deadlock se as requisições para alguns processos
nunca serão atendidas ”
Redução de grafos
Î É uma maneira simples de examinar grafos para determinar
se existe deadlock
“ Um grafo pode ser reduzido em relação a um processo se
todas as requisições do processo podem ser garantidas ”
385
Deadlock

“ Os processos que não podem ser reduzidos são os que estão


em deadlock “

Teorema:
“ Não existe processos em deadlock se e somente se o grafo é
completamente redutível “

386
Deadlock
R2
R1 P1

P2
Podemos reduzir o grafo por P1 porque suas requisições
podem ser garantidas a redução é feita retirando-se as arestas
de/para o processo
R2
R1 P1

P2
P2 pode, agora, ter suas requisições atendidas
R2
R1 P1

P2
387
O grafo foi completamente reduzido
Deadlock
Algoritmo de detecção de deadlock
Î um único recurso com muitas unidades
Î estruturas de dados

REQ .......

1 number of processes
ALLOC .......

1 number of processes
REDUCED .......

1 number of processes

AVAIL: número de unidades presentemente disponíveis


388
Deadlock
Algoritmo
begin
for (i=1 to numberofprocess)
reduced(i) := false,
reducedprocess:=0;
“ Repeti até que não seja mais possível reduzir “
loop
exit when not reduction
reduction := false;
for ( P = 1 to numberofprocess) {
if (not reduced(P)) {
if (req(P) <= avail) then {
reduced(P) := true;
reducedprocess := reducedprocess +1;
reduction := true;
avail := avail + aloc(P);
}
}
}
end loop
completelyreduced := (reducedprocess = numberofprocess); 389
end;
Deadlock
Algoritmo para vários recursos com várias
unidades por recurso
req : matriz
alloc : matriz R0 R1 R2
avail : vetor
0 1 2 Avail

P0 0 0 1
P1 0 0 1 Requisição
P2 1 0 0

P0 1 1 0
P1 1 0 0 Alocação
P2 0 0 0

390
Deadlock
Algoritmo para vários recursos com várias
unidades por recurso
req : matriz
alloc : matriz
avail : vetor
A linha if (req(P) <= avail) then é substituída por
reducedbyp := true
for (R = 1; R <= numberofressources; R++) {
if req(P)(R) > avail(R) then {
reducedbyp := false;
}
if (reducedbyp) then
A linha avail := avail + aloc(P); é substituída por
for (R = 1; R <= numberofressources; R++) {
avail(R) := avail(R) + aloc(P)(R); 391
}
Deadlock
Quando executar o algoritmo
Î Quando uma requisição não pode ser satisfeita
Î Quando existe suspeita de deadlock
Ex: Um processo está bloqueado há muito tempo

392
Deadlock
Recuperação de deadlock
Quando o algoritmo de detecção de deadlock determina a
existência de um deadlock, muitas ações são possíveis:
a) Terminação de processos
Î Terminar todos os processos
Îreexecução
Î escolher uma vítima por vez até que o deadlock seja
eliminado
Îescolher criteriosamente
Îreexecutar o algoritmo de detecção
Problema da reexecução de um processo
nem sempre é possível
ex. atualização de base de dados
393
Deadlock
Recuperação de deadlock
b) Preempção de recursos
Recursos são retirados de processos no ciclo e entregues a
outros, no mesmo ciclo, até que o deadlock seja eliminado.
Problema: A escolha da vítima
c) Rollback
Î Os processos possuem checkpoints, em que,
periodicamente, o estado é gravado em um arquivo
(imagem de memória, recursos)
Î quando um deadlock é detectado, o processo é
rolledback até antes de pedir um recurso
Î o recurso é atribuído a um outro processo no ciclo
394
Deadlock
Eliminar condições necessárias
Previne-se situações de deadlock eliminando-se pelo menos
uma das condições necessárias para sua ocorrência

a) Quando um processo que já tem um recurso pode solicitar


outro
esta condição é eliminada se todo processo solicitar todos
os recursos necessários antes de iniciar a execução

395
Deadlock
Eliminar condições necessárias
b) Quando os recursos não podem ser confiscados
temporariamente para serem alocados a outros processos
Um processo pode requisitar e liberar recursos, mas quando
requisitar um recurso não disponível deve liberar os que
estava utilizando e, então solicitar todos coletivamente
c) Quando é possível a formação de um ciclo no qual cada
processo esta bloqueado a espera de recursos que estão alocados
para outros processos do mesmo ciclo
esta condição é eliminada se os recursos existentes são
hierarquizados e os processos são obrigados a solicitá-los na
ordem crescente dessa hierarquia 396
Deadlock
Conj. recursos
r = { r1, r2, r3, ... ,rn}
função f = r -> N onde N é o conjunto dos números naturais
f(disco) = 1
f(fita) = 2
f(impressora) = 3

Processo que requisita r(I) somente pode requisitar r(j) se e


somente se f(rj) > f(ri) ou somente requisita rj após liberar ri
se f(ri) > f(rj)

397
Deadlock
Evitar deadlocks
abordagem: aumentar informação sobre o uso
de recursos

Î Os recursos são requisitados quando necessários


Î O sistema deve decidir se a requisição pode ser atendida
sem gerar deadlock
Î Os algoritmos necessitam que os processos declarem o
máximo de recursos, de cada tipo, necessários

398
Deadlock
Estado seguro/não seguro
Î Se o sistema consegue alocar recursos para cada processo,
em alguma ordem, e ainda evitar deadlock, o estado é seguro
“ O estado é seguro se existe uma seqüência segura “
“ O estado é não seguro se não existe uma seqüência segura “
“ O estado de deadlock é um estado não seguro “
“ Nem todo estado não seguro é um estado de deadlock “

399
Deadlock
Estado seguro/não seguro
Î Com a informação de número máximo de recursos
necessários para cada processo é possível construir um
algoritmo que assegura que o sistema nunca entrará em
deadlock
Î O algoritmo examina dinamicamente o estado de alocação
de recursos para assegurar que não existe uma espera circular
Î O estado de alocação é definida pelo número de disponíveis,
alocados e demanda máxima de cada processo

400
Deadlock
Exemplo
Possui Máximo
P0 3 10
P1 2 4
P2 2 8
Número de unidades do recurso:12, disponível:5
Possui Máximo
P0 5 10
P1 2 4
P2 2 8
Número de unidades do recurso:12, disponível:3
Possui Máximo
P0 5 10
P1 2 4
P2 3 8
Número de unidades do recurso:12, disponível:2
401
Deadlock
Suponhamos que:
P1 solicita duas unidades, é atendido e termina, liberando as
quatro unidades que possuía
Î O número de unidades disponíveis é 4
Î P0 solicita 5 unidades
Î P2 solicita 5 unidades

DEADLOCK

O sistema passou de um estado seguro para não seguro

402
Deadlock
Algoritmo para evitar deadlocks
Î Baseado no estado
Î Dijkstra 1965
Î Banker`s algorithm

403
Deadlock
Proc Tape Printer Driver
P0 2 0 0
P1 0 0 0
P2 1 1 1
P3 1 1 0
Matriz alocação
P0 1 1 1
P1 2 1 1
P2 0 0 0
P3 1 0 1
Matriz necessidade
P0 3 1 1
P1 2 1 1
P2 1 1 1
P3 2 1 1
Matriz máximo
1 0 0
vetor disponível 404
Deadlock
Estrutura de dados
Î Available: Vetor que indica o número de unidades
disponíveis de cada tipo de recurso
ÎMax: Matriz que define, para cada processo, o número
máximo de unidades, de cada tipo de recurso, necessárias
Î Allocation: Matriz que define o número de unidade, de cada
tipo de recurso, alocadas presentemente para cada processo
Î Need: Matriz que indica o número de unidades, de cada
recurso, necessárias para cada processo (Max_Allocation)

405
Deadlock
Deadlock
Para uma requisição request (P,i) = k o processo P esta
solicitando k unidades do recurso i
if (request(P,i) <= need(P,i)) {
if (request(P,i) <= available(i)) {
available(i) = available(i) - k;
allocation(P,i) = allocation(P,i) + k;
need(P,i) = need(P,i) - k;
}
safe_state();
} else
erro; 406
Deadlock
Safe_state: Estrutura de dados:
temp: vetor
Finish: vetor
temp[i] = available[i];
finish[i] = false; “para todo i “
continue = true;
while(continue) {
continue = false;
if (need(i) <= temp(i) and finish(i) = false) {
temp(i) = temp(i) + allocation(i);
finish(i) = true;
continue = true;
}
}
if finish(i) = true para todo i then
o sistema esta em um estado safe 407
Estudo de Casos

408
UNIX
Unix

Shell

núcleo

hardware

410
Conteúdo

1 - Histórico
2 - Visão do Usuário
3 - Serviços do sistema
4 - Arquitetura do sistema
Entidades: Arquivos
Processos
5 - Bibliografia
411
Visão do usuário

„ Sistema de arquivos
– Hierárquico
– Criação / destruição de arquivos
– Crescimento dinâmico de arquivos
– Proteção

„ Exercício: fazer um programa COPY

412
Visão do usuário (cont.)

„ Ambiente de execução
– Programa: arquivo executável
– Processo: programa em execução
– Processos solicitam os serviços do núcleo
com o uso de chamadas de sistema. Ex.: fork,
exec, etc.

„ Exercício: fazer um programa com fork

413
Shell

„ Interface entre o usuário e o sistema


„ Interpretador de comandos
„ Executa:
– comandos simples
– comandos compostos
– redirecionamento de I/O
– pipe
– if then else; for; while;
– etc;
414
Shell (cont.)

„ Funcionamento: (detalhar)
while (1) {
ler comando;
criar filho para executar;
}

„ Exercício: fazer um shell simplificado

415
Serviços do Sistema

„ Controlar processos;
„ Escalonar;
„ Alocar / liberar memória;
„ Gerenciar memória secundária;
„ E / S.

416
Arquitetura do Sistema
Programas Biblioteca
Nível Usuário
Nível Núcleo
Interface

Sub-sistema de Comunicação
arquivos Sub-sistema
de gerência
Cache Scheduling
de processos
Carac. Blocos
Ger. Memória
Drivers

Hardware
417
Arquivos

418
Representação Interna dos Arquivos

„ Fornecida por um i-node;


„ I-node: contém a descrição do arquivo;
„ Cada arquivo contém um i-node;
„ Mais de um nome pode estar associado a um i-
node;
„ O sistema gerencia os arquivos com três tabelas:
– Tabela de arquivos abertos: uma por processo
– Tabela de arquivos: global
– Tabela de i-nodes: global
419
Tabelas usadas para acesso aos
arquivos
Tab. Arq. Abertos Tab. Arquivos Tab. I-nodes

420
I-nodes

„ Proprietário;
„ Tipo de arquivo (ordinário, diretório, bloco
especial, caracter especial, fifo(pipe));
„ Direitos de acesso;
„ Datas de acesso (acesso, modificação,
modificação de i-node);
„ Número de links;
„ Lista de blocos;
„ Tamanho do arquivo;
421
I-nodes (cont.)
– Proprietário José
– Grupo Parsys
– Tipo Ordinário
– Permissões RWX R_X R_X
– Acessado 08 July 1999 21:00
– Modificado 08 July 1999 21:00
– Tamanho 7820 bytes
– Blocos de dados 32,27,85,31,84,92,23,55,30,77
Indireção
Dupla indireção
Tripla indireção

422
I-node na Memória

„ Estado do I-node
– Bloqueado / não bloqueado
– Processos bloqueados
„ Número do periférico;
„ Número do i-node;
„ Contador de referências;

423
Estrutura do sistema de arquivos

boot super bloco lista i-nodes blocos dados

„ Boot: contém o código de boot;


„ Super bloco: descreve o sistema de
arquivos (lista de blocos livres, número de
arquivos, tamanho das outras áreas);
„ Lista de i-nodes: configurável pelo
administrador, referenciados por um índice.

424
Tamanho dos arquivos

„ 10 blocos diretos (1 K) = 10 K
„ 1 indireto c/ 256 diretos = 256 K
„ 1 duplo indireto c/ 256 diretos = 64 M
„ 1 tripla indireção c/ 256 dupla indireção
= 16 G

425
Conversão de um caminho de
acesso em um i-node
(/usr/parsys/ep/artigo)

/ I-node 12 bloco 134


proprietário
ep 25
Direitos de acesso
ctc jn
pass im
usr 12 134

426
Conversão de um caminho de
acesso em um i-node (cont.)

Bloco 256 I-node 13


I-node 25 (artigo) (artigo)

prop pum 5 prop


direitos mpi 11 direitos
tipo artigo 13 tipo
256 aulas 27 bloco 0
prog 89 bloco 1

427
Chamadas de Sistema

„ open
„ close
„ read
„ write
„ create
„ mkdir
„ cd
„ pipe
428
open

fd = open ( nome, modo );


transformar “nome” em i-node
if (ñ existe ou acesso ñ permitido)
return (erro);
Alocar uma entrada da Tabela de Arquivos
Atribuir à Tabela de Arquivos o i-node
Inicializar contador de deslocamento
Alocar uma entrada na Tabela de AA
Atribuir à TAA o índice da Tabela de Arquivos
Return( índice da TAA )
429
open (cont.)

TAA T-Arquivos T-Inodes


0
1
2

T-Arquivos: - apontador p/ tabela de i-nodes


- deslocamento (byte corrente)
- direito (leitura / escrita)
- contador de referências
430
pipe

„ Alocar um i-node
„ Alocar um elemento da tabela de arquivos (em
escrita)
„ Alocar um elemento da tabela de arquivos (em
leitura)
„ Inicializar o contador de referência do i-node em 2
„ Alocar um par de entradas em TAA (processo)
„ Atribuir os elementos da tabela de arquivos
„ Retornar (elementos da TAA)

431
Exemplo de Programa
main() {
int fds (2);
char c ;
pipe (fds);
pid = fork () ;
if pid != 0 {
for ( ; ; ){
c = getchar () ;
write (fds (1),&c, sizeof (char)));
}
else {
read ( fds (0), &c, sizeof (char));
printf (“%c\n”, c) ;
}
}
432
Processos

433
Controle de processos

„ fork
„ kill
„ exec
„ exit
„ wait

434
exec

„ acessar o arquivo
„ verificar se é executável
„ alocar memória (código, dados, pilha)
„ efetuar a carga
„ liberar a região de memória usada
anteriormente

435
fork

„ fork()
– Cria uma cópia exata do processo original,
incluindo registradores, descritores de
arquivos, etc;
– Cada processo tem seu próprio espaço de
endereçamento;
– Retorna um valor (zero para o filho, o pid
do filho para o pai);

436
fork (cont.)

„ Procurar uma entrada livre na tabela de


processos;
„ Alocar memória;
„ Copiar a imagem do pai para o filho;
„ Colocar no descritor o mapa de
memória do filho;
„ Fabricar um pid para o filho;
„ Sinalizar ao pai final de operação;
437
Exemplo de uso: shell

While (1){
read_command ( command, par );
pid = fork();
if (pid != 0)
if not background wait();
else
exec(command, par);
}
438

Potrebbero piacerti anche