A maior rede de estudos do Brasil

Grátis
58 pág.
Aula 1 a 10   Sistemas Operacionais

Pré-visualização | Página 1 de 2

Aula 1: Introdução a Sistemas Operacionais
Um velho conhecido pelos usuários de microcomputadores é a famosa “tela azul”. Quem já utilizou sistemas operacionais antigos, como o Windows 95, certamente já se deparou com este problema. A “tela azul” era de fato uma violação de acesso que tornava o sistema instável.
A partir do 80386, esse problema foi solucionado em termos de hardware através da possibilidade de 2 modos de execução: o modo protegido e o modo real. Ficava a cargo do sistema operacional a comutação entre esses dois modos por questões de compatibilidade.
A instabilidade evidenciada pela “tela azul” tem razões históricas. Os primeiros processadores da linha x86 possuíam um único modo de operação: o modo real. Dessa forma, todas as operações poderiam ser executadas diretamente pelas aplicações que, ao produzir erros, geravam panes no sistema.
As aplicações são executadas em modo usuário, ou seja, modo que não possui privilégios para operações que coloquem o sistema em risco tais como escrever no disco, criar novas tarefas etc.
Quando essas aplicações precisam executar tarefas críticas, é necessário que haja uma mudança para modo Kernel. Essa mudança ocorre através de uma “system call” ou chamada ao sistema.
Chamadas ao sistema (system call): Mecanismo responsável pela mudança de modo usuário para modo kernel. Ao invés de executar diretamente funções do kernel a aplicação executa uma função intermediária que verifica se o acesso ao kernel é seguro e, só então, completa a operação.
Voltando à “tela azul”: As aplicações podiam executar diretamente as funções do kernel sem a proteção da mudança de modo, ou seja, o erro acontecia após a execução de uma função do kernel. Com a mudança de modo, se a execução não for segura, a aplicação será impedida de continuar a execução e o sistema permanecerá estável.
Veja as simulações de um aplicativo com erro:
Execução não protegida
Execução protegida
Tipos de estrutura: 
Os sistemas são classificados em relação às atribuições do kernel e a relação entre seus módulos em monolíticos, camadas e microkernel.
Os sistemas modernos são divididos em dois grandes grupos: arquitetura monolítica e microkernel. A diferença entre elas está nas atribuições do núcleo do sistema operacional, denominado KERNEL.
Essa característica é muito importante no projeto de um Sistema Operacional e foi alvo de discussão entre dois grandes nomes da computação: Andrew Tanenbaum e Linus Torvalds.
São sinais de hardware fundamentais para a existência de sistemas multitarefa, pois provocam a suspensão da tarefa em execução pela ocorrência de um evento externo permitindo que outras tarefas compartilhem o tempo de uso do processador.
ATENÇÃO: Neste caso, o que está sendo compartilhado é o TEMPO DE USO do processador e NÃO o processador em si. Cada tarefa utiliza 100% do processador.
Compartilhar recursos significa que diferentes usuários ou programas usam os recursos de forma concorrente. 
Como administrar recursos compartilhados?
Os recursos são limitados e, assim, o uso dos mesmos pelos diferentes programas ou usuários precisa ser controlado e administrado de forma a evitar possíveis conflitos ou uma alocação por tempo indeterminado de algum recurso.
Concorrência
É a capacidade de execução concorrente de tarefas permitindo um melhor aproveitamento de recursos.
Uma tarefa pode deixar a CPU por vontade própria, quando precisa aguardar por um recurso, ou por uma interrupção.
Em particular, uma interrupção de temporizador provoca a substituição da tarefa em execução criando uma alternância entre as tarefas.
ATENÇÃO: A alternância entre as tarefas pode dar a impressão de execução simultânea de tarefas, mas não é o que ocorre.
Aula 2: Processos
Aula 3: Threads
Threads são fluxos de execução distintos dentro de um mesmo processo, um executável.
Atualmente, uma thread é considerada a unidade de execução de um sistema ao invés do processo como um todo. 
Um processo pode ter uma ou mais threads. Veja o exemplo.
Um processo que contenha threads é composto pelo seu PCB (Process Control Block) e pelos blocos específicos para cada thread que contém uma estrutura de contexto de software e uma estrutura de contexto de hardware.
Cada thread possui contextos próprios de hardware e software, porém compartilham o mesmo espaço de endereçamento alocado ao processo.
Vamos entender melhor.
Pense em funções de um mesmo processo onde todas as funções são capazes, por exemplo, de ver e alterar o conteúdo de variáveis globais.
Vamos exemplificar com o seguinte trecho de programa:
Como a variável x é visível por todas as funções,
o valor final da variável x será 12. 
As funções enxergam a mesma área de memória.
Processo leve ou LWP.
A combinação entre os dois tipos de threads promove uma associação entre threads de usuário e de Kernel, porém a forma de associação depende do sistema operacional.
ATENÇÃO: Esta é a solução mais utilizada nos sistemas modernos. Pois o  uso combinado de threads de usuário e de Kernel permite melhor aproveitamento do tempo de CPU, possibilidade de paralelismo e facilidade de programação.
Vamos conhecer agora os modelos de associação entre threads de usuário e de Kernel.
Muitos para um:
• Gerenciamento da thread é feito no espaço do usuário; 
• Usadas em sistemas que não suportam threads;
• Uma thread bloqueada bloqueia todo o processo.
Um para um: 
• Cada thread de usuário é mapeada para uma Kernel thread;
• Criar uma user thread requer a criação de uma thread de Kernel;
• Algumas implementações restringem o número de threads suportada pelo sistema; 
• É utilizada pelo Windows e pelo Linux.
Muitos para muitos:
• Permite que várias threads de usuário sejam mapeadas para um número menor ou maior de threads de Kernel dinamicamente;
• Permite que o SO crie um número suficiente de threads de Kernel.
Aula 4: Comunicação entre processos
MOTIVAÇÃO
Processos e threads em sistemas multitarefa compartilham recursos. 
Aprendemos nas aulas anteriores que processos e threads não executam direto, ou seja, desde o inicio até ao fim. Durante o tempo de execução, sofrem interrupções e ficam bloqueados aguardando recursos.
Suponha que um Processo P1 está executando quando é interrompido pelo final da fatia de tempo.
Outro Processo P2 será selecionado para execução e poderá querer utilizar o mesmo recurso que estava sendo utilizado por P1. 
E agora?
Vamos entender o exemplo:
Podemos perceber neste exemplo muito simples que obtivemos 3 resultados diferentes em função da ordem em que os processos ocorrem.
Esse efeito é denominado CONDIÇÃO DE CORRIDA.
Caso 1
Resultado final:  A = 3  B = 3
Caso 2
Resultado final:  A = 4  B = 4
Caso 3
Resultado final:  A = 3  B = 4
Há condição de corrida quando existem recursos compartilhados entre duas ou mais threads ou entre dois ou mais processos sem as devidas precauções.  
Mais uma informação importante:
Sabe aqueles problemas de “erro intermitente” do sistema operacional? 
Não existe erro intermitente de software, já que não existe “mau contato” dentro de um programa.
Erros intermitentes são mesmo erros de programação que ocorrem em determinadas situações. 
Essas situações podem se repetir ou não com frequência. Com a repetição do contexto é impraticável, torna-se muito mais difícil localizar um erro de execução do programa.
Para que um mecanismo de exclusão mútua seja efetivo, deve garantir que:
• Somente um processo por vez possa executar uma região crítica.
• Um processo interrompido fora de uma região crítica não possa impedir que outro processo tenha acesso a essa região crítica.
• Não possa haver nem deadlock nem starvation.
• Quando não houver processo executando uma região crítica, qualquer processo que solicitar acesso deverá obtê-lo imediatamente.
• Um processo deve permanecer executando