Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
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
4
Introdução
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
12
Introdução
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
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
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
29
Estrutura interna do Minix
MM FS NetS
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
}
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
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
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
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
65
running
selecionado
interrupção
ready blocked
evento
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
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
74
Algoritmos de Scheduling
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
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
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
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
86
Algoritmos de Scheduling
87
Algoritmos de Scheduling
88
Algoritmos de Scheduling
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)
2 4 1 3
0 1 5 10 17 26
preempção
92
Algoritmos de scheduling
93
Algoritmos de Scheduling
1 2 4 3
0 8 12 17 26
(8-TC)+(12-TC) +( 26-TC) + (17-TC) onde TC=tempo de chegada
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
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
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
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
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
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
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
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
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
128
proc.c - Principais funções
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
133
Multiprocessor Scheduling
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
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
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 ;
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
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 ;
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
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
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
169
Benefícios de threads
170
Benefícios de Threads
171
Estados de Threads
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
186
Programação Concorrente
“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
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
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
197
Seção Crítica de Código
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
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-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);
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 )
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 )
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
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
265
Software E/S
266
Software E/S
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
269
Software E/S
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
272
Software E/S
Processos do
usuário
Software independente
do dispositivo
Tratamento de
interrupções
Hardware
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
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
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
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
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)
...
...
32
33
...
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
291
Conceitos Básicos
292
Conceitos Básicos
293
Conceitos Básicos
294
Gerência de memória
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
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
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
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:
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
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
323
Paginação
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
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
332
Paginação
333
Paginação
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
337
Segmentação (cont.)
338
Segmentação
segment table
s
limite base
CPU (s d)
d yes
< +
memory
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
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
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
352
Organização de diretórios
games
mail
progs
353
Quantidade de diretórios
354
Quantidade de diretórios
root
root
A
A B C
B
...
D E F G
C
355
Quantidade de diretórios
356
Quantidade de diretórios
A B C
A1 B1 B2 C1 C2 C3
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
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
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
368
Compartilhamento de arquivos
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”
374
Gerência de blocos livres
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
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
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
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
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
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
397
Deadlock
Evitar deadlocks
abordagem: aumentar informação sobre o uso
de recursos
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
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
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.
413
Shell
Funcionamento: (detalhar)
while (1) {
ler comando;
criar filho para executar;
}
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
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
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)
426
Conversão de um caminho de
acesso em um i-node (cont.)
427
Chamadas de Sistema
open
close
read
write
create
mkdir
cd
pipe
428
open
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.)
While (1){
read_command ( command, par );
pid = fork();
if (pid != 0)
if not background wait();
else
exec(command, par);
}
438