Escolar Documentos
Profissional Documentos
Cultura Documentos
2020
TEMA:
Os sistemas mono programados eram capazes de executar um único programa de cada vez, e é
por isso nestes sistemas operacionais os recursos como processador, memória e dispositivos de
entrada e saída, eram usados de forma pouco eficiente, limitando o desempenho destas
arquitecturas. Isto porque muitos destes recursos permaneciam ociosos por longos períodos de
tempo.
Por exemplo, enquanto uma leitura em disco é realizada, o processador permanece ocioso. O
tempo de espera é longo uma vez que uma operação de entrada e saída é mais lenta do que um
cálculo realizado pelo processador.
Um outro exemplo, é o desperdício de memória principal uma vez que somente um programa
que não ocupe toda a memória, Neste caso existirá vários blocos de memória ociosos durante
toda a execução do programa.
1
Em sistemas multi programados isso não ocorre pois vários programas podem ser executados
pelo processador e compartilham a memória principal.
Quando o programa 1 termina sua execução o programa 2 é iniciado e leva 20 minutos sendo
executado enquanto o programa 3 aguarda sua vez. Finalmente o programa 3 inicia sua execução
após aguardar 25 minutos e completa seu processamento em dez minutos, totalizando 35 minutos
de processamento dos 3 programas. O tempo total de execução dos programas é grande devido
ao sequenciamento da execução dos programas. Em um sistema multiprogramado o ganho de
execução é grande pois os 3 programas são executados de forma concorrente, com o uso do
processador, memória e discos sendo compartilhados pelos 3 programas.
A utilização concorrente da UCP deve ser implementada de maneira que, quando um programa
perde o uso do processador e depois retorna para continuar o processamento seu estado deve ser
idêntico ao do momento em que foi interrompido. O programa deverá continuar sua execução
exactamente na instrução seguinte àquela em que havia sido interrompido. Para o usuário este
processo é transparente, ficando ao usuário a percepção de que o computador está totalmente
dedicado ao usuário e a mais nenhum outro processo.
Pois é exactamente este mecanismo de concorrência que permite o compartilhamento de recursos
pelos vários programas sendo executados pelo processador.
2
INTERRUPÇÕES E EXCEÇÕES
INTERRUPÇÃO
Uma interrupção é sempre gerada por algum evento externo ao programa, e, nesse caso,
independe da instrução que está sendo executada. Um exemplo de interrupção ocorre quando um
dispositivo de entrada e saída sinaliza ao processador que uma operação de entrada saída está
completa. Neste caso, o processador deve interromper o programa que está sendo executado para
tratar o termino da operação de entrada saída.
Ao final da execução de cada instrução, a unidade de controle verifica a ocorrência de algum tipo
de interrupção. Nesse caso, o programa em execução é interrompido e o controle desviado para
uma rotina responsável por tratar o evento ocorrido, chamada rotina de tratamento de
interrupção. Como existem vários tipos de interrupção, podem haver diferentes rotinas de
tratamento de interrupção.
Para que o programa interrompido possa retomar sua execução exactamente do ponto onde foi
interrompido, é necessário que, no momento da interrupção, sejam guardadas informações a
respeito da execução do programa. Estas informações são basicamente o conteúdo dos
3
registadores que deverão ter seus valores restaurados quando a execução do programa
interrompido for reiniciada.
4
O mecanismo de interrupção envolve, em seus passos, tanto o hardware quanto o software:
Para cada tipo de interrupção existe uma rotina de tratamento associada, para a qual o fluxo de
execução deve ser desviado. No momento em que a interrupção é gerada, o processador deve
determinar para qual rotina de tratamento de interrupção deve ser desviado o fluxo.
O primeiro método chamado Vector de Interrupções possui um vector com o endereço inicial
de cada rotina de tratamento de interrupção.
5
O segundo método utiliza um Registrador de Status que identifica o tipo de interrupção gerada.
Neste método existe uma única rotina de tratamento de interrupção que examina o registrador de
Status a fim de dar o tratamento adequado a interrupção gerada.
As interrupções são geradas por eventos assíncronos, que são externos à instrução do programa
corrente. Estes eventos não podem ser previstos e podem ocorrer inúmeras vezes, inclusive
podendo ocorrer durante a execução de uma rotina de tratamento de interrupção.
Neste caso, alguns processadores simplesmente ignoram a ocorrência de interrupção quando uma
rotina de tratamento de interrupção estiver sendo executada.
Outros processadores não permitem que as interrupções sejam desabilitadas fazendo com que
exista sempre um tratamento para cada interrupção. Para isso o processador necessita saber qual
a ordem de atendimento que deverá sequir para atender as interrupções. Para isso as interrupções
precisam possuir prioridade, de acordo com a importância de cada interrupção.
As Exceções
As exceções são parecidas com as interrupções, a principal diferença é o motivo pelo qual o
evento é gerado. A exceção é o resultado directo de uma instrução dentro do próprio programa,
como a divisão por zero ou a ocorrência de um erro de estouro de memória em uma operação
aritmética (overflow).
As exceções são portanto geradas por eventos síncronos dentro do próprio programa e portanto
tais eventos são previsíveis e podem ser tratados pelo programador que pode incluir tratamento
de exceção no programa para que o mesmo não seja interrompido.
6
O tratamento de exceção é similar ao tratamento de interrupções. Para cada exceção gerada
durante a execução de um programa a acção é interromper a execução do programa e invocar
uma rotina para o tratamento da exceção. Existe uma rotina de tratamento de exceção, para a
qual o fluxo de execução é desviado quando a exceção é lançada durante a execução do
programa e o programa é interrompido.
7
A evolução deste modelo foi permitir que após o inicio da operação de entrada saída o
processador ficasse livre para outras tarefas e em intervalos de tempo o sistema operacional
deveria testar o estado do periférico para saber se a operação de entrada saída tinha terminado.
Em sistemas com muitos periféricos, o processamento é interrompido toda hora para testar o
estado dos diversos periféricos.
O modo de entrada saída controlada por interrupção é muito mais eficiente pois libera o
processador para outras tarefas, principalmente, para executar instruções que é a função principal
do processador, ao invés de controlar a comunicação com os dispositivos de entrada saída,
ficando esta função para o sistema operacional.
BUFFERING
A técnica de buffering consiste no uso de uma área da memória principal denominada buffer que
serve para transferência de dados entre os dispositivos de entrada saída e a memória. Esta técnica
permite que uma operação de leitura seja transmitida primeiramente para o buffer, liberando
imediatamente o dispositivo de entrada para efectuar uma nova leitura. Neste caso, enquanto o
processador manipula o dado localizado no buffer, o dispositivo realiza outra operação de leitura
no mesmo instante. Este mesmo mecanismo é usado em operações de escrita de dados.
8
O buffering foi criado para minimizar o problema de velocidade entre o processador e os
dispositivos de entrada saída. O objectivo é manter, na maior parte do tempo, o processador e os
dispositivos de entrada saída ocupados.
A ideia é que o buffer possa armazenar vários registros ainda que nem todos estejam sendo
processados pelo processador. Assim o dispositivo de entrada lê vários registros e os coloca no
buffer antes que o processador manipule todos os registros. A ideia é tentar compatibilizar a
diferença entre o tempo em que o processador executa as instruções e o tempo em que o
dispositivo de entrada saída realiza as operações de leitura e gravação.
Figura:1.1
9
SPOOLING
A técnica de spooling foi pensada para aumentar o grau de concorrência e a eficiência dos
sistemas operacionais. Esta técnica utiliza uma área em disco como um grande buffer. Neste
caso, os dados são lidos ou gravados em disco enquanto programas são executados
concorrentemente.
Esta técnica está presente actualmente nos sistemas operacionais e é usada para gerenciar a fila
de impressão. No momento em que um arquivo é impresso o mesmo é gravado em disco, em um
arquivo de spool, e o programa que solicitou a impressão fica livre para outras actividades
podendo ser continuar sua execução sem ter que aguardar o término da impressão do arquivo, a
conclusão da operação de saída. Posteriormente, o sistema operacional envia o arquivo de spool
para uma fila de impressão onde será enviado para a impressora.
Figura:2
10
Reentrância
A reentrância permite que um programa em execução seja compartilhado por vários usuários
simultaneamente de forma a evitar que várias cópias do mesmo programa sejam carregadas na
memória principal para execução. Isto evita desperdício de espaço em memória e redundância de
processos no sistema operacional que são o mesmo programa.
A reentrância permite que apenas uma cópia do programa seja carregada na memória e o código
executável seja compartilhado por vários usuários onde cada usuário possui sua área de dados em
separado. Desta forma temos um uso mais eficiente da memória.
Este recurso é muito usado em programas usados por vários usuários tais como editores de texto,
compiladores, planilhas electrónicas.
11
GESTÃO DE PROCESSOS
Um sistema de computação quase sempre tem mais actividades a executar que o número de
processadores disponíveis. Assim, é necessário criar métodos para multiplexar os processadores
das máquinas entre as actividades presentes. Além disso, como as diferentes tarefas têm
necessidades distintas de processamento, e nem sempre a capacidade de processamento existente
é suficiente para atender a todos, estratégias precisam ser definidas para que cada tarefa receba
uma quantidade de processamento que atenda suas necessidades. Este módulo apresenta os
principais conceitos, estratégias e mecanismos empregados na gestão do processador e das
actividades em execução em um sistema de computação.
OBJETIVOS
12
processador entre as várias tarefas que requerem processamento. Por multiplexar entendemos
compartilhar o uso do processador entre as várias tarefas, de forma a atendê-las da melhor
maneira possível”.
O CONCEITO DE TAREFA
Tarefa é definida como sendo a execução de um fluxo sequencial de instruções, construído para
atender uma finalidade específica: realizar um cálculo complexo, a edição de um gráfico, a
formatação de um disco. Assim, a execução de uma sequência de instruções em linguagem de
máquina, normalmente gerada pela compilação de um programa escrito em uma linguagem
qualquer, é denominada “tarefa” ou “actividade” (do inglês task).
Fazendo uma analogia clássica, pode-se dizer que um programa é o equivalente de uma “receita
de torta” dentro de um livro de receitas (um directório) guardado em uma estante (um disco) na
cozinha (o computador). Essa receita de torta define os ingredientes necessários e o modo de
preparo da torta. Por sua vez, a acção de “executar” a receita, providenciando os ingredientes e
seguindo os passos definidos na receita, é a tarefa propriamente dita. A cada momento, a
cozinheira (o processador) está seguindo um passo da receita (posição da execução) e tem uma
certa disposição dos ingredientes e utensílios em uso (as variáveis internas da tarefa).
13
Assim como uma receita de torta pode definir várias actividades interdependentes para elaborar a
torta (preparar a massa, fazer o recheio, decorar, etc.), um programa também pode definir várias
sequências de execução interdependentes para atingir seus objectivos. Por exemplo, o programa
do navegador Web ilustrado na Figura define várias tarefas que uma janela de navegador deve
executar simultaneamente, para que o usuário possa navegar na Internet:
14
A GERÊNCIA DE TAREFAS
1. Sistemas monotarefa;
2. Sistemas multitarefa;
3. Sistemas de tempo compartilhado;
SISTEMAS MONOTAREFA
Os primeiros sistemas de computação, nos anos 40, executavam apenas uma tarefa de cada vez.
Nestes sistemas, cada programa binário era carregado do disco para a memória e executado até
sua conclusão. Os dados de entrada da tarefa eram carregados na memória junto à mesma e os
resultados obtidos no processamento eram descarregados de volta no disco após a conclusão da
tarefa. Todas as operações de transferência de código e dados entre o disco e a memória eram
coordenados por um operador humano. Esses sistemas primitivos eram usados sobretudo para
aplicações de cálculo numérico, muitas vezes com fins militares. A Figura 2.2 a seguir ilustra um
sistema desse tipo.
15
Sistema monotarefa:1) carga do código na memória, 2) carga dos dados na memória, 3)
processamento, consumindo dados e produzindo resultados, 4) ao término da execução, a
descarga dos resultados no disco.
Nesse método de processamento de tarefas é possível delinear um diagrama de estados para cada
tarefa executada pelo sistema, que está representado na Figura abaixo.
Com a evolução do hardware, as tarefas de carga e descarga de código entre memória e disco,
coordenadas por um operador humano, passaram a se tornar críticas: mais tempo era perdido
nesses procedimentos manuais que no processamento da tarefa em si. Para resolver esse
problema foi construído um programa monitor, que era carregado na memória no início da
operação do sistema com a função de coordenar a execução dos demais programas. O programa
monitor executava continuamente os seguintes passos sobre uma fila de programas a executar,
armazenada no disco:
16
SISTEMAS MULTITAREFA
O uso do programa monitor agilizou o uso do processador, mas outros problemas persistiam.
Como a velocidade de processamento era muito maior que a velocidade de comunicação com os
dispositivos de entrada e saída1, o processador ficava ocioso durante os períodos de transferência
de informação entre disco e memória. Se a operação de entrada/saída envolvia fitas magnéticas,
o processador podia ficar vários minutos parado, esperando. O custo dos computadores era
elevado demais (e sua capacidade de processamento muito baixa) para permitir deixá-los ociosos
por tanto tempo.
A solução encontrada para resolver esse problema foi permitir ao processador suspender a
execução da tarefa que espera dados externos e passar a executar outra tarefa. Mais tarde, quando
os dados de que necessita estiverem disponíveis, a tarefa suspensa pode ser retomada no ponto
onde parou. Para tal, é necessário ter mais memória (para poder carregar mais de um programa
ao mesmo tempo) e definir procedimentos para suspender uma tarefa e retomá-la mais tarde. O
ato de retirar um recurso de uma tarefa (neste caso o recurso é o processador) é denominado
preempção. Sistemas que implementam esse conceito são chamados sistemas preemptivos.
A adoção da preempção levou a sistemas mais produtivos (e complexos), nos quais várias
tarefas podiam estar em andamento simultaneamente: uma estava activa e as demais suspensas,
esperando dados externos ou outras condições. Sistemas que suportavam essa funcionalidade
foram denominados monitores multitarefas. O diagrama de estados da Figura abaixo ilustra o
comportamento de uma tarefa em um sistema desse tipo:
17
SISTEMAS DE TEMPO COMPARTILHADO
18
Esse temporizador normalmente é programado para gerar interrupções em intervalos regulares (a
cada milissegundo, por exemplo) que são recebidas por um tratador de interrupção (interrupt
handler); as activações periódicas do tratador de interrupção são normalmente chamadas de ticks
do relógio. Quando uma tarefa recebe o processador, o núcleo ajusta um contador de ticks que
essa tarefa pode usar, ou seja, seu quantum é definido em número de ticks. A cada tick, o
contador é decrementado; quando ele chegar a zero, a tarefa perde o processador e volta à fila de
prontas. Essa dinâmica de execução está ilustrada na Figura abaixo.
19
CICLO DE VIDA DAS TAREFAS
Nova: A tarefa está sendo criada, i.e. seu código está sendo carregado em memória, junto com
as bibliotecas necessárias, e as estruturas de dados do núcleo estão sendo actualizadas para
permitir sua execução.
Pronta: A tarefa está em memória, pronta para executar (ou para continuar sua
execução),apenas aguardando a disponibilidade do processador. Todas as tarefas prontas são
organizadas em uma fila cuja ordem é determinada por algoritmos de escalonamento, que serão
estudados na Seção 2.5.
20
Executando→Pronta: esta transição ocorre quando se esgota a fatia de tempo destinada à
tarefa (ou seja, o fim do quantum); como nesse momento a tarefa não precisa de outros recursos
além do processador, ela volta à fila de tarefas prontas, para esperar novamente o processador.
Executando→Terminada: ocorre quando a tarefa encerra sua execução ou é abortada em
consequência de algum erro (acesso inválido à memória, instrução ilegal, divisão por zero,). Na
maioria dos sistemas a tarefa que deseja encerrar avisa o sistema operacional através de uma
chamada de sistema (no Linux é usada a chamada).
Terminada: Uma tarefa terminada é removida da memória e seus registros e estruturas de
controlo no núcleo são apagadas.
Executando→Suspensa: caso a tarefa em execução solicite acesso a um recurso não
disponível, como dados externos ou alguma sincronização, ela abandona o processador e fica
suspensa até o recurso ficar disponível.
Suspensa→Pronta: quando o recurso solicitado pela tarefa se torna disponível, ela pode voltar a
executar, portanto volta ao estado de pronta.
A estrutura do diagrama de ciclo de vida das tarefas pode variar de acordo com a interpretação
dos autores. Por exemplo, a forma apresentada neste texto condiz com a apresentada em
[Silberschatz et al., 2001] e outros autores. Por outro lado, o diagrama apresentado em
[Tanenbaum, 2003] divide o estado “suspenso” em dois subestados separados: “bloqueado”,
quando a tarefa aguarda a ocorrência de algum evento (tempo, entrada/saída, etc.) e “suspenso”,
para tarefas bloqueadas que foram movidas da memória RAM para a área de troca pelo
mecanismo de memória virtual (vide Seção 5.7).
Todavia, tal distinção de estados não faz mais sentido nos sistemas operacionais actuais baseados
em memória paginada, pois neles os processos podem executar mesmo estando somente
parcialmente carregados na memória.
21
IMPLEMENTAÇÃO DE TAREFAS
Conforme apresentado, uma tarefa é uma unidade básica de actividade dentro de um sistema.
Tarefas podem ser implementadas de várias formas, como processos, threads, jobs e transacções.
Nesta seção são descritos os problemas relacionados à implementação do conceito de tarefa em
um sistema operacional típico. São descritas as estruturas de dados necessárias para representar
uma tarefa e as operações necessárias para que o processador possa comutar de uma tarefa para
outra de forma eficiente e transparente.
Resumo:
O conjunto dos recursos alocados a uma tarefa para sua execução é denominado processo.
Historicamente, os conceitos de tarefa e processo se confundem, sobretudo porque os
sistemas operacionais mais antigos, até meados dos anos 80, somente suportavam uma tarefa
para cada processo (ou seja, uma actividade associada a cada contexto). Essa visão vem sendo
mantida por muitas referências até os dias de hoje. Por exemplo, os livros [Silberschatz et al.,
2001] e [Tanenbaum, 2003] ainda apresentam processos como equivalentes de tarefas. No
entanto, quase todos os sistemas operacionais contemporâneos suportam mais de uma tarefa
por processo, como é o caso do Linux, Windows e os UNIX mais recentes.
Os sistemas operacionais convencionais atuais associam por default uma tarefa a cada
processo, o que corresponde à execução de um programa sequencial (um único fluxo de
instruções dentro do processo). Caso se deseje associar mais tarefas ao mesmo contexto (para
construir o navegador Internet da Figura 2.1, por exemplo), cabe ao desenvolvedor escrever o
código necessário para tal. Por essa razão, muitos livros ainda usam de forma equivalente os
termos tarefa e processo, o que não corresponde mais à realidade.
Assim, hoje em dia o “processo” deve ser visto como uma “unidade de contexto”, ou seja,
um contêiner de recursos utilizados por uma ou mais tarefas para sua execução. Os processos
são isolados entre si pelos mecanismos de protecção providos pelo hardware (isolamento de
áreas de memória, níveis de operação e chamadas de sistema) e pela própria gerência de tarefas,
que atribui os recursos aos processos (e não às tarefas), impedindo que uma tarefa em execução
no processo para ascese um recurso atribuído ao processo pb. A Figura 2.8 ilustra o conceito de
processo, visto como um contêiner de recursos.
22
Figura 2.8: O processo visto como um contêiner de recursos.
23