Baixe o app para aproveitar ainda mais
Prévia do material em texto
REVISÃO DE SISTEMAS OPERACIONAIS PROCESSOS É um módulo executável único, que corre concorrentemente com outros módulos executáveis. Um sistema operacional não executa somente os programa que podemos ver. Imagine que os aplicativos que você roda reúnem diversas instruções e comandos, porém, são os processos que efetivamente executam esses comandos. Isso significa que um único aplicativo pode ter vários processos relacionados a ele. Por exemplo, o navegador Google Chrome, que executa uma nova tarefa a cada aba aberta. Essa medida permite que cada aba seja gerenciada individualmente e, mesmo que uma trave, as outras continuam trabalhando normalmente. Fato 1: Nossas máquinas executam vários processos simultaneamente. Fato 2: Existe apenas um processador em nossas máquinas. Conclusão: Existe um pseudo-paralelismo Tipos de Processos: -Processos CPU bound: utiliza muito do processador -Processos I/O bound: muitas operações de entrada e saída de dados -Ideal: balanceamento entre os processos anteriores Criação de Processos: - No início de tudo, o SO está executando sozinho. - Outros processos são criados: Na inicialização do sistema; Por system calls de criação de processos; Por solicitação direta do usuário executar um programa; Pela execução de um programa batch. - Sempre existe um processo executando uma system call para a criação de um novo processo. - EXEMPLOS DE DIFERENTES IMPLEMENTAÇÕES: DOS: System call que carrega um novo processo na sua memória e o executa. O processo “pai” aguarda seu encerramento. UNIX: A System call fork duplica o processo pai. A System call execve altera o conteúdo da memória substituindo por um novo e o executa. Término de Processos: -Saída normal (voluntária): EXIT -Saída por erro (voluntária): IMPOSSIBILADE DE EXECUTAR UMA INSTRUÇÃO -Erro fatal (involuntária): EXECUÇÃO DE INSTRUÇÃO ILEGAL -Cancelamento por um outro processo (involuntário): KILL Hierarquia de processos: -Pai cria um processo filho, o processo filho pode criar o seu próprio processo. -UNIX chama isso de “grupos de processos” -Windows não possui o conceito de hierarquia de processos – todos os processos são iguais. Estados de Processos: -Um processo passa por diferentes estados desde sua criação até seu término. Enquanto ele é criado, seu estado é considerado "Novo"; em ação, muda para "Executando"; quando depende da ocorrência de algum evento, vira "Esperando"; quando não mais necessário, o processo é "Terminado". O sistema operacional reúne todas essas informações através de estruturas específicas chamadas PCB (sigla de Process Control Blocks, o que em tradução livre seria Blocos de Controle de Processos). Implementação de Processos: COMUNICAÇÃO ENTRE PROCESSOS É o grupo de mecanismos que permite aos processos transferirem informação entre si. Thread: é um pequeno programa que trabalha como um subsistema, sendo uma forma de um processo se autodividir em duas ou mais tarefas. É o termo em inglês para Linha ou Encadeamento de Execução. Essas tarefas múltiplas podem ser executadas simultaneamente para rodar mais rápido do que um programa em um único bloco ou praticamente juntas, mas que são tão rápidas que parecem estar trabalhando em conjunto ao mesmo tempo. Threads de Usuário: -Vantagem: velocidade -Desvantagens: gerenciamento de THREADS do espaço usuário e o bloqueio de uma THREAD bloqueia todo o processo. Modelos de Comunicação entre Processos: -Memória Compartilhada: uma região de memória é compartilhada entre os processos. -Troca de Mensagem: Ocorre por meio de troca de mensagens entre os processos. Ambiente de Cooperação entre Processos: -Motivos: Compartilhamento de informações, agilidade na computação, modularidade e conveniência Condições de Corrida (DISPUTA): -Situações onde dois ou mais processos estão acessando dados compartilhados. -O resultado final pode variar de acordo com a ordem de execução. -Mecanismo de Sincronização: A sincronização entre processos permite gerir o acesso concorrente a recursos do sistema operativo de forma controlada por parte dos processos, de maneira que um recurso não seja modificado em simultâneo, ou que os processos não fiquem em espera que o recurso seja libertado. Concorrência em Programas: -Enquanto um processo estiver usando um recurso, os outros devem aguardar até que o recurso esteja liberado. -Exclusão Mútua: A exclusão mútua deve afetar os processos concorrentes quando um deles estiver em uma região crítica. Soluções de Hardware: -Desabilitação das interrupções: Solução mais simples para a exclusão mútua; Falha de Proteção: O processo precisa voltar a habilitar as interrupções. Não aplicável para múltiplas CPUs. Este recurso só deve ser permitido ao SO. -Instrução Test-and-Set. Utilização de uma variável para testar a possibilidade de executar a região crítica. O teste e o bloqueio são realizados através de uma única instrução (TSL). O processo impedido de executar sua região crítica executa um loop de espera. Gasto de CPU. -Variável de Travamento; Uma variável é utilizada para informar se algum outro processo está em sua respectiva região crítica; Gera uma nova condições de corrida. -Estrita Alternância. Processos se alternam na execução da região crítica; Processos podem estar bloqueados, sem ninguém estar em sua região crítica; É necessário que os processos possuam freqüência semelhante na execução da região crítica. -Solução de Peterson: Chamadas a rotinas antes de entrar e após sair da região crítica; A rotina de entrada só retorna quando não houver outro processo executando a sua região crítica. -Chamadas sleep e wakeup: SLEEP: Coloca o processo chamador no estado de espera. WAKEUP: Coloca um outro processo que está em espera no estado de pronto. SEMÁFOROS E PROBLEMAS CLÁSSICOS DE SINCRONIZAÇÃO Semáforos: é uma variável especial protegida (ou tipo abstrato de dados) que tem como função o controle de acesso a recursos compartilhados (por exemplo, um espaço de armazenamento) num ambiente multitarefa. Jantar dos filósofos: IMPORTANTE Considere 5 filósofos que passam a vida a pensar e a comer. Partilham uma mesa redonda rodeada por 5 cadeiras sendo que cada uma das cadeiras pertence a um filósofo. No centro da mesa encontra-se uma taça de arroz e estão 5 garfos na mesa, um para cada filósofo. Quando um filósofo pensa não interage com os seus colegas. De tempos em tempos, cada filósofo fica com fome e tenta apanhar os dois garfos que estão mais próximos (os garfos que estão ou à esquerda ou à direita). O filósofo apenas pode apanhar um garfo de cada vez e como o leitor compreende, não pode apanhar um garfo se este estiver na mão do vizinho. Quando um filósofo esfomeado tiver 2 garfos ao mesmo tempo ele come sem largar os garfos. Apenas quando acaba de comer, o filósofo pousa os garfos, libertando-os e começa a pensar de novo. O nosso objetivo é ter uma representação/implementação que nos permita simular este jantar sem que haja problemas de deadlock ou starvation. Para isso, o jantar será modelado usando uma thread para representar cada filósofo e usaremos semáforos para representar cada garfo. Quando um filósofo tenta agarrar um garfo executa uma operação wait no semáforo, quando o filósofo larga o garfo executa uma operação signal nesse mesmo semáforo. Cada filósofo (thread) vai seguir o algoritmo, ou seja, todos fazem as mesmas ações. Como deve estar já o leitor a pensar, o facto de seguirem o mesmo algoritmo pode dar azo à situação de deadlock, dai a utilização das primitivas de sincronização wait e signal. Uma outra possibilidade de deadlock seria o facto de mais do que um filósofo ficar com fomeao mesmo tempo, os filósofos famintos tentariam agarrar os garfos ao mesmo tempo. Isto é outro ponto que uma solução satisfatória terá que ter em atenção, devendo ser salvaguardado o facto de um filósofo não morrer à fome. Devemos recordar o leitor que uma solução livre de deadlock não elimina necessariamente a possibilidade de um filósofo morrer esfomeado. Barbeiro Sonolento: IMPORTANTE Na barbearia há um barbeiro, uma cadeira de barbeiro e n cadeiras para eventuais clientes esperarem a vez. Quando não há clientes, o barbeiro senta-se na cadeira de barbeiro e cai no sono. Quando chega um cliente, ele precisa acordar o barbeiro. Se outros clientes chegarem enquanto o barbeiro estiver cortando o cabelo de um cliente, eles se sentarão (se houver cadeiras vazias) ou sairão da barbearia (se todas as cadeiras estiverem ocupadas). O problema é programar o barbeiro e os clientes sem cair em condições de disputa. Esse problema é semelhante a situações com várias filas, como uma mesa de atendimento de telemarketing com diversos atendentes e com um sistema computadorizado de chamadas em espera, atendendo a um número limitado de chamadas que chegam. A solução aqui apresentada usa três semáforos: customers, que conta os clientes à espera de atendimento (exceto o cliente que está na cadeira de barbeiro, que não está esperando); barbers, o número de barbeiros (0 ou 1) que estão ociosos à espera de clientes, e mutex, que é usado para exclusão mútua. Precisamos ainda de uma variável, waiting, que também conta os clientes à espera de atendimento. É essencialmente uma cópia de customers. A razão de se ter waiting é que não há uma maneira de ler o valor atual do semáforo. Nessa solução, um cliente que entra na barbearia deve contar o número de clientes à espera de atendimento. Se este for menor que o número de cadeiras, ele ficará; do contrário, ele sairá. Na solução, quando chega de manhã para trabalhar, o barbeiro executa o método barber, que o leva a bloquear sobre o semáforo customers,que inicialmente está em 0. O barbeiro então vai dormir, e permanece dormindo até que o primeiro cliente apareça. Quando chega, o cliente executa customer e inicia obtendo mutex para entrar em uma região crítica. Se um outro cliente chega logo em seguida, o segundo nada pode fazer até que o primeiro libere o mutex. O cliente então verifica se o número de clientes à espera é menor que o número de cadeiras. Se não for, ele liberará o mutex e sairá sem cortar o cabelo. Se houver uma cadeira disponível, o cliente incrementará a variável inteira waiting. Ele faz então um up no semáforo customers, que acorda o barbeiro. Nesse ponto, o cliente e o barbeiro estão ambos acordados. Quando o cliente libera mutex, o barbeiro o pega, faz alguma limpeza e começa a cortar o cabelo. Quando termina o corte de cabelo, o cliente sai do procedimento e deixa a barbearia. Diferente de nossos exemplos anteriores, não há um laço para o cliente porque para cada um deles terá apenas um corte de cabelo. O barbeiro, contudo, contém um laço para tentar obter o próximo cliente. Se houver algum outro cliente, um novo corte de cabelo será iniciado. Do contrário, o barbeiro cairá no sono. Leitores e Escritores: IMPORTANTE Imagine, por exemplo, um sistema de reserva de linhas aéreas, com muitos processos em competição, querendo ler e escrever. É aceitável que múltiplos processos leiam a base de dados ao mesmo tempo, mas, se um processo estiver atualizando (escrevendo) na base de dados, nenhum outro processo pode ter acesso ao banco de dados, nem mesmo os leitores. A questão é: como programar os leitores e os escritores? Na solução apresentada abaixo, para obter o acesso à base de dados, o primeiro leitor faz um down no semáforo db. Os leitores subsequentes meramente incrementam um contador, rc. Conforme saem, os leitores decrescem o contador de um e o último leitor a sair faz um up no semáforo, permitindo que um eventual escritor bloqueado entre. Tal solução contém implicitamente uma decisão sutil que vale a pena ser comentada. Suponha que, enquanto um leitor está usando a base de dados, um outro leitor chegue. Como ter dois leitores ao mesmo tempo não é um problema, o segundo leitor é admitido. Um terceiro leitor e outros subsequentes podem também ser admitidos se chegarem. Agora, imagine que chegue um escritor. O escritor não pode ser admitido na base de dados, pois escritores devem ter acesso exclusivo. O escritor é então suspenso. Leitores adicionais chegam. Enquanto houver pelo menos um leitor ativo, leitores subsequentes serão admitidos. Como consequência dessa estratégia, enquanto houver um fluxo estável de leitores chegando, todos entrarão assim que chegarem. O escritor permanecerá suspenso até que nenhum leitor esteja presente. Se um novo leitor chegar - digamos, a cada dois segundos - e cada leitor levar cinco segundos para fazer seu trabalho, o escritor nunca entrará. ESCALONAMENTO DE PROCESSOS Um Escalonador de Processos é um subsistema do Sistema Operacional responsável por decidir o momento em que cada processo obterá a CPU. É utilizado algoritmos de escalonamento que estabelecem a lógica de tal decisão. Nesse momento de decidir qual escalonador será utilizado no sistema operacional, cabe avaliar o cenário que o sistema será utilizado. Algoritmos de Escalonamento SISTEMAS BATH: -FIFO -SJF -SJF com preempção -POR PRIORIDADE Algoritmo de Escalonamento SISTEMAS INTERATIVOS: -ROUND ROBIN -POR PRIORIDADE -MÚLTIPLAS FILAS -MÚLTIPLAS FILAS COM REALIMENTAÇÃO Escalonamento em SISTEMAS DE TEMPO REAL: -Dados: Conjunto de m eventos periódicos O evento i ocorre dentro do período Pi e requer Ci segundos Então a carga poderá ser tratada somente se Escalonamento de THREADS: -A JVM implementa um escalonador de threads simples chamado "escalonamento com prioridades fixas" -Threads rodam dependendo de sua prioridade em relação a outros threads -A prioridade de um thread: Quando um thread é criado, herda a prioridade do thread criador O método setPriority pode ser usado para alterar a prioridade Prioridades são inteiros entre MIN_PRIORITY e MAX_PRIORITY Um número mais alto dá prioridade "melhor" GERENCIAMENTO DE MEMÓRIA Gerenciador de Memória é a parte do SO que é responsável por cuidar de quais partes da memória estão em uso, quais estão livres, alocar memória a processos quando eles precisam, desalocar quando eles não necessitarem mais e gerenciar a troca dos processos entre a memória principal e o disco (quando a memória principal não é suficiente para manter todos os processos). Gerenciamento sem Troca ou Paginação: troca e paginação são métodos utilizados de movimentação da memória para o disco e vice-versa durante a execução dos processos. Sem troca ou paginação é o caso mais simples. Monoprogramação sem Troca ou Paginação: temos um único processo sendo executado por vez, de forma que o mesmo possa utilizar toda a memória disponível, com exceção da parte reservada ao SO (que permanece constante em local pré-determinado). O SO carrega um programa do disco para a memória executa-o e em seguida aguarda comandos do usuário para carregar um novo programa, que irá se sobrepor ao anterior. Multiprogramação: a monoprogramação não é mais utilizada em sistemas grandes, pois: -Muitas aplicações são mais facilmente programáveis, quando as dividimos em dois ou mais processo; -Os grandes computadores em geral oferecem serviços interativos simultaneamente para diversos usuários (seria impossível trabalhar com um único processo por vez, pois representaria sobrecarga devido à constante necessidade de chavear de um processo para outro – constantemente lendo e escrevendo no disco); -É necessário que diversos processos estejam “simultaneamente” emexecução devido as operações de E/S, que implica em grandes esperas nas quais por questão de eficiência a UCP deve ser entregue a outro processo. 1 1 m i i i C P= Gerenciamento de espaço: as duas principais formas de cuidar da utilização de memória são: -Gerenciamento com Mapa de Bits: A memória é subdividida em unidades de um certo tamanho. A cada unidade é associada um bit que se for 0 indica que essa parte da memória está livre e se for 1 indica que está ocupada. O tamanho deve ser cuidadosamente escolhido. A desvantagem é que quando um novo processo que ocupa k unidades de memória deve ser carregado na memória, o gerenciador deve percorrer o mapa de bits para encontrar k bits iguais a zero consecutivos, o que não é um processo simples. - Gerenciamento com Listas Encadeadas: mantemos uma lista encadeada de segmentos alocados e livres, sendo que cada segmento é um processo ou um buraco entre dois processos. A lista apresenta-se em ordem de endereços, e quando um processo termina ou é enviado para o disco, e a atualização da lista ocorre da seguinte maneira: cada processo, desde que não seja nem o primeiro nem o último da lista, apresenta-se cercado por dois segmentos, que podem ser buracos ou outros processos. Os buracos adjacentes devem ser combinados num único. Para escolher o ponto em que deve ser carregado um processo recém criado ou que veio do disco por uma troca, vamos utilizar alguns algoritmos assumindo que o gerenciador de memória sabe quanto espaço alocar no processo: 5. Alocação de espaço de troca (swap): espaço de troca é o espaço ocupado no disco pelos processos que aí estão guardados, pois foram retirados da memória devido a uma troca. Os algoritmos para gerenciar o espaço alocado em disco para swap são os mesmos apresentados para o gerenciamento de memória. A diferença é que em alguns sistemas, cada processo tem no disco um espaço reservado para o mesmo e na memória ele é constantemente mudado de lugar. Além disso, como os discos são dispositivos de bloco, a quantidade de espaço reservado para os processos no disco deverá ser múltipla do tamanho do bloco. 6. Memória Virtual: A primeira solução adotada para programas grandes demais para a quantidade de memória foi a utilização de overlays. Nesta técnica o programa era subdividido em partes menores (overlays), que podiam ser rodadas separadamente e quando um overlay terminava a execução um outro poderia ser carregado na mesma posição de memória utilizada pelo anterior. O problema é a divisão do programa em overlays não é simples e deve ser realizada pelo programador. A técnica de memória virtual para executar um programa que não cabe na memória existente consiste em manter partes do programa, dos dados e da pilha no disco, sendo que existe uma forma de decisão de quais processos devem permanecer no disco e quais na memória. Esta técnica é realizada de forma automática pelo computador. Podemos alocar diversos processos na memória virtual, de forma que cada um pensa ter uma quantidade de memória que somadas ultrapassam a quantidade real de memória. PROCESSOS COMUNICAÇÃO ENTRE PROCESSOS É o grupo de mecanismos que permite aos processos transferirem informação entre si. SEMÁFOROS E PROBLEMAS CLÁSSICOS DE SINCRONIZAÇÃO ESCALONAMENTO DE PROCESSOS Um Escalonador de Processos é um subsistema do Sistema Operacional responsável por decidir o momento em que cada processo obterá a CPU. É utilizado algoritmos de escalonamento que estabelecem a lógica de tal decisão. Nesse m... GERENCIAMENTO DE MEMÓRIA Gerenciador de Memória é a parte do SO que é responsável por cuidar de quais partes da memória estão em uso, quais estão livres, alocar memória a processos quando eles precisam, desalocar quando eles não necessitarem mais e ge...
Compartilhar