Escolar Documentos
Profissional Documentos
Cultura Documentos
Capítulo 6
Sistema de entrada/saída
6.1. Introdução
• E/S programada: quando um processo inicia uma operação de E/S, a UCP faz a
verificação se o dispositivo já se encontra pronto para a transmissão de outro
dado (estado chamado de espera ociosa ou pooling). Este é um modelo simples,
mas pouco eficaz, pois a UCP fica alocada ao processo até que a operação de
E/S seja concluída, ficando ociosa durante este tempo.
Drivers de classes de dispositivos: um driver de disco SCSI pode tratar vários discos
SCSI de diferentes tamanhos e velocidades.
O uso deste sistema busca respondar a seguinte pergunta: como impedir que um
usuário crie um processo que ocupe um dispositivo de E/S durante longos períodos, mas
que não faça nada?
3
Faça uma revisão sobre a estrutura e funcionamento de discos rígidos, matéria abordada em livros de
Arquitetura de Computadores
4
Aproveite e faça uma pesquisa sobre o funcionamento de memórias SSD – solid state drive
_________________________________________________________________ 81
Fisicamente os discos rígidos possuem duas superfícies, sendo cada uma delas
divididas em trilhas e setores. Um setor é a menor unidade onde pode ser feito um
acesso em um disco, através da cabeça de leitura e escrita. Uma solicitação de acesso
deve especificar superfície, trilha e setor desejados.
A velocidade de acesso ao disco pode ser composta por três partes. Para realizar
o acesso ao setor do disco, primeiro devemos mover a cabeça de leitura e escrita para a
trilha apropriada. O tempo gasto neste movimento é denominado seek time (tempo de
busca). Uma vez atingida a trilha correta, é necessário esperar que o setor desejado seja
rotacionado sob a cabeça de leitura e escrita. Este tempo é denominado latency time
(tempo de latência). Finalmente, há a transferência de dados entre o disco e a memória
principal. O tempo gasto na transferência dos dados é denominado transfer time (tempo
de transferência). O tempo total do serviço de um pedido ao disco é dado pela soma
destas três fatias de tempo.
• Entrada ou saída;
• Endereço do disco (disco, trilha, setor);
• Endereço de memória;
• Quantidade de informação a ser transferida.
First-Come-First-Served (FCFS)
640 trilhas e pode ser visto na figura 6.3. Se pudesse ser feita uma troca na ordem de
atendimento dos pedidos, o tempo para atender aos pedidos poderia decrescer
substancialmente. Por exemplo, trocando os pedidos pela trilha 122 e 14. Assim, após
atender ao pedido 37, atenderia ao pedido 14, depois o 122 e 124. Este fato melhoraria
muito o desempenho, pois reduziria o movimento total da cabeça de leitura e escrita
para 425 trilhas.
Este algoritmo seleciona o pedido com o menor seek time a partir da posição
corrente da cabeça de leitura e escrita. Uma vez que o seek time é proporcional a
diferença de trilhas entre os pedidos, esta abordagem é implementada movendo a cabeça
de leitura e escrita para a trilha mais próxima na fila de pedidos. Para a mesma fila de
pedidos, temos na figura 6.4, a ilustração de como é o procedimento do algoritmo SSTF.
SCAN
6.7 Resumo
O sistema Operacional tem um importante papel no funcionamento de uma
infinidade de dispositivos responsáveis pela entrada e saída de dados do sistema. Deve
ainda gerenciar as formas de transferência de dados entre tais dispositivos e a memória
do sistema computacional, além de saber se comunicar corretamente com eles, o que faz
necessário o uso de drivers de dispositivos.
Capítulo 7
5
Em alguns casos é possível que outros processos acessem um recurso compartilhado, como a variável
citada, porém, com permissão somente para leitura do valor, incapazes de alterá-la, enquanto não estiver
liberada.
_________________________________________________________________ 87
verifica o valor desta variável. Se for igual a 0, ele pode entrar na sua seção crítica e
altera o valor da variável para 1. Se, ao testar a variável, o valor já for igual a 1, o
processo deve aguardar até que o valor passe para 0, indicando que algum outro
processo saiu da seção crítica, liberando os recursos do sistema.
Este método também pode estar sujeito a falhas: suponha que um processo
verificou o valor de lock, que é igual a 0. Existe a possibilidade que, antes que este
primeiro processo altere o valor de lock para 1, um segundo processo seja escalonado,
execute e altere a variável de lock para 1. Ao executar novamente, o primeiro processo
também grava o valor 1 na variável de lock, e então existirão dois processos em suas
seções críticas ao mesmo tempo.
Quando o processo A deixa sua seção crítica, muda o valor de turn para 1, o que
permite ao processo B entrar em sua região crítica. Apesar de ser uma solução que
obrigue que os processos alternem suas entradas nas regiões críticas, não garante o
impedimento de uma situação de parada do sistema causada por erro na alternância7,
violando a terceira condição da lista já apresentada.
6
Espera ociosa (busy waiting) deve ser evitada, já que gasta tempo de CPU. Só é aceitável quando há
uma expectativa razoável que o tempo de espera seja breve.
7
Como isto pode acontecer? Pesquise a respeito e apresente os resultados.
_________________________________________________________________ 89
o que só acontecerá quando o processo 0 chamar a função leave_region para sair de sua
seção crítica. Nesta solução, caso os processos chamem a função enter_region quase
simultaneamente, ambos armazenarão seus valores na variável turn, porém, prevalecerá
o que armazenou por último, sobrescrevendo o anterior.
A Instrução TLS é um mnemônico para test and set lock, isto é, lê o conteúdo da
palavra de memória (neste caso, o lock, no registrador RX), e armazena um valor
diferente de zero no endereço de memória lock; as operações de leitura e
armazenamento de uma palavra são indivisíveis, o que garante que nenhum outro
processador acesse a palavra de memória até o término da instrução, pois bloqueia o
acesso ao barramento de memória para outras CPUs.
8
Pesquise a respeito, parece uma daquelas perguntas que o professor gosta de colocar na prova.
_________________________________________________________________ 90
• Quando o produtor quer colocar um novo item produzido no buffer, mas este
encontra-se cheio. Neste caso, o produtor deve ser colocado para dormir, e ser
acordado quando ao menos um processo consumidor retirar um ou mais itens do
buffer.
• Quando o consumidor quer retirar um item do buffer, mas este estiver vazio; de
forma análoga ao processo produtor, o consumidor deve ser colocado para dormir e
ser acordado quando o produtor tiver colocado algum novo item no buffer.
7.4. Semáforos
A questão sobre a comunicação interprocessos foi abordada em 1965 pelo
conceituado cientista da computação, E. W. Dijkstra9, que propôs a utilização de uma
variável inteira, o semáforo, utilizada para contar o número de sinais de acordar salvos
para uso posterior. Duas operações podem ser feitas sobre o sinal, up e down (apesar de
ser muito comum ver implementações que utilizam as letras P e V para implementar as
operações. Como Dijkstra era holandês, originalmente as operações eram Proberen
(testar), e Verhogen (incrementar)).
9
Pesquise sobre a obra de Dijkstra, o site http://en.wikipedia.org/wiki/Edsger_W._Dijkstra contém um
resumo de sua vida e obra
_________________________________________________________________ 91
• mutex: usada para garantir que os processos produtor e consumidor não acessem
simultaneamente o buffer. Inicializada com o valor 1, pois é um semáforo
binário. Observe no trecho de código a seguir que em ambos os processos, a
primeira operação feita em um mutex é sempre um down, e ao sair da seção
crítica, um up, o que garante a exclusão mútua.
7.5. Mutexes
Um mutex funciona como um semáforo simplificado, pois não possui a
capacidade de contar, e, como o nome diz10, é utilizado para tratar a questão da exclusão
10
Mutex é a abreviação de mutual exclusion – exclusão mútua.
_________________________________________________________________ 92
mútua. Pode ser representado com somente 1 bit, já que só pode representar dois
estados: impedido ou desimpedido.
Sobre um mutex operam as operações de lock, para ter acesso a uma seção
crítica, e unlock, para liberá-la. Caso o mutex já esteja em uso e outro processo tente
utilizar o lock, este permanecerá bloqueado até que o processo que esteja na seção
crítica utilize o unlock. Se múltiplos processos estiverem bloqueados sobre um mesmo
mutex, quando este for liberado, o S.O escolherá um deles aleatoriamente para adquirir
o mutex em seguida.
7.6. Monitores
Apesar das funcionalidades, alguns dos métodos anteriores, como os semáforos,
possuem vulnerabilidades contra falhas críticas, podendo enfrentar até situações que
terminem em uma situação de impasse11, o que motivou vários pesquisadores a estudar
métodos alternativos. Na década de 70, dois pesquisadores, Hoare e Brinch Hansen,
desenvolveram pesquisas separadamente, e chegaram a soluções similares, que
consistiam em uma unidade básica de sincronização de alto nível, chamada de monitor.
11
Deadlock, assunto que será tratado no próximo capítulo. Por enquanto, basta saber que deadlocks são
muito, muito ruins. Você não vai querer que um aconteça em seu sistema.
_________________________________________________________________ 93
12
Estes são problemas clássicos de transmissão de dados. Maiores detalhes serão discutidos nas
disciplinas de Redes de Computadores
_________________________________________________________________ 94
7.8. Barreiras
Barreiras são mecanismos de sincronização para grupos de processos, ao invés
de pares que atuam no modelo produtor/consumidor. Certas aplicações utilizam o
conceito de fases, de forma que nenhum processo que tenha concluído pode passar para
a fase seguinte até que todos os outros processos também já estejam em condição de
fazê-lo. Como exemplificado na figura 7.2, ao alcançar uma barreira estabelecida, um
processo ficará no estado de bloqueado (através de uma chamada a um procedimento de
biblioteca barrier) até que todos os demais processos também alcancem a barreira, para
ultrapassá-la juntos.
Problema proposto em 1965 por Dijkstra, desde então é utilizado para analisar o
funcionamento de novas técnicas de sincronização entre processos que venham a surgir.
O problema é caracterizado por cinco filósofos sentados em torno de uma mesa circular,
cada um com seu prato de espaguete. Cada filósofo só faz duas coisas na vida: comer e
filosofar. Quando vai comer, ele deve pegar os garfos à sua direita e à sua esquerda,
pois o espaguete está escorregadio, portando, precisa dos dois, 14 porém, só existem
cinco garfos na mesa. Quando termina de comer, ele coloca os garfos de volta na mesa e
começa a filosofar, até que sinta fome novamente, quando tornará a pegar os garfos para
comer mais. A figura 7.3 ilustra o que seria o ambiente real do problema.
13
Geralmente o processo paralelo cria a ilusão que um único sistema computacional de grande porte
tenha feito o processamento, e não que o resultado foi gerado por um conjunto de recursos
computacionais atuando cooperativamente.
14
Em publicações mais recentes, o enunciado foi ‘atualizado’ para comida japonesa e cada filósofo usa
hashis, os ‘pauzinhos’ para comer, o que torna mais plausível a necessidade de pegar os dois talheres
adjacentes, ao invés dos garfos.
_________________________________________________________________ 96
Existem várias propostas para a solução deste problema, porém, algumas levam
a situações de processos atingirem um estado de starvation, ou que o correto
funcionamento dependerá de uma aleatoriedade em algum fator, ou ainda, limitam a
somente um filósofo estar comendo a cada instante. Existe uma solução que evita
deadlocks, e permite o máximo paralelismo a um número arbitrário de filósofos, através
de arranjos de semáforos, um por filósofo, e um mecanismo de controle para determinar
se o filósofo está comendo, pensando ou faminto (tentando pegar os garfos).
7.10. Resumo
Em sistemas operacionais modernos, é comum ter vários processos que precisam
se comunicar entre si. Em diversas situações estes processos podem compartilhar
posições de memória, a partir dos quais realizam operações de leitura e escrita de dados.
Eventualmente surgem situações de disputa, onde dois ou mais processos querem fazer
uso simultâneo de um recurso compartilhado, o que pode levá-los a condições de
conflito.
Capítulo 8
Deadlocks
• Espera Circular: Deve existir um conjunto de processos {p0, p1, ...pn} tal que
p0 espera por um recurso que está sendo usado por p1, p1 espera por um recurso
que está sendo usado por p2 e assim por diante, até que pn espera por um
recurso que esta sendo usado por p0.
15
É sério, este é o nome do método, que é adotado por diversas versões de Windows e Unix.
_________________________________________________________________ 101
Figura 8.2. (a) processo de posse de um recurso; (b) processo aguardando por um recurso; (c)
deadlock.
Exclusão mútua
A condição de exclusão mútua é mantida para tipos de recursos que não podem
ser compartilhados (por exemplo, uma impressora). Já os recursos que podem ser
compartilhados não necessitam de acesso mutuamente exclusivo, e, portanto, não
_________________________________________________________________ 102
Para que a condição hold and wait nunca se mantenha no sistema, devemos
garantir que sempre que um processo peça por um recurso, ele não mantenha qualquer
outro recurso. Um protocolo que pode ser utilizado requer que cada processo peça e
receba todos os recursos necessários antes que inicie a execução. Este fato provoca a
subutilização dos recursos.
Sem preempção
Espera circular
Para que a espera circular não ocorra é imposta uma ordenação linear de todos os
tipos de recursos. É atribuído a cada recurso um número inteiro único, que permite a
comparação entre os recursos e determinar qual recurso precede outro na ordenação.
Num protocolo para prevenir deadIock cada processo pode pedir somente recursos
numa ordem crescente de numeração. Isto é, um processo pode pedir inicialmente um
tipo de recurso ri, após isto, o processo pode pedir um novo recurso rj se e somente se
F(rj) >F(ri).
Apesar de este exemplo ilustrar uma situação de estado seguro que levou a um
deadlock, não podemos afirmar isto para qualquer situação, pois é considerada que a
diferença entre um estado seguro e um inseguro é que o primeiro pode garantir que
todos os processos terminarão; já no estado inseguro, esta garantia não pode ser dada.
Por melhores que sejam as intenções, evitar completamente deadlocks em um sistema é
praticamente impossível, por isso a maior parte dos esforços concentram-se na
prevenção e recuperação do sistema.
_________________________________________________________________ 104
8.4.1. Detecção
Usando o mesmo raciocínio, suponha agora que além das duas unidades de fita e
do plotter, o processo P3 necessite de um CD-ROM, o que acontecerá?
8.4.2. Recuperação
A recuperação de uma situação de deadlock deve ocorrer sempre que ela for
detectada. Existem três operações que recuperam o sistema, baseado nas quatro
condições que levam ao deadlock A primeira seria violar a exclusão mútua, o que não
pode ser feito. A segunda é abortar um ou mais processos para quebrar a espera circular
e trazê-los de volta ao sistema em um tempo posterior. A terceira é retirar alguns
recursos de um ou mais processos em deadlock. Assim, se utilizarmos a segunda ou a
terceira operação, devem ser considerados três pontos:
• Seleção de uma vítima. Quais recursos de quais processos devem ser retirados?
• Rollback: Se retirarmos um recurso de um processo, o que deveríamos fazer com
ele' Devemos retornar a execução até atingir um estado seguro?
• Starvation: Como garantir que o starvation não ocorrerá? Isto é, como garantir
que um mesmo processo não será sempre o escolhido para ser retirado do
sistema?
• Prioridade do processo;
_________________________________________________________________ 107
• Quanto tempo o processo já completou e o quanto ainda falta para terminar a sua
execução.
• Quantos e quais tipos de recursos o processo usou até o momento?
• Qual a quantidade de processos envolvidos no rollback?
Rollback
Uma vez decidido qual o processo que sofrerá o rollback, devemos determinar o
quanto este processo deve retornar na sua execução. A solução mais simples é retornar
tudo, isto é, parar o processo e reiniciá-lo, porém esta solução é a mais custosa. Outra
solução é retorná-lo o suficiente para quebrar o deadlock, porém isto necessita que o
sistema mantenha mais informações sobre o estado de todos os processos que estão
executando.
Starvation (inanição)
Alguns sistemas podem evitar o deadlock através de uma política que defina
quais processos devem ganhar um recurso e em qual momento, porém, este processo
pode ter suas solicitações negadas indefinidamente, causando a starvation. Deve-se
garantir que um processo só possa ser escolhido como vítima um número limitado de
vezes. Desta forma, impedimos que ocorra starvation.
_________________________________________________________________ 108
8.5. Resumo
Deadlocks representam um potencial problema para sistemas operacionais, pois
estão relacionados com a alocação de recursos do sistema aos processos do usuário. Na
ocorrência de uma situação onde um processo obtém acesso exclusivo a alguns recursos
e necessita de recursos alocados a outros processos e assim por diante, gerando uma
situação de impasse, está caracterizado um deadlock.
Deadlocks são difíceis de ser evitados por questões de sua própria natureza,
porém, existem métodos que podem ser utilizados para previnir a sua ocorrência e caso
aconteçam, corrigir o sistema.