![]()
Histórico dos sistemas operacionais
Classificações de Sistemas Operacionais
Tratamento de E/S em Sistemas
Multiprogramáveis
Processos e Estrutura de Sistemas
Operacionais
Exercícios Gerência de Processador
Sincronização na Comunicação entre processos
Outra visão de GERÊNCIA DE MEMÓRIA
Definicao de Sistema: Conjunto de
partes, funcionalmente independentes, que trabalham de maneira
harmônica objetivando um fim comum.
1-
Conjunto de partes – Não pressupõe uma seqüência;
2-
Funcionalmente independentes – Cada parte do sistema
executa uma função bem definida, diferente de qualquer outra parte;
3-
trabalham de maneira harmônica – Executam sua função da
melhor maneira possível em cooperação com as outras partes;
4-
fim comum - O objetivo
do programa.
Ø O hardware e o
sistema operacional
Sistema Operacional: É o programa (Software
(SW) ) de computador responsável por duas tarefas básicas:
-
Gerenciamento dos recursos de sistema
-
Interface com o usuário
Interface – É a forma do usuário interagir com o sistema
Gerência de recursos: (Elementos básicos do Sistema de Computação)
-
CPU: (Central Processing Unit) – Processador, Parte do sistema onde são
executadas as instruções.
-
MEMÓRIA: Real ou Primária – Armazenamento de dados.
-
PERIFÉRICOS: “O que sobrou” – Dispositivos de entrada e/ou saída de
dados.
Para entendimento do conceito de sistema
operacional, objeto desta disciplina, vamos tomar como exemplo uma configuração
de hardware (conjunto de componentes
eletrônicos interligados, composto de processador, memória principal, e
dispositivos de entrada e saída: discos magnéticos, monitor, impressora, etc.)
de um microcomputador PC. Basta abrir o caderno de informática de um jornal e
escolher uma configuração, dentre as tantas existentes com os mais diferentes
preços. Ex:
|
Componente |
Especificação (capacidade, marca, modelo) |
|
Placa-mãe (mainboard, motherboard) Processador (UCP) Clock Memória Principal (RAM) Memória Secundária (FD, HD, CD-ROM) Memória Cache Placa e monitor de vídeo Kit Multimídia Placa Fax/Modem Gabinete, teclado, mouse, estabilizador Outros: impressora, scanner, câmera digital, joystick |
ASUS P2L97
INTEL PENTIUM III
800MHz 64Mb Zip Drive 3 ½ “, 10 Gb e 52X 256Kb on-board DIAMOND AGP com 8Mb, SVGA colorido CREATIVE qq com acessórios US-Robotics de 56K Mini-torre, ABNT2 com 104 teclas, padrão MICROSOFT, qq de 1KVA Jato de tinta HP, de mesa com boa resolução, etc. |
Se numa próxima etapa, de posse de todos esses
componentes, um bom técnico conectá-los de maneira correta, será que esse microcomputador
funciona? Alguns ajustes no SETUP (programa de configuração/verificação gravado
em um componente da placa-mãe) se fazem necessários, mas certamente o
computador ligaria e mostraria toda sua configuração de hardware.
|
|
A pergunta agora seria um pouco mais específica: do jeito que foi feita
a montagem e configuração dos componentes, qual seria a utilidade desse
microcomputador? A resposta é simples, NENHUMA. Para que o usuário possa
utilizar seus programas em benefício de suas atividades profissionais (editores
de texto, planilhas eletrônicas, banco de dados, etc.), ou mesmo lazer (jogos),
é necessário que seja instalado um SOFTWARE INDISPENSÁVEL que tem como função
mais abrangente GERENCIAR todos os recursos (hardware e software) disponíveis no sistema de computação (no caso o microcomputador), chamado SISTEMA
OPERACIONAL. O sistema operacional é
software : um conjunto de rotinas que
são executadas pelo processador para facilitar
o acesso aos componentes de hardware (processador, memória,
dispositivos de E/S), e gerenciar o
uso do sistema de computação (hardware
e software).
Então, podemos definir o SISTEMA OPERACIONAL como :
conjunto de rotinas que
controlam a execução das aplicações de usuário cujas funções principais são :
- fazer a interface entre o
homem e o hardware da máquina; fazer a comunicação entre o usuário, o
computador e seus periféricos;
- gerenciar o compartilhamento dos recursos de hardware e software entre várias tarefas e/ou programas, de forma a fazer com que o acesso a esses recursos seja feito de forma segura e eficiente.
Algumas atividades que
envolvem o sistema operacional:
§
leitura de um disquete (acionar a cabeça de leitura e gravação,
posicionar trilha e setor, dados do disco para a memória)
§
quando um usuário solicita a execução de um programa, o sistema
operacional deve alocar espaço na memória para carregar e acessar o programa.
Ø A divisão do
hardware de um computador
Como já havia
sido comentado, os componentes do hardware
de um computador são divididos em três grupos/subsistemas básicos:
1. Unidade Central de Processamento (UCP ou
processador) – é o “cérebro” do computador, responsável pela execução de todos os
programas armazenados na memória principal. A UCP é composta de várias partes:
-
ULA (Unidade
Lógica e Aritmética) : realiza
as operações aritméticas (soma, subtração, divisão e multiplicação) e lógicas (
AND, OR , XOR ), necessárias à execução das instruções;
-
UC (Unidade de
Controle) : responsável pelo controle de
todo o hardware. ( ver, p.ex., leitura e escrita na memória principal );
-
Registradores :
áreas de memória para armazenamento de dados e instruções temporários (registradores de dados ) e informações
de controle (registradores de controle).
Registradores de controle importantes :
Program Counter (PC) ou Contador de Instruções (CI)
: contém o endereço da próxima instrução a ser executada.
Instruction
Register (IR) ou Registrador de Instruções (RI) : armazena a instrução que está sendo executada;
Stack Pointer (SP) ou Apontador de Pilha (AP)
: aponta para o endereço do topo da pilha.
A pilha é uma estrutura de dados na qual o ultimo
dado a chegar é o primeiro a sair. A pilha do processador contém vários
endereços de memória, com o objetivo de indicar à CPU o “caminho da
execução”. As instuções são armazenadas
na memória principal em endereços consecutivos. Se o fluxo dessas instruções
for contínuo, o PC irá incrementar de 1 a cada execução de uma instrução. Se
houver um desvio para uma rotina, o PC passará a conter o primeiro endereço de
memória da rotina. Ao término da rotina o fluxo deverá retornar para o mesmo
“lugar” ( endereço ) onde estava quando houve a chamada da rotina. É por isso
que este endereço tem que ficar guardado na pilha.
Faça um esquema,
contendo o conteúdo do PC e a pilha
para o caso de um programa em execução chamar a Rotina Calcula quando
está executando a instrução armazenada no endereço 02001110. As instruções da
Rotina Calcula estão armazenadas na memória dos endereços 0011002A até o endereço 00111000. A
instrução armazenada no endereço 00110040 faz uma chamada à Rotina Ordem. A
Rotina Ordem está armazenada nos endereços 00111000 até 0011147B. (acompanhar
em sala com o professor )
-
Clock :
dispositivo interno ao processador que gera pulsos elétricos síncronos
em um determinado intervalo de tempo (sinal de clock). A quantidade de vezes que este pulso se repete em um
segundo define a freqüência do clock, medida em Hertz. O sinal de clock é utilizado pela unidade de
controle para a execução das instruções.
Passos para executar um Programa
A CP aponta para a primeira instrução
![]()

Busca da instrução
![]()
![]()
Decodificação da instrução
![]()
Busca dos Operandos
![]()
Execução da instrução
![]()
N
Incrementa CP![]()
![]()
Fim do programa
S
Término
Vejamos alguns conceitos relacionados aos processadores de um computador:
1.a) Pipelining – a execução de uma instrução pelo processador é feita em vários passos :
- busca da instrução na memória principal
- decodificação da instrução
- execução efetiva da instrução
- escrita do resultado da execução da instrução ( em um registrador )
Depois disso o processador faz a busca da póxima instrução. O conjunto desses passos é chamado ciclo de instrução. Normalmente a busca, a decodificação e a escrita são feitas, cada uma, em um ciclo de clock. Entretanto, para a execução podem ser necessários mais de um ciclo, o que vai depender da arquitetura do processador e da própria instrução.
Os processadores com pipelining tem uma unidade para cada passo do ciclo de isntruções, sendo que tem mais de uma unidade para o passo de execução.
Pipelining: Esse processamento nos
passa a idéia de uma produção em série, onde cada tarefa é dividida em uma
seqüência de sub-tarefas executadas em diferentes estágios.

|
|
|
|
|
Vamos acompanhar a execução de um programa
com as isntruções número 1,2 , 3, 4, ..., 25. Suponha que não há nenhum desvio
de fluxo, ou seja, que estas instruções serão executadas efetivamente nesta
ordem. Preencha os campos abaixo com os números das instruções .
(Acompanhamento do professor )
|
CICLO no |
Busca |
Decodifica |
Executa 1 |
Executa 2 |
Escreve |
|
1 |
|
|
|
|
|
|
2 |
|
|
|
|
|
|
3 |
|
|
|
|
|
|
4 |
|
|
|
|
|
|
5 |
|
|
|
|
|
|
6 |
|
|
|
|
|
|
7 |
|
|
|
|
|
|
8 |
|
|
|
|
|
|
9 |
|
|
|
|
|
|
10 |
|
|
|
|
|
|
11 |
|
|
|
|
|
|
12 |
|
|
|
|
|
|
13 |
|
|
|
|
|
|
14 |
|
|
|
|
|
|
15 |
|
|
|
|
|
|
16 |
|
|
|
|
|
|
17 |
|
|
|
|
|
|
18 |
|
|
|
|
|
|
19 |
|
|
|
|
|
|
20 |
|
|
|
|
|
|
21 |
|
|
|
|
|
|
22 |
|
|
|
|
|
|
23 |
|
|
|
|
|
|
24 |
|
|
|
|
|
|
25 |
|
|
|
|
|
|
26 |
|
|
|
|
|
|
27 |
|
|
|
|
|
|
28 |
|
|
|
|
|
|
29 |
|
|
|
|
|
Em quantos ciclos estas instruções seriam
executadas sem o pipelining ? Quantos ciclos foram necessários à execução com o
pipelining? Comente estes resultados. O que aconteceria se no passo execução2
da instrução numero 10 fosse concluido que a próxima instrução as ser
executada é a instrução numero 2
(desvio de fluxo) ? Faça nova comparação entre a execução com o pipelining e
sem o mesmo. Comente.
1.b) Arquitetura CISC X Arquitetura RISC
Um processador com arquitetura CISC (Complex Instruction Set Computer) caracteriza-se por possuir instruções complexas que são interpretadas pelo nível de microporgramação, onde são convertidas em microinstruções. O número de registradores é pequeno e qualquer instrução pode referenciar a memória principal. Exemplos de processadores dessa arquitetura: VAX (DEC), 80x86 e o Pentium (INTEL), 68xxx (Motorola), além da série 360 e todos os mainframes (IBM).
Já um processador de arquitetura RISC (Reduced Instruction Set Computer) se caracteriza por possuir poucas instruções de máquina, em geral bastante simples, que são executadas diretamente pelo hardware, sem a necessidade da camada de interpretação. Na sua maioria, estas instruçòes nào acessam a memória principal, trabalhando principalmente com registradores que, neste tipo de processador, se apresentam em grande número. Estas características, além se ajudarem as instruções serem executadas em alta velocidade, facilitam a implementação de pipeline. Exemplos de processadores dessa arquitetura: Sparc (SUN), RS-6000 (IBM, PA-RISC (HP), Alpha AXP (DEC), Rx0000 (MIPS).
Em geral em um mesmo computador coexistem diferentes tipos de
memória com diferentes tipos de aplicações. Por exemplo é fundamental que as
transferências de informações internas ao processador central (CPU) sejam
realizadas no menor espaço de tempo possível (para não subutilizá-la). Neste
caso a velocidade de transferência é crítica, enquanto a quantidade de
informação a ser manipulada é mínima. Já em outros casos a capacidade de
armazenamento pode ser o fator crucial.
Essas diferentes
características desejáveis, aliadas ao custo (ver figura abaixo) torna inviável
a implementação de um computador com um único tipo de memória. Na realidade,
existem muitas memórias em um computador, que se interligam de forma
estruturada, constituindo um
sistema, que denominamos subsistema de memória.
Esse subsistema é projetado de modo que seus componentes sejam
organizados hierarquicamente, conforme a figura abaixo:
custo alto ; velocidade
alta
baixa capacidade registradores
![]()
![]()
![]()
![]()
memória cache
![]()
![]()
![]()
memória principal
custo baixo; velocidade baixa
![]()
capacidade elevada memória secundária
A forma piramidal com
base larga simbolizando uma elevada capacidade de armazenamento, tempo de
acesso (leitura/escrita) e o custo do tipo de memória em questão.
Os principais parâmetros
para análise das características de cada tipo de memória são: Tempo de acesso (leitura/escrita), Capacidade de armazenamento, Volatilidade, e Tecnologia de fabricação.
Tempo de acesso: Indica quanto tempo a memória gasta para colocar uma
informação disponível no barramento de dados após uma determinada posição ter
sido endereçada para leitura.
Capacidade de armazenamento: Refere-se a quantidade
máxima de informação que pode ser
guardada em uma memória, a unidade de medida mais comum é o “byte”,
embora possam também ser utilizadas outras unidades dependendo do tipo de
memória, por exemplo: setores (no caso de discos), “bits”(no caso de
registradores), etc. Dependendo do tamanho da memória, isto é, da sua
capacidade de armazenamento, indica-se o valor numérico total de elementos de
forma simplificada, através da inclusão das abreviações K(quilo),
M(mega),G(giga),T(tera), e etc.
Volatilidade: As memórias podem ser do tipo volátil ou não volátil.
Uma memória do tipo não volátil é aquela que retém a informação nela contida
mesmo quando sua fonte de alimentação é desligada, enquanto que a memória do
tipo volátil não é capaz de suportar sequer “quedas” de tensão.
Como exemplo de
memórias do tipo volátil podemos citar: registradores e as memórias de
semicondutores do tipo RAM (Random
Access Memory), como exemplo de memórias do tipo não volátil podemos ter:
memórias magnéticas e óticas como discos e fitas e, as memórias semicondutoras
do tipo ROM (Read Only Memory) e EPROM (Erasable Programable Read Only
memory) e EEPROM (Eletricaly
Erasable PROM).
Tecnologia de fabricação: Com a evolução dos computadores diversas
tecnologias vêm sendo empregadas na construção de memórias, algumas destas
tecnologias já estão obsoletas, enquanto outras ainda não se apresentam
disponíveis no mercado comercial, como é o caso da memória de bolha (buble
memory), como tecnologias mais conhecidas utilizadas podemos citar:
Memórias
semicondutoras, que são dispositivos fabricados com circuitos eletrônicos e baseados
em semicondutores, são rápidas e relativamente caras, e as Memórias Magnéticas, que são dispositivos eletromecânicos, nestes
dispositivos as informações são armazenadas sob forma de campos magnéticos,
eles possuem características magnéticas semelhantes as fitas cassete de uso
doméstico.
Em um sistema de
computação, o destino final do conteúdo de qualquer tipo de memória é o
processador(CPU). Isto é, o objetivo final de cada uma das memórias é armazenar
informações destinadas a serem, em algum momento utilizadas pela CPU. Ela é
responsável pela execução das instruções, pela manipulação dos dados e pela
produção dos resultados das operações.
As ações operativas da
CPU são realizadas na ALU(Unidade lógica e Aritmética) e na FPU(Unidade de
ponto flutuante). Entretanto, antes que as instruções sejam interpretadas e as
unidades da CPU sejam acionadas, o processador necessita “buscar” as instruções
onde elas estiverem armazenadas (memória cache ou principal) e armazená-la em
seu próprio interior, em um dispositivo de memória denominado registrador.
Em seguida a este
armazenamento da instrução, a CPU deverá, na maioria das vezes, buscar dados da
memória (cache, principal ou mesmo da memória secundária) para serem
manipulados pela ALU. Esses dados também necessitam ser armazenados em algum
local do processador até serem efetivamente utilizados. Os resultados de um
processamento também precisam (as vezes) ser armazenados temporariamente na
CPU, ou para serem novamente manipulados pela ALU por uma outra instrução, ou
para serem transferidos para uma memória externa ao processador.
Um registrador é,
portanto, o elemento superior da pirâmide de memória, por possuir maior
velocidade de transferência (menor tempo de acesso), menor capacidade de
armazenamento e maior custo.
Nos computadores mais
antigos os registradores eram diretamente ligados a memória principal, na
execução de instruções a CPU acessava diretamente a memória principal pelo
menos uma vez para buscá-las e transferi-las para um registrador interno ao
processador. Considerando-se que atualmente o ciclo de memória é bem mais
demorado que o período de tempo que a CPU gasta para realizar uma operação na
ALU, fica evidente que a duração da execução de um ciclo de instrução é
bastante afetada pela demora dos ciclos de memória.
Na tentativa de
melhorar o desempenho dos computadores, os projetistas de CPUs vêm obtendo
constantemente velocidades cada vez maiores na operação dessas unidades, o que
não acontece na mesma proporção com a memória principal. Assim atualmente a
diferença de velocidade entre a CPU e a
memória principal é muito grande.
Na busca pelo
minimização dessa diferença foi desenvolvida uma técnica que consiste na
inclusão de um dispositivo entre a CPU e a memória principal, denominado
memória cache, cuja função é acelerar a velocidade de transferência entre esses
dois dispositivos, e com isso melhorar o desempenho dos computadores.
Para isso, a memória
cache é fabricada com tecnologia semelhante aquela empregada na CPU, e consequentemente
apresenta tempos de acesso compatíveis, resultando numa considerável redução da
espera da CPU para receber dados e instruções da cache.
A principal
característica dos sistemas computacionais baseados na arquitetura “Von Neuman”
consiste no fato de se encarar um computador como uma máquina de “programa
armazenado”. O fato das instruções, uma após a outra, serem imediatamente
acessadas pela CPU é que garante o automatismo do sistema e aumenta a
velocidade de execução dos programas. A CPU pode acessar uma instrução
imediatamente após a outra porque ela se encontram armazenadas internamente ao
computador. Esta é a importância da memória.
A memória especificada
para armazenar os programas (e seus dados) a serem executados é a memória que
chamamos de memória principal ou real.
A memória principal é
a memória básica de um sistema de computação. É o dispositivo onde os programas
(e seus dados) que serão executados são armazenados para que a CPU vá
“buscando” instrução por instrução.
A memória principal é
o “depósito” de trabalho da CPU, isto é, a CPU e a memória principal trabalham
íntima e diretamente ligadas na execução dos programas. As instruções e os
dados dos programas ficam armazenados na memória principal e a CPU vai buscando-os
uma a um, à medida que a execução vai se desenrolando. Os programas são
organizados de modo que os comandos são descritos seqüencialmente e o
armazenamento das instruções se faz da mesma maneira.
A memória principal de
qualquer sistema computacional é organizada como o conjunto de N células
seqüencialmente dispostas a partir da célula de endereço 0 até a última, de
endereço (N-1), conforme mostrado na figura abaixo.
Memória principal
![]()
3E 4B
Conteúdos de
memória
![]()
Endereço 46F7
N
células
Endereço 46F8

![]()
![]()
![]()
M
Bits
Cada célula armazena um grupo de M bits, que representam a informação
propriamente dita.
As memórias de
semicondutores são dispositivos voláteis de estado sólido e possuem várias
características interessantes que as tornam extremamente vantajosas para
constituírem-se na base da memória principal, por exemplo:
- São memórias de
acesso aleatório(RAM- Random Acces Memory);
- Ocupam relativamente
pouco espaço;
- Possuem tempo de
acesso pequeno.
Essencialmente, o
espaço armazenado da memória principal é um grupo de N células, cada uma
podendo armazenar um grupo de M bits. Esta é a memória de trabalho da CPU e,
portanto, deve permitir o armazenamento de programas e dados (operação de
escrita) e também a leitura destas mesmas instruções e dados. Chama-se essa
característica de memória do tipo leitura e escrita. Esse tipo de memória tem
uma particularidade desvantajosa, que é o fato de ser volátil.
No entanto, todo
sistema precisa, para iniciar seu funcionamento regular, que um grupo de
instruções esteja permanentemente armazenado na memória principal de modo que,
ao ligarmos o computador, este programa inicie seu funcionamento
automaticamente o funcionamento do sistema. Essas instruções vêm junto com o
“hardware” e não devem sofrer um apagamento acidental se, inadvertidamente, um
programa do usuário tentar gravar por cima delas. Elas devem estar, portanto,
em tipo de RAM que só permita leitura por parte dos programas comuns. A
gravação(escrita) nelas deve ser realizada eventualmente e não por processos
comuns. Essas memórias chamam-se memória somente de leitura (ROM- Read Only
Memory).
Em geral é o tipo de memória
que tem maior capacidade de armazenamento que os outros tipos anteriormente
descritos, menor custo por “byte” armazenado e tempo de acesso superior.
Conhecida como memória secundária ou memória auxiliar, ou ainda memória de
massa, tem por objetivo garantir um armazenamento mais permanente aos programas
e estruturas de dados, razão pela qual deve possuir maior capacidade de
armazenamento que a memória principal.
A memória secundária
de um computador pode ser constituída por diferentes tipos de dispositivos,
alguns diretamente ligados ao sistema por acesso imediato, e outros que podem
ser conectados quando desejado.
A maior característica
desse tipo de memória é a sua não volatilidade.
2. Memória
Principal (RAM) e Memória Cache –
É a parte do computador onde programas (instruções) e dados são armazenados,
sendo composta por unidades de acesso chamadas células, sendo que:
-
A célula é a menor unidade endereçável. A maioria dos fabricantes de
computador padronizam a célula em 8bits de tamanho (byte). Bytes são agrupados
em palavras; um computador com palavra de 16bits tem 2bytes/palavra, enquanto
que um computador com palavra de 32bits tem 4bytes/palavra. O significado de
uma palavra é que a maioria das instruções operam em palavras inteiras, por
exemplo somando duas palavras. Então uma máquina de 16bits terá registradores
de 16bits e instruções que manipulam palavras de 16bits;
-
Todas as células em uma memória possuem o mesmo número de bits;
-
Cada célula da memória possui um endereço
único; a quantidade de bits do endereço, que não tem relação com a quantidade de bits da célula, está
relacionada ao número máximo de células endereçáveis.
Observe quantos números
binários diferentes você pode escrever com 2 bits, com 3 bits, com 4 bits, com 5 bits. Conclua que
com Nbits você pode escrever 2N números binários diferentes.
Lembrando que 1K=210,
1M=220 ( mega), 1G = 230 (giga), veja quantos bits são
necessários para endereçar uma memória de 1Kbyte, sendo cada célula de 1byte. Faça
o mesmo para uma memória de 64Kbytes, de 32Mbytes e 4Gbytes.
Depois do processador, que é o componente que executa as instruções dos programas, a memória é o componente mais disputado pelos programas, uma vez que os programas devem estar carregados na memória principal para ser “enxergado” e executado pelo processador. Esta memória é classificada como volátil, ou seja, não tem capacidade de preservar o seu conteúdo sem uma fonte de alimentação. Por esse motivo devemos sempre gravar nossos programas/arquivos quando estes foram alterados e permanecem na memória principal.
O tempo de acesso aos dados contidos na memória principal pode ser agilizado quando coloca-se no computador uma memória auxiliar, chamada memória cache. A memória cache é uma memória volátil de alta velocidade, localizada na placa-mãe do computador e atualmente também dentro do próprio processador. O tempo de acesso a um dado nela contido é muito menor que se estivesse na memória principal. Toda vez que o processador faz referência a uma célula da memória principal, ele verifica antes na memória cache. Se a cópia da célula já estiver na cache (acerto ou hit ) , não há necessidade do acesso à memória principal; do contrário (falha ou miss) , o acesso é obrigatório. Neste último caso, o processador, copia para a cache um bloco de células contíguas àquela referenciada. O tempo de transferência entre as memórias é pequeno, se comparado com o aumento do desempenho obtido com a utilização desse tipo de memória. Por que isto acontece ocorre o aumento de desempenho? Vejamos : se a cada vez que o processador procurar uma cópia de célula na cache, não encontrar ( falha ) terá que buscar um bloco de instruções na memória principal. Sem o uso da cache a busca na memória principal é feita instrução por instrução. Conclui-se, portanto, que só será vantajoso o uso da cache se o número de acertos for muito maior que o número de falhas. E isso realmente ocorre !!! Ocorre porque na maioria dos casos, observa-se que um programa faz acessos consecutivos a endereços consecutivos da memória e, além disso, observa-se que na maioria dos casos um programa em execução passa grande parte do tempo utilizando o mesmo conjunto de instruções. À esta observação, importantíssima para grandes ganhos de performance, denomina-se PRINCÍPIO DA LOCALIDADE.
Cache
Objetivo - Simular a existência de uma memória de grande capacidade e
alta velocidade para a CPU.
Operação - Manter em uma memória de pequena capacidade e alta velocidade
cópias das posições que mais provavelmente serão acessadas na MP.
Tempo de acesso:
T = PA x TC + (1 - PA)
x TP
Onde:
PA = Probabilidade de acesso no cache (Hit Rate)
TC = Tempo de acesso
ao cache
TP = Tempo de acesso à MP.
Ex.:
PA = 90%
TC =
50 ms
TP = 300 ms
T = 0,9 x 50 + (1 - 0,9) x 300 = 75
OPERAÇÕES DE LEITURA DA MEMÓRIA CACHE
Obs.: A busca de um bloco inteiro (e não apenas de uma palavra)
objetiva minimizar a taxa de falhas nos próximos acessos (princípio da
localidade). O critério de seleção do bloco a ser substituído depende da
organização interna do cache.
Operações de escrita no cache
As estratégias são:
Write Back
Em caso de acerto no cache (hit) a palavra é alterada apenas no cache.
Em caso de falha (miss), a palavra é alterada na memória e no cache.
A MP só é utilizada quando o bloco que contém a palavra é substituído
no cache.
Maior velocidade nas operações de escrita.
A manutenção de caches em sistemas multiprocessados é complicado.
Write Through
Em caso de acerto (hit), a palavra é alterada no cache e na MP.
Em caso de falha (miss), 2 esquemas são possíveis:
As operações de escrita são mais lentas
A MP está sempre consistente e é mais fácil manter a consistência das
caches em sistemas multiprocessados.
ORGANIZAÇÃO INTERNA DO CACHE
- Mapeamento totalmente associativo:
Um bloco de palavras da MP pode ser armazenado em qualquer posição do
cache.
- Mapeamento Direto
Cada bloco de palavras da MP só pode ser mapeado em uma única posição
do cache cujo endereço é dado por: (número de blocos) módulo (tamanho do
cache).
- Mapeamento Associativo por Conjunto
A cada posição do cache pode ser associado um conjunto de blocos
(tipicamente 2 a 16) de palavras da MP.
CARACTERÍSTICAS DO MAPEAMENTO
- Totalmente Associativo:
- Direto
- Associativo por conjunto
TAMANHO DA MEMÓRIA CACHE
A escolha do tamanho do bloco na memória cache é uma decisão de
compromisso. Blocos grandes tendem a aumentar a taxa de acerto mas possuem os
seguintes incovenientes:
Obs.: O tamanho típico de um bloco de memória varia entre 16 e 256
bytes.
POLÍTICAS PARA SUBSTITUIÇÃO DE BLOCOS NA MEMÓRIA CACHE
(Não se aplica ao mapeamento direto pois não se tem escolha onde alocar
o dado)
Os esquemas de mapeamento totalmente associativo ou associativo por
conjunto exige uma política de substituição de blocos exigem uma política de
substituição de blocos na memória cache.
Algumas dessas políticas são:
ABORDAGENS PARA MELHORAR O DESEMPENHO DA CACHE
Obs: Blocos são como páginas. Só se pega na MP bloco a bloco, mesmo que
o primeiro bloco só contenha metade da informação que você deseja.
Write Buffer é um cache separado só para escrita. Economiza tempo de
acesso.
3. Dispositivos de Entrada/Saída – São os
componentes que permitem a comunicação entre o computador e o mundo externo.
Podem ser divididos em duas categorias:
·
os que servem apenas de interface homem/máquina - através deles, o
processador e a memória principal podem comunicar-se com os usuários (teclado,
monitor, impressoras, scanner, caneta ótica, mouse). O desenvolvimento de
interfaces cada vez mais amigáveis permite que as pessoas sem conhecimento
específico sobre informática possam fazer uso de computadores;
·
aqueles destinados ao armazenamento de programas e dados (discos e
fitas magnéticas), chamados de memórias secundárias. Seu custo é relativamente
baixo, porém o tempo de acesso é maior quando comparado ao tempo de acesso à
memória principal ou mesmo à memória cache.
4. Barramento ( ou Bus ) - A memória principal, o processador e os dispositivos de E/S encontram-se interligados fisicamente através de linhas de comunicação denominadas barramentos. Um barramento pode ser visto como um conjunto de fios paralelos, cada um carregando um bit, onde trafegam informações. Cada tipo de barramento carrega um tipo de informação específica, a saber: barramento de dados, barramento de endereços e barramento de controle.
Ø LEITURA E ESCRITA NA MEMÓRIA PRINCIPAL :
Vamos acompanhar mais de perto o processo de
leitura na memória principal.
Seja, durante uma execução, em determinado
instante PC=010978EF. Isto significa que este é o endereço no qual está a
próxima instrução a ser executada. Quando termina a execução da instrução
corrente, o processador copia para o registrador MAR (Memory Registrer Address) o
valor do PC e a seguir incrementa o PC. Depois, a unidade de controle (UC)
coloca no barramento de controle o código em bits informando que será feita uma
leitura; e coloca no barramento de endereços o conteúdo do registrador MAR. A
UC dá o sinal para a leitura. A leitura na memória principal é feita e o
conteúdo da célula é colocado no barramento de dados. No processador o conteúdo
do barramento de dados é copiado para o registrador MBR (Memory Buffer Register).
Explicite
os passos para ESCRITA na MEMÓRIA PRINCIPAL.
Conceitos de software
O hardware sozinho
não tem utilidade, tornando-se necessária a existência de um conjunto de
programas relacionado mais diretamente com os serviços do sistema operacional,
possibilitando inclusive a criação de aplicativos pelos usuários
desenvolvedores de sistemas (programadores). Utilizaremos o termo utilitário
para referenciar o software mais ligado ao sistema operacional; e o termo aplicativo ou aplicação para os programas desenvolvidos pelo usuário. Isto e
feito atraves de linguagens de programacao.
Linguagem de Programação:
Conjunto limitado de instruções a serem executadas em um determinado computador. A linguagem de programação se divide em 3 níveis:
1º- Linguagem de alto nível – a linguagem que o usuário final (na
maioria das vezes o programador) entende com certa facilidade. Ex.: VB, C,
Delphi, Cobol, Pascal, ...
2º- Linguagem de médio nível ou linguagem de montagem – Conjunto limitado de instruções que são executados por um determinado processador. Ex.: Assembly do processador.
3º- Linguagem de baixo nível ou linguagem de máquina – Nos computadores
digitais são seqüências de 0 e 1 (binárias).
Preparação
para a execução de um programa:
![]()
![]()
![]()
Compilador
![]()
![]()
Arquivo Assembly
![]()
![]()
Montador
![]()
![]()
Arquivo Objeto ( L. Máquina)
![]()
![]()
Ligador
![]()

![]()
![]()
Carregador
![]()
![]()
Programa
Executável na Memória
Tradutor , Montador e
Compilador
Na época do surgimento dos primeiros computadores
digitais (1945 a 1955), não havia a idéia de sistema operacional. O programador
tinha que saber o funcionamento do hardware para trabalhar com a máquina. Por
exemplo, um programa era escrito em linguagem de máquina ( utilizando as
instruções que o processador “conhece” ) e já endereçado às posições de memória
que iria ocupar. Ocorreu que com o passar do tempo, mesmo depois do surgimento dos sistemas operacionais, com o
objetivo de fazer a interface entre o usuário e a máquina, algumas máquinas de
uso específico ainda utilizavam esta programação escrita em binário ou
hexadecimal.
A linguagem de programação Assembly é uma linguagem de montagem porque as suas
instruções estão ligadas diretamente às instruções do processador ==> ou
seja, o Assembly está, então, ligado diretamente à arquitetura do processador. O software que faz a tradução das instruções em Assembly ( código-fonte
) para as instruções da máquina é
chamado Assembler, e é dito MONTADOR, por ser o TRADUTOR de uma linguagem de montagem
para a linguagem de máquina.
Outras linguagens de programação, chamadas de alto
nível, não tem uma relação tão direta com a linguagem de máquina. Para
dar o primeiro passo da transformação das instruções em alto nível ( código-fonte)
para a linguagem de máquina, é preciso usar um tradutor também, que neste caso
( linguagens de alto-nível ) é chamado de COMPILADOR
.
O código gerado pelo tradutor é denominado código
objeto, que, apesar de estar em código de máquina, ainda não é
executável ( ou seja, ainda não está pronto para execução ). Então o tradutor
gera um código-objeto a partir de um código-fonte. Se o código-fonte estiver
escrito em linguagem de montagem ( Assembly ) o tradutor é chamado montador; se
estiver escrito em linguagem de alto nível ( Fortran, C, C++, Cobol,
Pascal, etc.) o tradutor é chamado de compilador. Os nomes dos compiladores são
os mesmos da linguagem correspondente ( compilador C, compilador Pascal, etc. )
Complete os quadrinhos abaixo com os nomes
corretos, baseados na explicação anterior :



![]()
Código
Fonte Código Objeto

![]()
![]()
![]()
Linguagem
de Montagem Código Objeto
![]()
![]()
![]()
![]()
Linguagem de
Alto Nível Código Objeto
Linker
Também chamado de linkage editor (editor de ligação) ou linkeditor, é o utilitário responsável por gerar a partir de um ou
mais módulos objeto, um único programa executável. Suas funções básicas são
resolver todas as referências simbólicas existentes entre os módulos e reservar
memória para a execução do programa.
As referências simbólicas são resolvidas pelo linker através de pesquisa
em bibliotecas do sistema ou do próprio usuário, que são arquivos que contêm
diversos módulos objeto e/ou definições de símbolos.
Já a operação de reserva de memória para execução do programa é conhecida como relocação. Em sistemas operacionais mais antigos, a relocação era realizada uma única vez, quando todos os endereços simbólicos eram traduzidos para endereços físicos fixos e o programa executável gerado somente podia ser carregado em uma determinada região da memória (código absoluto). Porém, em sistemas multiprogramáveis esse tipo de relocação era inviável. A solução é permitir que o programa seja carregado em regiões diferentes toda vez que for trazido para a memória principal (código relocável), sendo este tipo de relocação realizado por outro utilitário denominado loader.
Loader
Também chamado de carregador, é o utilitário que carrega/leva o programa para a memória principal para que este seja então executado. Como pudemos constatar anteriormente, o procedimento de carga varia com o código gerado pelo linker, que em função disso é classificado como sendo do tipo absoluto ou relocável.
Interpretador
Imagine um tradutor que não gere código objeto e que a partir de um programa em código fonte, escrito em linguagem de alto nível, traduza cada instrução e a execute em seguida. Esse software é denominado interpretador e sua maior desvantagem, como podemos perceber, é o tempo gasto na tradução das instruções de um programa toda vez que este for executado, já que não existe a geração de código executável. Algumas linguagens tipicamente interpretadas: Basic, APL e dBase.
Depurador
Todos sabemos que os programadores podem cometer erros de lógica no desenvolvimento de programas. O depurador (debugger) permite ao usuário controlar toda a execução de um programa a fim de depurá-lo/torná-lo puro/detectar erros, através de alguns recursos:
· Acompanhamento da execução instrução por instrução;
· Monitoramento e alteração do conteúdo das variáveis (watchpoint);
· Implementação de pontos de parada no decorrer da execução do programa (breakpoint);
Linguagem de controle ou de
comando
É a forma mais direta de um usuário se comunicar com o sistema operacional, possibilitando ao usuário acesso a rotinas específicas do sistema. Os comandos quando digitados pelo usuário são interpretados por um programa denominado interpretador de comandos ou shell, que verifica a sintaxe do comando, envia mensagens de erro e faz chamadas na rotinas do sistema.
A evolução de tais linguagens originam as interfaces gráficas e no futuro, com a introdução das linguagens naturais, os sistemas passarão a reconhecer também comandos falados.
Linguagem de máquina
É a linguagem de programação que o processador realmente consegue entender. Cada processador possui um conjunto único de instruções de máquina definido pelo fabricante, que especifica detalhes, como registradores, modos de endereçamento e tipos de dados. O programa nessa linguagem é totalmente codificado em formato binário.
Em
Resumo:
Existe um conjunto de programas que permitem ao usuário gerar outros
programas, que podem ser:
-
Interpretadores: (Arquivo Fonte – Arquivo Objeto)
-
Compiladores: (Arq. Fonte – Programa Executável)
Ambos utilizam linguagens próprias para interfacear o programador das
instruções de máquina.
Uma grande diferença entre compiladores e interpretadores é que o
último, para ter seu programa executando, é necessário que tenhamos um outro
programa(interpretador) rodando para executá-lo passo a passo.
Já programas compilados não necessitam de mais nada para executar.
Ø Máquina de Níveis
Nos primeiros computadores, a programação era realizada em painéis, através de fios, exigindo grande conhecimento do hardware. Depois surgiu o sistema operacional, tornando a interação entre usuário e computador mais simples e confiável. O programador afasta-se cada vez mais da complexidade do hardware, deixando-a por conta do sistema operacional. Podemos então, considerar o computador como um conjunto hierárquico de níveis ou camadas, onde inicialmente existem dois níveis: o nível o (hardware) e o nível 1 (sistema operacional).
Um computador não possui apenas dois níveis, e sim tantos níveis quanto forem necessários para adequar o usuário às suas diversas aplicações. Com a evolução das arquiteturas de computadores e das linguagens de programação, atualmente a maioria dos computadores possui a estrutura mostrada na figura :
|
Aplicativos |
|
Utilitários |
|
Sistema Operacional |
|
Linguagem de Máquina |
|
Microprogramação |
|
Dispositivos Físicos |
Identifique na figura acima os níveis que
se referem a software e os que se referem ao hardware.
De forma generica o modelo de Máquina de Níveis é utilizado no sistema de computação com a seguinte visão:
·
A camada, ou nível, N faz uma chamada à camada de nível N-1 que,
posteriormente, retornará um ou mais resultados à camada de nível N.
![]()
![]()
![]()
P R
NÍVEL 2
NÍVEL N
E E
R S
G P Máquina “Divisão
e Conquista” – Um pedido complexo vai
NÍVEL 2
NÍVEL N
U O de
Nível sendo quebrado em
pedidos mais simples a cada nível.
Dispositívos de E/S Controlados
de E/S
N S
Dispositívos de E/S Controlados
de E/S
T T
A A
![]()
1001001010101 -
Binário
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
-
Corrente
Faremos um breve resumo da história dos sistemas operacionais com objetivo ilustrativo, apenas para termos uma idéia da ordem cronológica de fatos importantes. A evolução do software dos computadores, especialmente os sistemas operacionais, está relacionada ao desenvolvimento de equipamentos cada vez mais velozes, menores no tamanho e com custo cada vez menor, e à necessidade de aproveitamento e controle desses recursos.
Primeira fase (1945-1955)
·
Computadores baseados em válvulas (ENIAC, criado para fins militares de
cálculos balísticos, com 18 mil válvulas, 30 toneladas, consumo de cerca de
140.000 watts; EDVAC, utilizado por universidades e também órgãos militares;
UNIVAC I, criado para auxiliar no censo americano de 1950, aplicação
comercial);
·
Ausência de sistema operacional: programação feita por painéis, através
de fios, sem uso de linguagens de programação.
Segunda fase (1956-1965)
·
Criação do transistor (maior velocidade e confiabilidade no
processamento, menor dissipação de energia) e das memórias magnéticas (acesso
mais rápido aos dados, maior capacidade de armazenamento e diminuição do
tamanho dos computadores);
·
Surgimento das primeiras linguagens de programação (Assembly e Fortran)
– os programas deixam de ser feitos diretamente no hardware;
·
Seqüenciamento da execução dos programas, sem intervenção do operador,
conhecido como processamento batch (em
lote);
·
Importantes avanços com a linha de computadores 7094 da IBM
Terceira fase (1966-1980)
·
Diminuição do tamanho e dos custos de aquisição do hardware com a criação dos circuitos integrados (CIs) e,
posteriormente, dos microprocessadores – lançamento da série 360 de
computadores da IBM e da linha PDP-8 da DEC;
·
Evolução dos processadores de E/S, possibilitando a utilização da
técnica de compartilhamento da memória e do processador denominada
multiprogramação;
·
Substituição das fitas por discos magnéticos, possibilitando a
alteração na ordem de submissão dos programas em lote (spooling);
·
Surgimento em 1969 do sistema operacional UNIX.
Quarta fase (1981-1990)
·
Miniaturização e barateamento dos computadores através da integração
cada vez maior dos componentes;
·
Surgimento dos microcomputadores pessoais (PCs) e do sistema
operacional DOS (Disk Operating System);
·
Sistemas multiusuário e multitarefa, permitindo a execução de diversas
tarefas de forma concorrente;
·
Equipamentos com múltiplos processadores, processadores vetoriais e
diversas técnicas de paralelismo em diferente níveis (multiprocessamento);
·
As redes de computadores se difundiram por todo mundo – software de
redes intimamente relacionados ao sistema operacional e surgimento dos sistemas
operacionais de rede.
Quinta fase (1991- )
·
Grandes avanços de hardware (microeletônica),
software e telecomunicações – processadores
e memórias cada vez menores e mais baratos;
·
Processamento distribuído em sistemas operacionais;
·
Novas interfaces
homem/máquina – linguagens naturais, sons e imagens;
·
Sistemas multimídia, bancos de dados distribuídos e inteligência
artificial.
Antes
de apresentar a classificação dos sistemas operacionais, vamos introduzir 4 conceitos relativos à medida de
eficiência de um SO.
Utilização da CPU
: esta medida é
feita em porcentagem. Por exemplo : durante 80 ms o processador trabalhou num
total de 60 ms. Qual foi a porcentagem de utilização
do processador neste caso ? Na construção do projeto do SO o objetivo deve ser
no sentido de maximizar ou minimizar a utilização do processador ? Por que ?
Tempo de
turnaround : tempo total do programa ou tarefa desde a sua admissão/criação até o
seu término.
Qual deve ser o objetivo do SO em relação ao tempo de turnaround ?
Tempo de resposta
: Tempo decorrido entre o envio de um pedido ao SO e o início da
resposta. Cite um exemplo de pedido ao SO.
Normalmente, qual a ordem de grandeza do tempo de resposta para este pedido ( s, ms, ns ? )
Throughput : É o número de
tarefas e/ou programas executados em
algum intervalo de tempo. No laboratório faremos a
medida de throughput.
Um
Sistema Operacional pode ser classificado quanto a quantidade de:
1-
Usuários: Quantos
usuários estão utilizando o sistema em um determinado momento. Pode ser Mono-usuário
(DOS, Windows) ou Multi-usuário (VMS, Unix)
2-
Programas
Utilizados: Quantos programas estão utilizando o sistema em um determinado
momento. Pode ser Mono-programado – executa cada programa do início ao fim sem
sofrer perda de controle da CPU; ou Multi-programado – multi-task – executa
vários programas, sofrendo interrupções.
3-
Processadores: Número de
|processadores que o sistema consegue trabalhar. Pode ser Mono-processador ou
Multi-processador.
O diagrama abaixo ilustra os vários tipos de sistemas operacionais de acordo com a configuração do hardware.
![]()
Sistemas
Operacionais

Quanto ao
Numero de Tarefas Simultaneas Quanto aos Processadores


Monoprogramaveis Multiprogramaveis Fracamente Fortemente
ou Monotarefa ou
Multitarefa Acoplado Acoplado
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
![]()
Batch
Tempo Compartilhado Tempo Real SOR Distribuido Simetrico Assimetrico
2.1 Sistemas
Monoprogramáveis ou Monotarefas
Neste tipo de sistema operacional, todos
os recursos do sistema de computação estão dedicados exclusivamente a um programa ou tarefa, de cada vez. I
Sejam três
programas PROG1, PROG2 e PROG3 a serem executados. Ocorre o seguinte :
PROG1 é
admitido na máquina. O SO reserva espaço na memória para o código e
dados referentes ao programa. O SO aloca o programa na memória principal. O SO
dá o comando para o processador iniciar a execução. A execução prossegue. Se
determinada instrução fizer um pedido de leitura em disco, o SO dará o comando
para a leitura. O acesso a disco é
feito. Como um acesso a disco é muito
lento em relação à velocidade de cálculo no processador ( veja cálculos nos
exercícios ) , o processador ficará ocioso, durante o acesso ao disco. A
execução prossegue. Se outros pedidos de E/S forem feitos, novamente o
processador ficará ocioso durante o acesso aos dispositivos E/S. Mesmo que
sobre espaço na memória principal, o mesmo não será preenchido, permanecendo
nesta somente as rotinas do SO, o código de PROG1 e os dados de PROG até o
final da execução do mesmo. Somente ao final de todo o PROG1, o PROG2 poderá
será admitido. Somente após o término de PROG2, o PROG3 poderá ser admitido.
Qual a desvantagem imediata que você percebe num sistema operacional
monotarefa ?
Para que tipo de ambiente, este SO
pode ser utilizado sem que esta desvantagem seja importante ?
Se a velocidade de acesso aos dispositivos de entrada e saída fosse
da ordem da velocidade de execução esta desvantagem continuaria ocorrendo? Por
que ?
Esses sistemas podem ser MULTIUSUÁRIO ?
Você acha que o projeto e código deste tipo de SO é complexo ? Por
que ?
2.2 Sistemas Operacionais Multiprogramáveis ou
Multitarefa
Ao
contrário dos monotarefa este tipo de SO compartilha os recursos do sistema de
computação (quais são mesmo estes recursos ? ) entre vários programas e/ou tarefas.
O
compartilhamento da memória principal
é feito através da utilização da memória simultaneamente
por vários programas e/ou tarefas, ou seja, em determinado instante temos o
código e dados de vários programas e /ou tarefas alocados na memória principal.
Isso ocorre no monotarefa ? Qual é o tipo de segurança que o SO deve oferecer no que se
refere a este item ?
O
compartilhamento do processador, que é único, é feito de forma que vários
programas e/ou tarefas podem ter a sua execução iniciada e mediante uma série
de razões, para dar a vez a outro programa e/ou tarefa, mesmo antes de terem
terminado. Ou seja, o compartilhamento do
processador é feito de forma que temos em determinado instante um e somente um programa ou tarefa em
execução. Ou seja o compartilhamento do processador é feito de forma concorrente e não simultânea. Por que ?
O
compartilhamento dos dispositivos E/S é feito de forma que dois dispositivos
diferentes podem estar recebendo/enviando dados relativos a tarefas e/ou
programas diferentes, simultaneamente.
E
além disso, podemos ter um acesso a disco relativo a um programa e/ou tarefa
ocorrendo simultaneamente a uma
execução, por exemplo.
Cite outros acessos simultâneos num
multitarefa.
Quantas instruções podem ser executadas
durante um acesso a disco ? Trabalhe com ordens de grandeza, ou seja, potências
de 10.
Faça uma comparação monotarefa x multitarefa, no que se refere à complexidade do
projeto e código do SO.
Faça uma comparação monotarefa x multitarefa
no que se refere à segurança que o SO deve oferecer.
Faça uma comparação monotarefa x multitarefa
no que se refere à eficiência que o SO deve apresentar no compartilhamento dos
recursos entre os vários programas e/ou tarefas.
SISTEMAS
OPERACIONAIS MULTITAREFA
Apresentamos abaixo os três
tipos de multitarefa. Vamos observar ao longo do nosso estudo que primeiramente
seremos apresentados a uma classificação, para depois concluir que os sistemas
atuais, na verdade, implementam um híbrido
de um ou mais dos tipos estudados.
BATCH
: Inicialmente os computadores
de grande porte, praticamente só processavam. Os dados a serem processados eram
lidos numa máquina e gravados em uma fita magnética. Esta fita era transportada
por um operador até o computador que fazia o procesamento. Após o processamento
os resultados eram escritos numa fita magnética e levados até uma outra máquina
que procedia a impressão. O primeiro tipo de multitarefa fazia com que vários programas compartilhassem o recurso fita magnética entre vários programas (chamados na época jobs).
Esta foi a primeira situação em que surgiu o termo batch. Vários programas e seus dados eram lidos e passados para a fita. O operador levava a fita até o
computador, que processava todos os programas, um por um e ia escrevendo
os resultados na fita. Depois, o operador levava a fita até o canal de saída (
impressão em papel, perfuração em fita de papel ). Numa segunda fase, já com os
dispositivos de E/S ligados diretamente ao computador, o processamento batch era feito com vários programas
sendo lidos diretamente pelo computador. Mas ainda executados um por um. Atualmente
chamamos de batch as tarefas que são
deixadas para execução de baixa prioridade, sem a interferência do usuário.
TEMPO
COMPARTILHADO OU TIMESHARING : Os
sitemas de tempo compartilhado tem como principal característica a interação com o usuário. Nestes
sistemas todos os recursos da máquina são compartilhados por várias
tarefas/programas, dando a impressão que os processamentos são simultâneos.
Para atingir este objetivo, há a implementação de uma fatia de tempo, para o
uso do processador. É este tipo de
sistema operacional que é implementado nos computadores de grande porte, no
qual há vários terminais ligados a um processador. Os usuários que estão
on-line nos terminais trabalham como se o computador estivesse dedicado somente
a cada um deles. Então esta sistema é multiusuário.
Além disso, cada usuário pode ter ativas várias tarefas. O sistema operacional
trabalha dando a impressão de que todos os recursos da máquina estão
disponíveis para cada uma das tarefas.
Você conhece
algum sistema multitarefa ? Qual ?
Para este tipo de sistema
operacional o tempo de resposta é
extremamente importante, por causa da interação com o usuário : o usuário não
pode fazer um pedido ao SO ( por exemplo abrir um aplicativo ) e esperar um
tempo absurdo pela resposta, porque há outras tarefas/ programas/usuários
ativos. Se isto ocorrer não será cumprido o objetivo de fazer parecer a um
usuário/programa/tarefa que os recursos da máquina estão dedicados a estes.
TEMPO
REAL : Para esse tipo de sistema operacional, o mais importante é a prioridade
e não o tempo de resposta. É utilizado em situações como navegação aérea ou
marítima, controle de caldeiras de petróleo, nas quais os pedidos estão sendo
processados e as respostas devem ocorrer em tempos pré-determinados. Se um programa
de prioridade maior do que o que está
sendo executado for admitido, o primeiro deverá dar lugar ao segundo. (
Exemplo, no caso de navegação marítima, radar detecta um pedra no rumo atual ;
deve entrar o programa de mudança de rumo )
SISTEMAS
OPERACIONAIS PARA AMBIENTES COM MÚLTIPLOS PROCESSADORES
Conceitos importantes
relativos a ambientes com múltiplos processadores :
Vamos definir os seguintes
conceitos agora e empregá-los na explicação sobre sistemas com múltiplos
processadores.
escalabilidade
: refere-se
ao aumento da capacidade de computação. Ou seja, uma tarefa é escalável, se
puder ser dividida em várias outras tarefas que podem ser executadas
independentemente. Suponha que precisamos fazer um vasto processamento sobre
todas as notas da vida acadêmica dos alunos desta turma.
As notas de
um aluno irão influenciar nos cálculos de outro aluno ?
Então podemos
dividir a tarefa em várias outras independentes ? Então este procedimento é
escalável ?
Que tipo de
máquina apresenta maior , uma com 5 processadores ou uma com 30
processadores ?
reconfiguração
: capacidade
do sistema poder continuar o processamento mesm se um dos processadores
falhar.
Como o sistema operacional pode tornar isso possível ?
balanceamento
: (de
carga ) : refere-se à divisão de tarefas entre os vários processadores. Se um
processador, num ambiente com 4 processadores, apresenta uma utilização de processador de 90%,
enquanto os outros no mesmo intervalo de tempo, apresentam utilização de processador de 5%, a carga de processamento não está
bem balanceada, ou seja, o sistema com múltiplos processadores está sendo usado
como um monoprocessador, praticamente.
a
) Ambientes com múltiplos processadores
FORTEMENTE ACOPLADOS
Os sistemas com múltiplos
processadores fortemente acoplados são aqueles em que há que vários
processadores dentro de uma mesma máquina, compartilhando
memória e dispositivos de E/S. Este ambiente é gerenciado por um só sistema
operacional.
Como são vários
processadores executando simultaneamente,
podemos ter várias tarefas/programas em execução simultaneamente.
Também é possível dividirmos
um programa em partes que podem ser executadas independentemente umas das
outras, utilizando uma linguagem de
programação paralela. Nesse caso teremos partes diferentes de um mesmo
programa sendo executadas simultaneamente
por vários processadores. Isto é chamado paralelismo
explícito. O contrário seria o paralelismo
implícito, situação na qual o sistema operacional e compiladores
verificariam as partes independentes do programa, direcionando-as para
diferentes processadores. Isto tem sido motivo de estudo na Ciência da
Computação.
Normalmente, estes sistemas
com vários processadores, são utilizados em processamentos que utilizam muito o
processador e fazem poucas requisições de E/S. A propósito chamamos de CPU-bound as aplicações que tem esta característica. Contrariamente,
chamamos de I/O-bound as aplicações
que fazem pouco processamento e muitas requisições de E/S.
SISTEMA
OPERACIONAL ASSIMÉTRICO : Na organização assimétrica
ou mestre/escravo (master/slave), somente UM PROCESSADOR
(mestre) EXECUTA AS ROTINAS DO SISTEMA OPERACIONAL.
O que
acontece se , com esta configuração, um processador escravo precisar fazer uma
leitura do teclado ?
E se forem
vários processadores, cada um executando uma aplicação I/O bound ?
Então, quais
são as vantagens da configuração assimétrica ?
E quais são
as desvantagens ?
SISTEMA
OPERACIONAL SIMÉTRICO : Nesta configuração TODOS OS PROCESSADORES EXECUTAM
as rotinas do SISTEMA OPERACIONAL.
Como fica a
situação do boot (inicialização) do sistema ?
O que
acontece se dois processadores fizerem acesso à mesma área de memória
simultaneamente ?
Quais seriam
as vantagens e desvantagens deste tipo de sistema operacional em relação ao
assimétrico ?
Outras questões :
Faça uma análise desses dois
tipos de sistemas operacionais em relação aos conceitos de escalabilidade,
reconfiguração e balanceamento de carga.
b )
Ambientes com múltiplos processadores FRACAMENTE ACOPLADOS
Possuem dois ou mais sistemas de computação interligados por
linha de comunicação. Observe que estamos tratando de dois ou mais sistemas
de computação, que inclui todo o hardware e software básico. Cada
sistema de computação, nesta configuração, terá, portanto, o seu processador
central, a sua memória principal, os seus disposistivos de E/S e o seu sistema
operacional, que irá gerenciar os seus próprios recursos. Observe, ainda, que
cada sistema de computação tem capacidade
de processamento própria.
Em uma rede, cada sistema de
computação independente pode ser chamado de nó, host ou estação.
SISTEMA
OPERACIONAL DE REDE : Cada nó é
totalmente independente dos outros, podendo possuir sistemas operacionais
diferentes. Cada nó compartilha os recursos com o restante da rede. Caso uma
das estações sofra algum problema, os demais continuarão em funcionamento. São
permitidos :
cópia remota de arquivos,
emulação de terminal, impressão remota, gerência remota e correio eletrônico.
O usuário on line na máquina número 1 da rede, por
exemplo, poderá buscar um arquivo do disco da máquina número 2. Para isso ele
indicará este direcionamento.
SISTEMA
OPERACIONAL DISTRIBUÍDO : Nesta configuração, normalmente, os sistemas operacionais
são os mesmos e há uma interligação maior entre os hosts do que no caso acima.
Uma aplicação está em execução na
máquina número 1 da rede, por exemplo, e precisa de um arquivo que está no
disco da máquina 2. Este arquivo será encontrado pelo sistema operacional e
essa busca será transparente ao usuário. Outro exemplo : se um usuário on
line na máquina número 1 enviar uma aplicação para execução e o seu
processador já estiver ocupado, o SO
irá verificar se há um outro processador livre em algum host da rede. Se houver
o SO enviará a aplicação para este host. Mas, isso será transparente ao
usuário. Uma vez escalonada para executar no processador de um determinado
host, a aplicação irá até o fim neste host.
Faça a
comparação do balanceamento de carga e reconfiguração entre os dois tipos de SO
acima.
Qual a
relação existente entre sistema fracamente acoplado distribuído e sistema
fortemente acoplado ?
Como vimos, os
sitemas multiprogramáveis ou multitarefa são capazes de compartilhar os
recursos de um sistema de computação, entre várias aplicações, apesar desses
sistemas possuírem apenas um processador central.
Neste capítulo
explicitaremos alguns detalhes das operações de E/S, que proporcionaram, cada
vez mais ao longo da evolução de hardware e software, melhor performance
multitarefa.
Nos sistemas mais
primitivos, a comunicação entre a UCP e os periféricos era controlada por um
conjunto de instruções especiais, chamadas instruções de entrada/saída. Estas
instruções eram executadas pela UCP e continham detalhes específicos de cada
periférico, como p.ex. trilhas e setores de um disco.
A implementação
de um disposistivo de hardware chamado controlador ou interface fez com que a
comunicação entre UCP e periféricos fosse feita através de tal
dispositivo. Com esta nova
implementação, surgiram duas maneiras de controle dos
periféricos, pela UCP :
1 - E/S
controlada por programa : nesta situação a UCP sincroniza com o controlador,
é iniciada a transferência de uma palavra, a UCP testa o controlador para saber
se terminou, senão inicia a transferência da próxima palavra. Neste caso, a UCP
fica presa à transferência de dados,
durante todo o tempo. Como a UCP executa uma instrução muito mais rápido do que
a realização de uma operação de E/S, isto significa que a UCP ficava presa e ociosa, aguardando o término da transferência. Chamamos esta "espera presa" de busy
wait ou seja espera ocupada.
2 - Polling : nesta situação a UCP faz o
teste para saber se a transferência terminou também, mas o faz de tempos em
tempos, ficando liberada, neste
intervalos para realização de outras tarefas. Estas outras tarefas podem ser
aplicações de usuário, mas antes destas, a UCP percorre todas as portas de E/S para verificar de já terminou alguma
transferência, ou se há alguma coisa para "entrar".
Não seria
melhor que a UCP fosse AVISADA do término de uma transferência ou de que há
algo para ser lido ?
SIM. A UCP
PASSOU A SOFRER UMA INTERRUPÇÃO .
E/S controladas por
Interrupção:
Ao invés do S.O. testar periodicamente o estado dos dispositivos, o
próprio dispositivo, através do seu controlador, interrompe a CPU quando
alterar o seu estado.
A CPU executa a operação e E/S, como já sabe que a resposta do
dispositivo vai demorar, o fluxo da instrução é desviado para outro processo.
Existe dois tipos de interrupção:
·
Exceção: (Interrupção
interna ou de programa) são geradas em decorrência a falhas de execução
(eventos síncronos) que podem ser previsíveis. Ex.: divisão por zero, overflow,
underflow.
·
Interrupção
externa: São causadas por sinais externos a CPU (evento assíncronos). Ocorrem
independentemente da execução do programa. Podendo ser:
·
Mascaráveis: Podem ter sua
aceitação desabilitada pela CPU;
·
Não-Mascaráveis: Devem ser sempre
atendidas e/ou tratadas.
Contr. de Interrupção Clock
O controlador de Interrupção sinaliza ao S.O. (CPU) qual dispositivo está
pronto. Cada periférico (disp. E/S) tem uma interrupção. Daí o S.O. irá
decidir, dentro de sua política, qual interrupção será tratada primeiro.
A interrupção
constitui-se no seguinte :
- a UCP está executando uma instrução de um programa
- a UCP sofre uma
interrupção
- a UCP salva
todos os seus registradores
- a UCP
identifica a origem da interrupção
- a UCP obtém o
endereço da rotina de tratamento desta interrupção, consultando o vetor
de interrupções
- a UCP executa
as instruções da rotina adequada
- ao terminar
este procedimento a UCP passará a executar algum conjunto de instruções,
conforme indicação do SO. Se for continuar algum procedimento anteriormente
interrompido, a UCP irá restaurar os registradores que foram guardados no
momento da interrupção.
Para que serve o vetor de interrupções
?
O vetor de
interrupções contém, para cada tipo de interrupção o endereço de memória da
rotina de tratamento daquela interrupção :
Vetor de Interrupções ( armazenado na memória
principal ) :
|
Tipo de interrupção |
Endereço da Rotina de Interrupção |
|
relógio |
0015002B |
|
teclado |
0015300E |
|
controlador de dico fixo |
00161117 |
|
controlador de disco flexível |
0016AE00 |
|
controlador de impressora |
0016B389 |
Parte da memória principal :
|
Endereço |
Conteúdo |
|
0015002B |
Rotina de
Tratamento da Interrupção do Relógio |
|
0015002C |
...................... |
|
|
. .
. |
|
0015300D |
Fim da Rotina
de Tratamento da Interrupção de Relógio |
|
0015300E |
Rotina de
Tratamento da Interrupção de Teclado |
|
0015300F |
....................... |
|
|
. .
. |
|
0016116 |
Fim da Rotina
de Tratamento da Interrupção de Teclado |
|
0016117 |
Rotina de Tratamento
da Interrupção de Conrolador de disco fixo |
|
0016118 |
....................... |
|
|
. .
. |
Acesso Direto à Memória
(DMA):
O DMA aloca as informações diretamente na memória então o controlador irá
avisar a CPU que o dispositivo está pronto.
O DMA é usado em
transferência de grupos de dados nos quais a CPU pode deixar de ser
sobrecarregada. Neste esquema, um volume de dados é transferido de/para memória
de/para o dispositivo de E/S, sem intervenção direta da CPU. Quem realiza a
transferência é o circuito de DMA. O controlador de DMA precisa saber o tamanho
em bytes da transferência, a região inicial da memória, o dispositivo alvo e o
sentido da transferência para realizá-la.
Técnica de Buffering:
Consiste na utilização de uma área de memória (volátil) para
transferência entre os periféricos e a CPU. Com isto reduzimos o
"GAP" de performance entre eles, porque a CPU poderá manipular os
dados neste "Buffer", evitando consumir o tempo da operação de E/S.
Ex.: Editores que não realizam as operações de E/S diretamente, no caso
de alterações em um arquivo, utilizam um buffer para tal.
No laboratório, faça uma lista dos números das interrupções e seus
dispositivos associados.
Em que ponto da evolução acima descrita, foi possível a multitarefa
? Por que ?
Em que situação a multitarefa ficou mais eficiente ? Por que ?
Qual o objetivo de salvar todos os registradores da UCP, após uma
interrupção ? E se isso fosse feito depois da identificação da origem da
interrupção ? Isso traria alguma vantagem ou desvantagem ?
O que a UCP busca na consulta do vetor de interrupções ? Para que ?
O que você acha
que acontece quando :
- dois
dispositivos tentam interromper o processador ao mesmo tempo ?
Parte I – Processos
Ø
Conceito de Processo
Num ambiente monotarefa
vimos que a CPU executa um programa seqüencialmente, utilizando os
recursos de hardware e software na ordem em que são solicitados
e aguardando o término da execução de um para começar o outro. Quando estudamos
os sistemas batch, vimos que a CPU
executava um job também
seqüencialmente, solicitando os recursos na ordem em que eram pedidos. Já no
ambiente multitarefa, entendemos que o que está executando no processador muda
constantemente. Isso ocorre para dar a impressão a cada usuário (no caso
multiusuário) ou a cada tarefa do
mesmo usuário (monousuário) que a máquina está a disposição de somente aquele usuário/tarefa.
Nós vimos que esses “pedaços” de programas ou tarefas que ora estavam sendo
executados pela CPU, ora estavam fazendo um acesso de E/S, ora estavam
aguardando para execução na CPU, etc. na verdade ficavam “disputando” os
recursos (CPU, E/S, memória) entre si. Isso nos leva ao conceito de um processo
à esses “pedaços”
de programas ou tarefas que estão fazendo acesso concorrente aos recursos do
sistema.
RESPONDA: 3.1) O
que ocorre quando um programa deixa a CPU, de forma que ele possa retornar no
mesmo ponto e nas mesmas condições que saiu ?
O estado atual do programa
na CPU tem que ser salvo para que o programa possa retornar e continuar sua
execução como se não tivesse sido interrompido. Isso inclui não só os
registradores (como já estudamos no mecanismo de interrupção) como também
outros detalhes como, por exemplo, quais eram os arquivos que estavam abertos.
Podemos dizer que este estado completo
do que estava em execução define
um ambiente de execução à é o PROCESSO. Ou seja, processo
é o ambiente onde se executa um programa, a estrutura responsável pela
manutenção de todas as informações necessárias a execução de um programa.
Ø
Materialização do Processo

|
Para poder definir o
ambiente completo de execução e assim materializar o conceito de processo, o
sistema operacional mantém uma estrutura de dados que contém os todos os
detalhes necessários para esta definição. Esta estrutura chama-se PCB (Process Control Block = BLOCO DE CONTROLE DO
PROCESSO). Alguns sistemas dão o nome de BLOCO DE CONTROLE DA TAREFA (task control block).
O conteúdo exato do PCB varia com o sistema operacional, mas basicamente contém dados como: ponteiro (uma forma de indicar algum outro processo), endereço de memória, nome do processo, tamanho, usuário que criou o processo, registradores (PC, SP, etc.), grupo de usuários que podem acessar o processo, prioridade, pilha, classe de escalonamento, lista de arquivos abertos, quando o processo foi iniciado, estado do processo, tempo acumulado de execução, etc.
É através de várias chamadas
de sistema (como será visto a seguir) que o sistema operacional
gerencia os processos. Todos esses elementos que definem o ambiente de execução,
o processo, podem ser classificados em três grandes grupos: contexto de
hardware, contexto de software e espaço de endereçamento.
RESPONDA: 3.2) Você acha que
a freqüente troca de contexto (troca de processos) na CPU introduz algum
overhead ?
O tempo gasto com a troca de
contexto vai variar com as especificações do hardware. Basicamente: tamanho da memória, número de registradores
que devem ser copiados, existência ou não de instruções especiais (exemplo: uma
instrução simples para carregar ou salvar registradores; os processadores RISC
possuem essas instruções load e store), tamanho do disco (para swapping), velocidade da CPU.
RESPONDA: 3.3) Sobre troca
(mudança) de contexto, reponda:
a) Em que consiste?
b) Que “programa” está em execução durante a troca de contexto?
A troca de contexto pode
produzir um gargalo (bottleneck)
fazendo decair em muito a performance. Atualmente há uma solução para esse
problema: a utilização de threads. O
uso de threads passa pela
programação, o que não é simples, e pelo
suporte por parte do próprio sistema operacional, que deve suportar sua criação
e controle. A idéia principal é diminuir o tempo gasto na criação/eliminação de
um PCB para cada subprocesso criado. Sendo assim, subprocessos se diferenciam
de threads pelo espaço de
endereçamento independente que possuem. Threads
compartilham o mesmo espaço de endereçamento de um processo, passando pelos
mesmos estados de um processo.
Contexto
de Hardware
É o contexto que é copiado
para o hardware (CPU) para que a
execução possa ocorrer. Basicamente os registradores : PC (program counter, que contém o endereço da próxima instrução a ser
executada) , SP (stack pointer, o
ponteiro de pilha, que é o registrador que contém o endereço de memória do topo
da pilha), a pilha toda (para que a CPU, ao completar uma função ou subrotina,
saiba para que endereço irá retornar), registrador de estado (PSW).
São as características que
vão influir na execução. O contexto de software
define basicamente 3 grupos de informações :
identificação, cotas e privilégios.
·
Identificação – Cada processo ao
ser criado recebe uma identificação, que é um número e, normalmente, também um
nome. Chamamos esse número de PID (Process IDentification = identificação
do processo). O processo pode receber também, de acordo com o S.O., um
número relacionado à identificação do usuário que o criou UID (User IDentification =
identificação do usuário) e uma identificação
do grupo de usuários aos quais é permitido o acesso a arquivos, processos,
etc.: GID (Group identification = identificação do grupo). Esses dois últimos estão ligados ao
modelo de segurança implementado por alguns S.O. para permitir acessos ou não.
Por exemplo, um usuário não pode normalmente deletar os processos de outros. O
super-usuário pode deletar todos os processos do sistema.
Um processo pode
criar um ou mais processos (estes são chamados de processos-filho = child process). O processo filho tem um PPID (Parent
Process IDentification = identificação do processo-pai), para que o
filho possa retornar ao pai. O PPID de um processo-filho é o UID do
processo-pai.
·
Cotas – Limites de cada
recurso que pode ser utilizado pelo processo. Esses limites são determinados
para o processo no momento de sua criação. Alguns sistemas incluem também,
dinamicamente, porcentagem do recurso já utilizado ou que ainda pode ser
utilizado. Basicamente são: número máximo de arquivos abertos simultaneamente,
tamanho máximo de memória que o processo pode alocar, número máximo de
operações de E/S pendentes, tamanho máximo de buffers para o acesso de E/S, número máximo de subprocessos que
podem ser criados.
·
Privilégios – Definem o que um
processo pode ou não fazer em relação ao sistema e aos outros processos.
Já vimos ( acima ) os privilégios associados à segurança.
Existem outros privilégios associados à operação e à gerência do sistema.
Espaço
de Endereçamento
É a área da memória onde reside o processo. Quando um programa é colocado na memória principal, para que a sua execução seja possível, temos que as instruções estão arrumadas em ordem de execução em endereços adjacentes. Logo após ao bloco de instruções temos a seção de dados que serão utilizados pelo programa. Da mesma forma um processo reside na memória principal com o seu código, em endereços adjacentes, seguido de um bloco de dados.
Ø
Estados do processo
Diagrama de Transição de estados de um processo:

NEW
1
![]()
7
4 2
![]()
![]()
READY
8
![]()
RUNNING 6 BLOCKED
3
![]()
![]()
![]()
6 5
EXIT
New - o processo acabou de ser criado;
Ready - O processo está pronto para executar (só falta o recurso da CPU);
Running - O processo está executando (em modo usuário ou supervisor);
Blocked (sleep) - O processo aguarda disponibilidade de um recurso
"lento" (não há previsão para o recebimento de um recurso que não
seja a CPU);
Exit - O processo terminou.
1.
Agente: S.O. - O S.O. inclui o processo dentre os prontos para
executar;
2.
Agente: S.O. (Rotina Dispatcher ou escalonador) - O processo ganha a
CPU, troca de contexto e o processo começa a rodar. O escalonador controla essa
transição através da lista de prontos (inserindo na lista);
3.
Agente: O próprio processo - O processo necessita de um recurso não
disponível para prosseguir a execução;
4.
Agente: S.O. - O processo foi liberado;
5.
Agente: O próprio processo - A imagem solicita ao S.O. ("System
Call"). É a sua terminação;
6.
Agente: S.O. - S.O. ou outro processo usando uma "system
call". Homicídio (Kill);
7.
Agente: S.O. - Preempção (troca de contexto) - ilusão que vários
processos que utilizam a mesma CPU tem de parecer que tem uma própria CPU;
8.
Agente: S.O. - Desespero - É utilizado em sistema de tempo real.
A política implementada,
normalmente, é a de várias listas de acordo com o que o processo precisa fazer.
Os nomes aqui citados e a quantidade de estados que um processo pode ter vão diferir
de um SO para outro. Ao ser criado o processo vai para a lista de PRONTO (READY),
que indica pronto para começar a execução. Assim que houver oportunidade o
SO vai selecioná-lo (escalonamento) para ocupar a CPU. Normalmente usa-se a
política de listas encadeadas, ou seja, ao colocar na lista o SO já leva em
conta as prioridades. Em cada lista o ponteiro
de um processo aponta (indica) o próximo processo da lista.
Quando estiver executando,
esse processo pode: terminar, fazer uma requisição de I/O, ser interrompido,
ter sua fatia de tempo terminada, criar um novo processo. Enquanto está
executando, ou seja, ocupando a UCP, o processo está no estado EXECUÇÃO (RUNNING).
RESPONDA: 3.6)
Numa máquina com um processador, quantos processos podem estar no estado
EXECUÇÃO simultaneamente? E num ambiente com múltiplos processadores?
Quando faz uma requisição de
I/O o processo pode ter que esperar pela liberação de algum dispositivo de I/O.
Cada dispositivo tem a sua lista. Nesse caso o processo fica no estado de ESPERA (WAIT).
Se o recurso do sistema desejado não está disponível ainda, podemos ter uma
diferenciação do estado de ESPERA,
chamado de estado BLOQUEADO. Um
processo pode estar no estado de ESPERA quando
ele cria um processo-filho e tem que esperar pelo término do processo-filho
para continuar a sua execução. Pode também ocorrer que um processo não precise
esperar pelo término do processo-filho para voltar à sua execução, nesse caso os
processos pai e filho executam concorrentemente.
O término de um processo
envolve uma chamada de sistema, que faz com que o SO retire o processo da lista
e desaloque o seu PCB. Se há processos-filho ainda não terminados, o SO
“aborta” esses processos-filho.
RESPONDA: 3.7)
Quantos processos podem estar no estado PRONTO ? E no estado ESPERA ?
3.8) Em que
estado deve estar um processo para “entrar” na CPU ? Por que motivo?
3.9) Os processos
em estado de PRONTO e ESPERA necessariamente precisam estar ocupando espaço na
memória principal? Que técnica ou recurso é utilizado para solucionar esse tipo
de ocorrência?
Ø
Mudanças de estado
Pelo que vimos acima,
diversos eventos causam uma mudança de estado em um processo. Chamamos de eventos voluntários aqueles gerados
pelo próprio processo e de eventos
involuntários aqueles gerados pelo sistema operacional.
Existem basicamente quatro mudanças de estado do processo, conforme será visto abaixo.
RESPONDA: 3.10) Complete o diagrama
abaixo com os estados “básicos” de um processo e indicação das mudanças de
estado possíveis (completando as setas e numere-as). Em seguida, responda:
a)
O que acontece ao processo em cada um dos estados?
b)
O que ocasiona cada tipo de mudança?
c)
|
|
d)
Quais mudanças são ocasionadas por eventos
voluntários? E por eventos involuntários?
Ø
Tipos de processo
Os processos podem ser classificados de acordo com o tipo de
processamento que realizam, a saber:
·
CPU-bound (ligado à CPU) –
passa a maior parte do tempo no estado de execução, ou seja, utilizando o
processador. Esse tipo de processo realiza poucas operações de E/S.
·
I/O-bound (ligado à E/S) – passa a maior parte do tempo no estado de
espera, pois realiza um elevado número de operações de E/S.
Parte II – Estrutura
Ø
Estrutura do Sistema Operacional
Podemos criar um sistema tão grande e complexo como um sistema operacional somente dividindo-o em pequenas partes. Cada uma dessas partes deve ser uma porção bem delineada do sistema, com entradas, saídas e funções, cuidadosamente definidas. Logicamente, nem todos os sistemas têm a mesma estrutura, ou seja, não apresentam a mesma forma de ligação entre as partes. Contudo, os sistemas operacionais modernos geralmente possuem as seguintes partes:
·
Gerenciamento de processos - criar e eliminar, suspender e retomar,
sincronismo e comunicação entre processos;
·
Gerenciamento da memória principal – manter o controle das partes da
memória que estão sendo usadas e por quem, decidir que processos serão
carregados para memória quando houver espaço disponível, alocar e desalocar
espaço de memória quando necessário;
·
Gerenciamento de memória secundária – o SO é responsável pelas
atividades de alocação de espaço livre, scheduling
de disco;
·
Gerenciamento de Entrada/Saída – manter os device drivers para comunicação com os diferentes dispositivos, um buffer-caching para o sistema;
·
Gerenciamento de arquivos – criar e eliminar arquivos e diretórios,
manter mapeamento dos arquivos em disco;
·
Proteção do sistema – se um sistema é multiusuário e permite mútliplos
processos concorrentes, estes processos devem ser protegidos de outras
atividades;
·
Networking – em um sistema
distribuído (fracamente acoplado) cada processador tem sua própria memória e
seus processadores que se comunicam através do SO. A comunicação entre eles
deve considerar roteamento e estratégias de conexão;
·
Interpretador de comandos – um dos mais importantes programas do SO é o
interpretador de comandos, que serve de interface entre o usuário e o SO.
Alguns SO’s incluem este programa no próprio núcleo (kernel). Já outros sistemas, como o DOS e o UNIX, tratam o
interpretador de comandos como um programa especial que é executado quando uma
sessão é iniciada.
Com
isso, um sistema operacional fornece um ambiente para execução, melhor dizendo,
fornece serviços para os programas e também para os usuários desses programas.
Ø
System Calls
System Calls fornecem a interface entre os processos e o sistema operacional. Estas “chamadas” estão geralmente disponíveis como instruções da linguagem Assembly, e são normalmente encontrados nos manuais usados por programadores de linguagens Assembly. Alguns sistemas permitem que as system calls sejam criadas diretamente a partir de um programa em linguagem de alto nível (linguagem C, Pascal, FORTRAN).
Elas podem ser agrupadas, na maioria dos sistemas, em cinco categorias principais:
·
controle de processos (end, abort, load, execute, create, terminate,
wait event, signal event, set attributes);
·
manipulação de arquivos (create, delete, open, close, read, write, set
attributes)
·
manipulação de dispositivos (request, release, read, write, logically
attach or detach);
·
manutenção de informação (get and set time or date, get and set process
or file);
·
comunicação (create and delete communication connection, send and
receive messages)
A partir do momento que as “chamadas ao sistema” servem de interface entre os processos e o SO, essas são o mecanismo de proteção ao núcleo do SO e também de acesso aos seus serviços, como se fossem as portas de entrada para os processos.
Ø
Modos de acesso
· Dispositivos/recursos compartilhados (E/S de um sistema) devem ser acessados por instruções exclusivas pelo SO;
· Instruções podem ser: privilegiadas (podendo comprometer a estabilidade do sistema) ou não-privilegiadas (não oferecem perigo ao sistema);
· Para execução de instruções privilegiadas, o processador implementa através de um registrador especial, o mecanismo de modos de acesso:
- modo usuário à permite a execução de um subconjunto do total de instruções disponíveis, ou seja, as instruções não-privilegiadas;
- modo kernel ou supervisor à todo conjunto as as instruções podem ser executadas;
· O SO executa em modo kernel, protegendo o hardware do usuário, enquanto os demais software (editores, compiladores) executam em modo usuário;
· Quem determina o acesso, controla e alterna o modo?
As system calls e, caso o programa tente executar uma instrução privilegiada, sem o processador estar em modo kernel, uma exceção é gerada e o programa encerrado.
Ø
Estruturas
A seguir, serão apresentadas algumas maneiras como o código do sistema é organizado e o relacionamento entre seus diversos componentes, ou em outras palavras, sua estrutura interna.
A organização mais comum aos sistemas operacionais é a monolítica. Em um sistema monolítico temos um conjunto de rotinas responsável pela interpretação dos parâmetros passados quando da chamada do sistema por parte de um programa aplicativo, pela execução do serviço solicitado e pelo retorno dos resultados. Qualquer rotina presente no sistema operacional pode vir a chamar qualquer outra das rotinas.
Um bom exemplo é o MS-DOS, originalmente escrito para fornecer o máximo de funcionalidade no menor espaço, até pela limitação do hardware no qual era executado. Como o INTEL 8088 da época não tinha registrador de modo de acesso, os desenvolvedores do MS-DOS não tinham escolha, deixando o hardware básico desprotegido (popular; não foi dividido em módulos; seus níveis de funcionalidade não são separados; programas errados ou maliciosos podem comprometer seu funcionamento).
A modularização de um sistema operacional pode ser feita de diferentes formas; a mais utilizada é a aproximação em camadas, que consiste em dividir o sistema operacional em um número de camadas (níveis), hierarquicamente dispostas, cada nível construído sobre o nível imediatamente abaixo. O nível mais baixo (nível 0) é o hardware e o mais alto é a interface com o usuário.
Módulos de uma camada oferecem funções aos módulos de camadas superiores; cada camada é implementada usando somente aquelas operações fornecidas pelas camadas de mais baixo nível, sendo que a camada não necessita saber como estas operações são implementadas; ela necessita saber o que estas operações fazem.
O kernel do SO passa a ser responsável pela comunicação entre processos e pela implementação de operações que seriam difíceis de serem executadas a partir dos processos servidores. A maioria dos serviços que seriam prestados pelo SO, executado em modo supervisor em uma organização monolítica, passariam a ser prestados por um conjunto de processos servidores que seriam executados em modo usuário, sendo apenas o kernel ainda executado em modo supervisor.
No caso do Windows NT, da Microsoft, cada subsistema do ambiente e o NT Executive são implementados como sendo vários processos. Cada processo espera por uma solicitação de um cliente para um de seus serviços (por exemplo, serviços de memória, serviços de criação de processos, ou serviços de escalonamento do processador). Um cliente, que pode ser uma aplicação do usuário ou outro módulo do sistema operacional, solicita um serviço por envio de uma mensagem. A mensagem é direcionada através do NT Executive para o servidor apropriado. O servidor realiza a operação solicitada e retorna os resultados por meio de uma outra mensagem, que é direcionada através do NT Executive de volta ao cliente. [STAL98]
Ø
Conceito de Escalonamento
Com a possibilidade da UCP ser compartilhada entre diversos processos (multiprogramação), o SO possui critérios para determinar qual a ordem na escolha dos processos para que estes passem do estado de PRONTO para EXECUÇÃO.
|
|
O procedimento de seleção é
função do SO, sendo conhecido como escalonamento (scheduling). A parte do código do SO responsável pelo escalonamento
é o escalonador (scheduler). O SO
deve tratar todos os processos igualmente, evitando starvation.
Como já foi mostrado anteriormente, um bom sistema operacional multitarefa deve levar em conta os critérios abaixo. Lembre-se que alguns podem ser mais “importantes” que outros, dependendo da atividade que o sistema operacional desempenhará com suas aplicações:
- Utilização da CPU : o processador principal deve estar ocupado a maior parte do tempo possível, a não ser que não haja o que executar mesmo;
-
Throughput : é o número de processos
executados por unidade de tempo; é desejável que a quantidade de processos
“atendidos” pelo sistema em um determinado intervalo de tempo seja a maior
possível;
-
Tempo de turnaround : tempo decorrido desde
a admissão do processo no sistema até o seu término. Então, inclui tempo na
fila de espera + tempo na fila de
pronto + tempo de execução;
-
Tempo de Resposta : Em sistemas interativos, é
o tempo decorrido entre o instante da submissão de um pedido (teclar um ENTER
após um comando, por exemplo) e a apresentação da primeira resposta.
Algoritmos de escalonamento buscam otimizar a utilização da UCP e o
throughput, enquanto tentam diminuir os tempos de turnaround e de resposta. No
entanto, o escalonamento somente afeta o tempo de resposta de processos na fila
de pronto.
Ø
Tipos de Escalonamento
|
|
Alguns PROBLEMAS
encontrados em escalonamentos não preemptivos:
·
FIFO – previsão de início da execução do processo;
processos CPU-bound de menor importância prejudicam processos I/O-bound mais
prioritários;
·
SJF – determinar quanto tempo de UCP cada processo
necessita para terminar seu processamento;
·
COOPERATIVO – não existe nenhuma intervenção do SO na execução
do processo, o que pode ocasionar problemas caso o processo não libere o
processador.
Escalonamento
Circular ou Round Robin
Implementação: UMA fila de
PRONTO. Os processos entram na fila na ordem de chegada e sai primeiro o que
chegou primeiro (FIFO). É definida uma fatia de tempo (time-slice).
Um processo em execução pode
deixar a CPU pelos seguintes motivos :
-
acabou è nesse caso deixa de estar ativo no sistema
-
fez requisição ao SO
è nesse caso fica em estado de ESPERA
-
acabou a fatia de tempo è nesse caso fica em estado de PRONTO, entrando no
final da fila de processos PRONTOs
|
|
Quando termina a fatia
de tempo, sem que o processo tenha terminado ou feito uma requisição ao
SO, é o SO quem retira o processo de execução. Chamamos este evento (que é
involuntário) de preempção por tempo.
Escalonamento por Prioridades
Implementação: UMA fila de
PRONTO. Cada processo tem, associada a ele, uma prioridade de execução.
Tal prioridade
pode ser dada ao processo pelo usuário ou pelo SO; pode ser estática
(quando é sempre a mesma ao longo da vida do processo) ou pode ser dinâmica
(quando o SO a modifica durante a vida do processo, de acordo com o
tipo de processamento e/ou carga do sistema).
Exemplo de prioridade dinâmica:
para compensar o tempo que os processos ficam em estado de ESPERA, o S.O
faz um acréscimo à prioridade dos processos sempre que saem do estado de
ESPERA.
Um clock interrompe o processador em determinados
intervalos de tempo, para que seja executada a rotina de escalonamento .
Esta rotina arruma os processos na fila de acordo com suas prioridades. Se na
fila de PRONTO estiver um processo com prioridade maior do que a prioridade
do processo que estava em execução, este que estava em execução passa a ficar
em estado de PRONTO e o outro de maior prioridade é escalonado para execução.
Chama-se preempção por prioridade o evento em que o SO retira um
processo que estava em execução para dar lugar a outro processo de maior
prioridade. Note que este evento é involuntário, ou seja, não depende do
processo que está sendo “preemptado”.
Escalonamento por Múltiplas Filas
Implementação: VÁRIAS FILAS
DE PRONTO, sendo que a cada uma está associada uma prioridade. Cada processo é
associado a UMA e SOMENTE UMA fila e nela PERMANECE durante toda a sua vida no
sistema.
O sistema SÓ PODE ESCALONAR
PROCESSOS DE UMA DAS FILAS QUANDO TODAS AS OUTRAS DE MAIOR PRIORIDADE ESTIVEREM
VAZIAS.
Exemplo
|
|
Seja um sistema com três
filas:
Escalonamento por Múltiplas Filas com realimentação
Implementação: VÁRIAS FILAS
DE PRONTO, sendo que a cada uma está associada uma prioridade. O sistema SÓ
PODE ESCALONAR PROCESSOS DE UMA DAS FILAS QUANDO TODAS AS OUTRAS DE MAIOR PRIORIDADE
ESTIVEREM VAZIAS.
O SO PODE MUDAR um processo
DE FILA de acordo com as características do processo e/ou carga do sistema.
Chama-se este esquema de mecanismo adaptativo.
Quando o processo é criado,
entra no final da fila de MAIOR prioridade. Quando um processo em execução
deixa a CPU seja por preempção por
prioridade ou por uma requisição ao SO, ele é reescalonado dentro da MESMA
fila. Quando deixa a CPU por preempção
por tempo, o processo é redirecionado para uma fila de MENOR prioridade.
Quanto maior for a prioridade de uma
fila menor será a fatia
de tempo associada a esta fila.
Escalonamento de Sistemas de Tempo Real
É um escalonamento
UNICAMENTE por prioridade ESTÁTICA.
Escalonamento com Múltiplos Processadores
-
Sistemas Fortemente
Acoplados (Memória Compartilhada): UMA
única fila de PRONTO para todos os processadores. Todos os processos estão
presentes nesta fila e são escalonados no primeiro processador disponível.
Naturalmente, cada processo só pode ser escalonado para um processador.
-
Sistemas
Fracamente Acoplados (Memória Distribuída): cada processador tem o seu
próprio escalonamento, visto que cada processador tem sua memória própria, seu
sistema operacional próprio e consequentemente seu algoritmo de escalonamento próprio.
4.1 Qual a parte do sistema operacional responsável pela escolha de processos no estado de pronto que passarão para o estado de execução?
4.2
O que é escalonamento?
4.3
Justifique: um algoritmo de escalonamento busca otimizar a utilização da UCP e
o throughput, enquanto tenta diminuir
os tempo de turnaround e de resposta?
4.4
O que é starvation? O escalonamento
de processos pode levar um processo a sofrer starvation? Explique?
4.5
Cite fatores que possam influenciar no tempo total de execução de processos.
4.6
O que é preempção? Diferencie escalonamento preemptivo de não-preemptivo.
4.7
Como funciona o escalonamento FIFO? (Lembre-se de uma fila de banco)
4.8 Sejam os processos abaixo:
|
Identificação do processo |
CPU (u.t.) |
Característica do processo |
A |
52 |
faz requisição de I/O a
cada 15u.t. |
|
B |
11 |
faz requisição de I/O a
cada 3u.t. |
|
C |
3 |
faz requisição de I/O a
cada 2u.t. |
onde por “CPU (u.t.)” estamos representando quantas
unidades de tempo são necessárias para a execução dos processos em CPU
Suponhamos que sejam
necessárias 8 u.t. (oito unidades de tempo) para que se realize qualquer uma
das requisições de I/O e que Vamos desconsiderar o overhead de criação/deleção de processos e de troca de contexto. O
tempo gasto no escalonamento de processos por parte do S.O. é de 1 u.t. (uma
unidade de tempo). Considere que os processos A, B e C entraram no sistema
nessa ordem (A, B e depois C), mas a diferença entre tais instantes é tal que
pode ser desconsiderada. Considere também que os processos foram criados no
instante inicial de funcionamento do sistema (0 u.t.). Faça o papel do sistema
operacional e complete os quadros abaixo:
1a
situação) Para um algoritmo de escalonamento não-preemptivo FIFO (nenhum
processo fique em momento algum bloqueado).
|
Instante de tempo (u.t.) |
Fila
de Pronto
|
Executando na UCP |
Fila de Espera |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2a
situação) Para um algoritmo de escalonamento não-preemptivo FIFO.
|
Instante de tempo (u.t.) |
Fila
de Pronto
|
Executando na UCP |
Fila de Espera |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3a
situação) Para um algoritmo de escalonamento preemptivo ROUND ROBIN com quantum de 10u.t.
|
Instante de tempo (u.t.) |
Fila
de Pronto
|
Executando na UCP |
Fila de Espera |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Tempo
que a CPU ficou inativa = ______ % do tempo total
Baseado nos resultados dos
quadros acima, preencha: (1,0p)
|
|
Tempo de turnaround
|
Tempo Ocioso da CPU |
Avaliação |
||||
|
Processo A |
I) |
II) |
III) |
I) % |
II) % |
III) % |
|
|
Processo B |
I) |
II) |
III) |
I) % |
II) % |
III) % |
|
|
Processo A + B |
I) |
II) |
III) |
I) % |
II) % |
III) % |
|
4.9 Considerando na fila de PRONTO de um sistema operacional que implementa um algoritmo de escalonamento de processos de forma preemptiva circular, sem prioridades e de quantum fixo, as seguintes situações:
1a situação) Muitos processos CPU-Bound e poucos processos I/O-Bound
2a situação) Somente processos I/O-Bound
3a situação) Muitos processos I/O-Bound e poucos processos CPU-Bound
Classifique cada sentença
como Verdadeira (V) ou Falsa (F), justificando-as quando falsas:
I. Na 2a situação, mesmo que o único
dispositivo de E/S seja rápido, a concorrência à utilização é grande o que
ocasiona menor utilização de tempo da UCP. (
)
II. Pode-se afirmar que o escalonamento de
processos por parte do sistema operacional é o único responsável pelo tempo de turnaround dos processos, afetando até o
tempo que os processo ficam na fila de espera. ( )
III. Na 3a situação a minoria de
processos CPU-Bound sofreria starvation. ( )
IV. Com exceção da 2a
situação, os processos CPU-Bound
certamente irão monopolizar o processador, mesmo que o tempo máximo de
utilização do processador seja igual ao quantum.
( )
V. Na 1a
situação, quanto menor o tempo perdido na troca de contexto pior é, pois os
processos I/O-Bound solicitam
operações de E/S a todo instante, independente do aproveitamento do processador
por parte dos processos CPU-Bound.
( )
Ø
Problemas de comunicação
A comunicação entre
processos concorrentes deve ser tratada pelos sistemas operacionais. Os
mecanismos que garantem a comunicação entre processos concorrentes e o acesso a
recursos compartilhados são chamados mecanismos
de sincronização;
Vejamos um exemplo onde pode ocorrer acesso concorrente a um arquivo em disco (memória secundária):
§ Imagine um arquivo de contas bancárias (ARQ_CONTAS) que contenha as informações de cada cliente do banco (REG_CLIENTE), dentre elas o saldo. Quando é realizado algum lançamento por um caixa, seja depósito ou retirada, um simples programa é executado:
READ (ARQ_CONTAS, REG_CLIENTE);
READLN (VALOR_DEP_RET);
REG_CLIENTE.SALDO : =
REG_CLIENTE.SALDO+VALOR_DEP_RET;
WRITE (ARQ_CONTAS, REG_CLIENTE);
§
Se em um mesmo instante dois caixas diferentes processarem seus
lançamentos no saldo de um mesmo cliente e, não houver controle do
compartilhamento, o que pode acontecer?
Suponha que os dois caixas leiam do arquivo o saldo (R$ 100,00, por exemplo), um deles realize uma operação de depósito de R$ 50,00 (total de R$ 150,00) e o outro de 500,00 (total de R$ 600,00); o que realizou o maior depósito atualiza a informação do arquivo primeiro e o outro atualize a informação logo depois, no instante seguinte; o resultado seria um saldo de R$ 150,00 para os dois depósitos.
CONCEITOS:
Recursos X
RC (Regiões Críticas)
Recursos - Qualquer coisa necessária para prosseguir com sua execução
Região Crítica - Trecho de programa (processo) onde se vai fazer uso do
recurso.
Postulado de Dijktra sobre
programação concorrente:
1.
Garantia da Exclusão Mútua: Só um processo pode ter acesso ao recurso
de cada vez (entrar na RC)
2.
Um processo fora da RC (Não está usando o recurso) não deve impedir que
outro processo entre na RC;
3.
Nenhum processo deve sofrer adiamento indefinido - Starvation;
4.
Nada pode ser assumido quanto à velocidade de execução dos processos
quanto ao número de processadores;
5.
Todo processo detém a posse do recurso (permanece na RC) por tempo
finito.
Ø
Exclusão mútua e região crítica
A solução mais simples para evitar problemas de compartilhamento de
recursos é impedir que dois ou mais processos acessem este recurso no mesmo
instante. Essa exclusividade de acesso é chamada exclusão mútua, ou seja, enquanto um processo acessa determinado
recurso, todos os outros que queiram acessá-lo deverão esperar até o término
deste acesso.
A exclusão mútua deve afetar
os processos concorrentes apenas quando um deles estiver realizando acesso ao
recurso compartilhado.
Somente a parte do código do programa onde é realizado o acesso ao
recurso compartilhado, chamada de região
crítica, é executada de forma
mutuamente exclusiva em relação a todas as outras. Em outras palavras, se for
possível evitar que dois processos entrem em suas regiões críticas ao mesmo
tempo, evitam-se problemas decorrentes do compartilhamento.
Ø
Soluções de software para exclusão mútua
a) Tranca
Variavel inteira que assume dois valores que
simbolizam os estados de Ocupado ou Livre, e a alteracao de seus valores e
indivisivel.
Para tal precisa-se que o HW garanta o
recurso e altere o seu valor em um
único ciclo da CPU.
Operação de Test and Set - TAS:(Instrução em Assembler). A partir do
momento que é ativada pede e garante o recurso. Substitui a variável que indica
se está trancada ou não por uma indicando que está trancada, independentemente
de qual era o seu estado anterior. Assim ela garante o recurso.
Problemas:
·
Depende de instrução específica;
·
Pode ocasionar starvation (3 processos: 2 revesam a posse do recurso e
1 nunca o conhece)
·
Ocorre espera Ocupada.
Por que usar esta solução?
Se o recurso for rápido
(alterar listas, tabelas,...) não vale a pena adormecer o processo (trocar o
contexto), portanto apesar da espera ocupada, esta solução se aplica a recursos
rápidos.
Spinlock - possui o TAS embutido.
Spinunlock - Destrava o recurso após sua utilização.
Tranca é um mecanismo
de sincronização que permite a manipulação de um recurso simples por diversos
processos. Apenas 1 processo detém a posse deste recurso em um dado instante de
tempo.
2 formas de checar o
valor da tranca:
·
loop interno
·
test an set - loop externo (2 acessos ao barramento)
Qual a vantagem de se ter um
loop interno dentro do TAS?
A vantagem do loop interno é que degrada menos o barramento, pois faz
apenas um acesso para fazer a consulta se o recurso está ou não disponível.
b) SEMÁFOROS
Semáforo é uma forma de sincronização
que permite a utilização de múltiplos recursos por vários processos, mas apenas
um único processo pode manipulá-lo em dado instante de tempo. Isso ocorre
porque existe um mecanismo de tranca em sua composição que tem uma política de
que apenas 1 processo pode ser executado por vez (processo de tranca).
Um semáforo é uma variável
inteira, não negativa, que só pode ser manipulada por duas instruções: DOWN e
UP. No caso da exclusão mútua, essas instruções funcionam para que um processo
possa entrar e sair de sua região crítica, respectivamente.
O semáforo fica associado a
um recurso compartilhado, indicando quando este recurso está sendo acessado por
um dos processos concorrentes.
O uso de semáforos exige do
programador muito cuidado, pois qualquer engano pode levar a problemas de
sincronização imprevisíveis e difíceis de reproduzir, devido a execução
concorrente dos processos.
Características
Elimina a espera ocupada
Generaliza a espera ocupada para recursos múltiplos
Tenta acabar com a starvation
Definição: O semáforo é uma
variável inteira que assume valores na faixa de 0....N.
Operações:
INIT (S,X) - S=X, sendo 0=< X =< N
DOWN (S) - se S>0 então
S=S-1
Caso contrário o processo na lista de espera é bloqueado (Blocked)
O Down estabelece a permissão do acesso (entrada na RC)
-UP(S) - se há processos esperando na lista de S
Acorda um deles
(Ready)
Caso contrário (S=S+1)
Chamadas:
Down (s);
RC ( );
UP (s);
Obs.: As operações são indivisíveis.
Semáforo é: - Valor (a ser incrementado/
decrem.)
- Lista de
espera (ponteiros p; PCB)
- Variável de
tranca (garante a indivisibilidade)
DEADLOCK - É uma situação
de falha na sincronização irreversível, ou seja, ocorrerá um adiamento perpétuo
na execução do processo. (isto ocorre quando se esquece de dar o spinunlock)
Difere do starvation pois este adiamento é indefinido e não perpétuo.
(ex. quando a região crítica é muito extensa)
Trydown - É uma função como o down dos semáforos mas esta dá uma poder
decisório para se tomar uma atitude caso não haja um recurso disponível. O
processo não precisa dormir automaticamente na ausência do recurso. Se houver
um recurso disponível ele age exatamente como o down.
Ex.: O Trydown pode dar uma mensagem de erro ao usuário, avisando sobre
a ausência de recursos. Assim o usuário poderia procurar o recurso em outra
máquina.
Com esta função,
você pode ter uma rotina de espera ocupada, que garante a exclusão mútua,
usando semáforos, da mesma forma que com trancas. É só colocar um loop de
trydown testando a disponibilidade do recurso.
c) MONITORES
O monitor é um conjunto de procedimentos,
variáveis e estrutura de dados definido dentro de um módulo, onde a exclusão
mútua é implementada automaticamente entre seus procedimentos. O mais
importante é que toda a implementação da exclusão mútua nos monitores é realizada pelo compilador,
e não mais pelo programador, como no caso dos semáforos. As regiões críticas
são colocadas em forma de procedimentos no monitor
e o compilador se encarrega de garantir a exclusão mútua desses procedimentos,
sendo as chances de erro menores.
Ø
Alocação de memória
Ao executar um programa residente na memória secundária, deve-se, de alguma forma, carregá-lo para a memória principal. A organização e a gerência da memória principal são fatores importantes no projeto de sistemas operacionais modernos. Melhor dizendo, os sistemas operacionais devem ocupar pouca memória e otimizar ao máximo sua utilização.
A) Alocação contígua simples – comum em
sistemas monoprogramáveis, onde a memória principal é dividida em duas partes:
uma para o sistema operacional e outra para o programa do usuário. O
programador deve se preocupar em não ultrapassar o espaço disponível de memória
endereçável, ou seja, o tamanho total da memória principal menos o que está
sendo ocupado pelo sistema operacional. Para proteger a área do sistema
operacional alguns desses sistemas implementavam proteção através de um
registrador, que delimita as áreas.
Nesse esquema de
fácil implementação e código reduzido, apenas um usuário poderia dispor do
processador e da memória, que ficava sem utilização caso o programa do usuário
não o preenchesse totalmente. Como os programas estavam limitados ao tamanho da
memória principal disponível, a situação foi contornada dividindo-se o programa
em partes (módulos) que pudessem executar independentemente uma da outra,
utilizando uma mesma área de memória (overlay);
B) Alocação particionada estática – para que a multiprogramação
fosse eficiente, era necessário que vários programas estivessem na memória
principal ao mesmo tempo. Por esse motivo, a memória foi dividida em pedaços de
tamanho fixo, chamados partições. O tamanho das partições era estabelecido na
fase de inicialização do sistema, em função do tamanho dos programas que iriam
executar no sistema. Sempre que fosse necessária a alteração do tamanho de uma
partição, o sistema deveria ser desativado e reinicializado com a nova
configuração.
Quando os compiladores e linkeditores geravam CÓDIGO ABSOLUTO, o código gerado possuía endereços físicos de memória (observação: vamos trabalhar com endereços expressos em decimal). O formato geral das instruções de máquina é:
|
endereço |
instrução |
Para facilitar, vamos supor
que cada instrução de alto nível gera 1 (uma) instrução de máquina. Com código
absoluto as instruções de máquina de um trecho do programa ficariam:
|
ENDEREÇO |
CÓDIGO DA INSTRUÇÃO |
|
501 502 503 504 505 506 507 508 |
Ler B, C e H A = B + C D = H – A Se D < 0 então vá para 502 J = V * H Escreve J |
Este programa SÓ PODE SER carregado na memória nos endereços físicos 502 a 507.
Com a evolução dos compiladores, linkeditores e loaders, a geração de CÓDIGO RELOCÁVEL foi possível, e os programas podiam então ser carregados em qualquer região disponível da memória. Ou seja, as instruções são geradas com um endereço virtual e não com o endereço físico.
|
ENDEREÇO VIRTUAL |
CÓDIGO DA INSTRUÇÃO |
|
0 1 2 3 4 5 |
Ler B, C e H A = B + C D = H – A Se D < 0 então vá para 0 J = V * H Escreve J |
721 REGISTRADOR DE RELOCAÇÃO
No momento em que o programa é carregado na
memória, um registrador de relocação
recebe o endereço inicial da região de memória que o programa irá ocupar
(relocação dinâmica). Toda vez que ocorrer uma referência a algum endereço
virtual, o endereço contido na instrução será somado ao conteúdo do registrador
de relocação, obtendo-se desta forma o endereço físico. Então esse programa
(como qualquer outro) PODERÁ RESIDIR EM QUALQUER PARTE da memória.
Para o exemplo anterior:
|
ENDEREÇO VIRTUAL |
ENDEREÇO FÍSICO |
CÓDIGO DA INSTRUÇÃO |
|
0 1 2 3 4 5 |
0+721=721 1+721=722 2+721=723 3+721=724 4+721=725 5+721=726 |
Ler B, C e H A = B + C D = H – A Se D < 0 então vá para 0+721=721 J = V * H Escreve J |
Como os programas normalmente não preenchiam totalmente as partições onde eram carregados, eles deixavam pedaços de memória que ficariam impedidos de ser utilizados por outros programas (fragmentação). E mesmo que existissem duas ou mais partições adjacentes que, somadas, totalizassem o tamanho do programa, ele ficaria aguardando uma única que o acomodasse;
A) Alocação particionada dinâmica – Como foi visto
no item anterior, havia a necessidade de diminuir o problema da fragmentação,
aumentado o compartilhamento da memória principal. Na alocação particionada dinâmica
foi eliminado o conceito de partições de tamanho fixo, de forma que cada
programa utilizasse o espaço de que necessitasse, passando esse pedaço a ser
uma partição. A fragmentação no entanto, começaria a ocorrer quando os
programas fossem terminando e deixando espaços cada vez menores na memória, não
permitindo ingresso de novos programas.
Existiam duas possíveis soluções para este problema: na primeira, apenas os espaços adjacentes são reunidos, produzindo um único espaço de tamanho maior; a segunda maneira envolve a relocação de todas as partições ocupadas, eliminando todos os espaços entre elas e criando uma única área livre contígua (alocação dinâmica com relocação). Porém a complexidade do seu algoritmo e o consumo de recursos do sistema, como processador e área em disco, podem tornar essu esquema inviável;
Ø
Estratégias para escolha de partição
Na tentativa de evitar, ou mesmo reduzir, a fragmentação antes que ela ocorra, algumas estratégias são implementadas pelos sistemas para determinar em qual partição livre um programa será carregado para execução:
ð
BEST-FIT – escolhe a partição em que o programa deixa o menor espaço
sem utilização; a lista de áreas livres está ordenada por tamanho; desvantagem:
com a alocação de partições que deixem as menores áreas livres, a tendência é
que cada vez mais a memória fique com pequenas áreas não contíguas, aumentando
o problema da fragmentação;
ð
WORST-FIT – é escolhida a partição em que o programa deixa o maior
espaço sem utilização; apesar de utilizar as partições maiores, os espaços
livres maiores permitem o aproveitamento da memória por um maior número de
programas;
ð
FIRST-FIT – esse mecanismo escolhe a primeira partição livre, que tenha
tamanho suficiente para carregar o programa; a lista de áreas livres está
ordenada por endereços crescentemente; é mais rápida, consumindo menos recursos
do sistema.
Ø
Swapping
É uma técnica utilizada para tentar solucionar o problema de falta de memória. Seja uma memória com área livre para programas de usuário de 500Kb. Imagine que há 4 programas A, B, C e D, cada um com 200Kb, que poderiam estar todos ativos se coubessem na memória. Então aloca-se os programas A e B somente. Se o programa A tiver que aguardar por algum evento, podemos retirá-lo da memória e levá-lo para o disco, enquanto aguarda pelo evento. Enquanto isso o programa C, por exemplo, pode ir para a memória para que sua execução seja iniciada.
SWAP OUT à retirada de um programa da memória para o disco
SWAP IN ß retorno do programa do disco para a memória
Ø
Memória Virtual
A utilização da memória virtual é uma outra técnica para tentar solucionar o problema de falta de memória. Esta técnica consiste em: - utilizar os endereços virtuais
- o disco com continuação da memória principal
sem que o usuário perceba.
Se um programa de 200Kb só pode utilizar 100Kb da memória, porque não há mais área livre, os outros 100Kb ficarão em disco. Somente quando os endereços virtuais que estão no disco forem referenciados é que a 2a parte do programa vai para a memória.
Ø
Mapeamento
Mecanismo que permite ao SO traduzir os endereços virtuais em endereços reais.
Implementação por software: o SO tem uma tabela com a tradução, que é mantida ma memória principal. Esse mecanismo é custoso, pois envolve percorrer tabelas
|
End. Real |
Nº processo |
End. Virtuais |
|
210 |
3174 |
20 a 133 |
|
323 |
2022 |
74 a 191 |
|
431 |
3174 |
0 a 20 |
Implementação por hardware: Translation Lookside buffer ou memória associativa
Qual o tamanho desses pedaços de programa?
Ø
Paginação
O espaço de endereçamento virtual e o espaço de endereçamento real são divididos em blocos do mesmo tamanho.
O princípio da localidade é a tendência dos programas de fazerem referência às posições consecutivas da memória. Baseado nisso surgiu a idéia de se dividir os processos em blocos de tamanhos fixos, chamados PÁGINAS. Se dividirmos também o espaço real em blocos do mesmo tamanho, teremos na memória principal, por exemplo, algo assim:
|
|
|
Página 4 do processo A |
|
Página 10 do Processo B |
|
Página 1 do processo A |
|
|
Com isso não haverá espaços livres entre os espaços ocupados, isto é, fragmentação. As páginas são levadas para a memória principal de acordo com a sua necessidade. Ao ser referenciado um endereço qualquer de uma página, toda a página é colocada na memória.
Nesse esquema o endereço virtual é:
|
nº da página |
deslocamento dentro da página |
Cada processo tem sua tabela de páginas:
|
nº da página |
end. físico |
Bit de validade |
|
000 |
|
0 |
|
001 |
7024 |
1 |
|
002 |
810 |
1 |
|
|
|
|
O bit de validade informa se a página está na memória (igual a 1) ou não (igual a 0).
Por exemplo: o endereço virtual 001 3 do processo A está no endereço real 7024+3=7027. Se um endereço referenciado não está na memória principal a página é alocada e a tabela de páginas é atualizada. Esse mecanismo de só levar para a memória principal as páginas que são necessárias chama-se PAGINAÇÃO POR DEMANDA. E chama-se FALHA DE PÁGINA (page fault) o evento de o processo precisar de 1 página que não está na memória.
WORKING SET de um processo é o conjunto de páginas referenciadas por ele durante um intervalo de tempo. Uma segunda definição: o conjunto das páginas constantemente referenciadas pelo processo, devendo permanecer na memória principal. Caso contrário, o processo poderá sofrer com a elevada taxa de paginação (TRASHING) comprometendo seu desempenho. O working set do processo deve ter um limite máximo de páginas permitidas; quanto maior a working set , menor a chance de ocorrer FALHA DE PÁGINA.
A paginação envolve uma operação de E/S, então é aconselhável que haja uma política que diminua a taxa de paginação. A escolha da página “certa” a ser retirada da memória principal para que outra seja carregada em seu lugar é importante. A página que está sendo retirada não deverá ser usada posteriormente, o que ocasionaria nova troca. As estratégias para retirar páginas de um processo da memória (realocação de páginas) são:
ð Aleatória: retira uma página aleatoriamente; algoritmo fácil à pouco overhead à pouca eficiência;
ð FIFO (First In First Out): a 1a página referenciada é a 1a página a sair; algoritmo simples utilizando fila à pouca eficiência;
ð LRU (Least Recently Used): retira a página menos recentemente utilizada, ou seja, a que está há mais tempo sem ser referenciada;
ð NRU (Not Recently Used): parecida com a anterior, um flag de referência indica se a página foi ou não utilizada. Inicialmente todas as páginas tem 0 (zero). Quando a página é utilizada, seu flag=1. De tempos em tempos, todos os flags são zerados. Overhead menor que a anterior, boa eficiência;
ð LFU (Least Frequently Used): retira a menos freqüentemente utilizada. Utiliza um contador que recebe um acréscimo cada vez que a página for referenciada. Grande eficiência; overhead razoável.
Para qualquer estratégia: ANTES DE RETIRAR UMA PÁGINA DA MEMÓRIA é preciso verificar o seu bit de modificação. Se a página foi modificada tem que ser atualizada no disco.
O tamanho da página é determinado pelo SO de acordo com o hardware (geralmente entre 512bytes e 64Kb). Se a página for . . . então . . .
MUITO PEQUENA: tabelas de mapeamento muito grandes à grande overhead para percorrer tabela à muita paginação à menor fragmentação;
MUITO GRANDE: memória ocupada sem utilização à custo maior a cada swap in, swap out à maior fragmentação;
Ø
Segmentação
Com o uso da paginação tentou-se deixar na memória apenas as páginas mais utilizadas de cada processo, ao invés de deixar residente o processo inteiro. Mas o sucesso dessa técnica vai depender da estrutura do programa. Uma outra idéia é dividir o programa pela sua estrutura e não em tamanhos fixos. Os blocos tem então tamanhos diferentes e são chamados segmentos. O endereço virtual é composto pelo número do segmento e o deslocamento dentro do segmento. O endereço físico é calculado a partir do endereço físico do segmento + o deslocamento dentro do segmento. E somente os segmentos referenciados são alocados na memória principal.
A eficiência desta técnica vai depender da modularização da aplicação: módulos grandes (cada módulo será um segmento) nos quais somente uma parte do código é referenciada vai retornar ao problema de ocupação desnecessária na memória.
SEGMENTAÇÃO COM PAGINAÇÃO
Os segmentos são estabelecidos de acordo com a estrutura do programa e os segmentos são divididos em páginas. As páginas tem tamanho único no sistema. Os segmentos tem tamanho variável. O endereço virtual é formado assim:
|
nº do segmento |
nº de página dentro do segmento |
deslocamento dentro da página |
Exercícios
1.
Qual a diferença da alocação particionada estática e dinâmica?
2.
Como funciona a alocação dinâmica com relocação e quais suas
desvantagens?
3.
O que é e qual a importância da análise do working set dos programas?
4.
Qual a relação entre working set
e trashing?
5.
O que é falha de página e quais as formas de se evitá-la?
6.
Diferencie paginação de segmentação com relação aos seguintes aspectos:
a)
lógica dos programas X divisão dos espaços de endereçamento
b)
fragmentação (quando e como ocorre)
1. Working Set de um processo A tem seu tamanho limitado a quatro frames e encontra-se ocupado conforme quadro abaixo:
|
Página |
Última referência |
Flag de Referência |
Entrada no sistema |
Contador de referências |
|
1 |
260 u.t. |
1 |
200 u.t. |
3 |
|
5 |
150 u.t. |
0 |
150 u.t. |
0 |
|
2 |
200 u.t. |
1 |
100 u.t. |
1 |
|
4 |
250 u.t. |
1 |
180 u.t. |
2 |
Tabela 1 – Frames do processo A
Às 300 u.t. ocorre uma falha de página referente à página 3, pertencente ao processo A. Responda qual página será escolhida para cada estratégia de relocação abaixo, justificando sua resposta:
a) LRU b)
FIFO c) NRU d) LFU
|
PÁGINA |
CARGA |
ÚLTIMA REFERÊNCIA |
CONTADOR |
M |
|
0 |
126 |
279 |
2 |
0 |
|
1 |
230 |
260 |
4 |
0 |
|
2 |
120 |
272 |
3 |
1 |
|
3 |
160 |
280 |
1 |
1 |
a) Qual página será
substituída pelo algoritmo FIFO? Justifique.
b) Qual página será substituída
pelo algoritmo LFU? Justifique.
c) Qual página será
substituída pelo algoritmo LRU? Justifique.
No momento da execução
o processador faz a busca das instruções e dos dados na memória principal. Além
disso, no caso de escrita, o processador também o faz na memória principal.
Sabemos que os sistemas de computação atuais utilizam a memória cache como uma
memória intermediária entre a memória principal e o processador, com o objetivo
de aumentar a velocidade de acesso aos dados e instruções. Neste capítulo vamos
tratar da gerência de memória feita pelo sistema operacional, ou seja, vamos
estudar como o sistema operacional trata de fazer com que o código e os dados
de um processo estejam na memória principal no momento de sua execução da forma
mais rápida e eficiente possível. Também estudaremos as técnicas utilizadas
pelo sistema operacional para ter em memória principal os códigos e dados
referentes ao maior número de processos possível, o que melhora a performance
do sistema de computação.
Vamos dividir o
nosso estudo em partes :
Parte I - Gerenciamento de Memória : Mecanismos
fundamentais utilizados em gerenciamento de memória.
Parte II - Memória Virtual : Criação de um
espaço virtual em disco => parte deste espaço é trazido para a memória real
quando é necessário => maior número de processos compartilhando a memória
real, sendo que apenas uma pequena parte ( a mais necessária ) pertencendo a
cada processo.
Parte III - Gerenciamento de Memória no Windows NT : Utilizaremos as
ferramentas do Windows NT para observarmos os aspectos desta gerência no
Windows NT
PARTE I
- GERENCIAMENTO DE MEMÓRIA
Em sistemas monotarefa
a memória principal é dividida em duas partes : uma para o sistema operacional
e a outra para a aplicação que está em execução.
----> ( Prática + Gabriel Torres )
Nos sistemas
multitarefa a parte relativa às aplicações deve ser "dividida" entre
várias tarefas. Por que ?
R : Sabemos que nos sistemas multitarefa há
várias tarefas ativas em um determinado instante. O sistema operacional utiliza
o seu algoritmo de escalonamento para determinar que processo estará ativo em
um determinado momento. Lembremos que nos sistemas de tempo compartilhado, por
exemplo, o sistema operacional dedica uma fatia de tempo para a execução de
cada processo, dando a impressão ao usuário de que várias tarefas estão em
execução. Na verdade, sabemos que num sistema de computação com um único
processador central, apenas um processo estará em execução de cada vez. Se a
cada vez que o S.O. dedicar o tempo do processador para outro processo, o
conjunto de instruções e dados deste processo tiver que ser buscado no disco, o
tempo de troca passará a ser da ordem do tempo de acesso a disco, o que tornará
o processador ocisoso e o sistema como um todo extremamente lento, caindo por
terra toda a vantagem da multitarefa.
Esta
"divisão"dinâmica da memória principal, é tarefa do sistema
operacional e é conhecida como gerenciamento
de memória.
I. 1 Requisitos necessários ao Gerenciamento de
Memória
relocação compartilhamento organização física
proteção organização lógica
Relocação : Se o conjunto de código e dados
de um processo passa para disco ( swap out ) enquanto o processo ainda
está ativo, que região da memória física este conjunto irá ocupar quando
retornar a esta ( swap in ) ? Se o código criado para cada processo for absoluto, todas as referências feitas
serão aos endereços físicos nos quais as informações desejadas estão alocadas.
Nesse caso, a alocação terá que ser sempre no mesmo espaço físico. É desejável
que a alocação possa ser feita em qualquer lugar da memória. Esta questão levou
à idéia de endereçamento virtual que
veremos adiante.
Lembremos a imagem de um processo :

Bloco de Controle do
Processo
![]()

Programa Desvio de fluxo

![]()
Referência
a dado
Dados
![]()
Pilha
Proteção : Um processo não pode fazer
referência para leitura ou escrita em outro processo, sem permissão. Assim
todas as referências a endereços de memória devem ser verificados em tempo
de execução.
Compartilhamento : O mecanismo de proteção deve
ter flexibilidade para permitir que alguns processos possam acessar alguma
porção da memória principal. Por exemplo, vários processos estão executando o mesmo programa. É desejável que
estes processos possam acessar a mesma cópia do programa, ao invés de cada
processo ter a sua cópia.
Organização lógica : A memória de um sistema e computação é normalmente
organizada de forma linear, consistindo de uma sequência de bytes ou palavras.
Os programas são organizados tipicamente em módulos, alguns dos quais são read
only(somente para leitura), outros execute only (somente para execução) e
outros contém dados que podem ser modificados. Se o sistema de computação puder
lidar com estes programas e dados de forma modular, teremos as vantagens :
- módulos podem
ser escritos e compilados
independentemente, com todas as referências de um módulo para outro resolvidas
em tempo de execução
- diferentes
graus de proteção (read only, execute only) podem ser dados a diferentes
módulos
- é possível
introduzir mecanismos para compartilhar módulos entre processos.
Veremos como a técnica
de segmentação resolve essas
questões.
Organização Física : Sabemos que num sistema de
computação a memória é classificada hierárquicamente quanto à velocidade de
acesso. É tarefa do S.O. mover dados entre memória secundária e memória
principal.
I. 2 Particionamento da Memória
A principal
operação do gerenciamento de memória é levar os programas para a memória principal para que possam ser
executados. Os sistemas operacionais modernos trabalham com memória virtual, que envolve duas
técnicas básicas : paginação e segmentação. Observemos abaixo um
resumo das técnicas de partição da memória principal, inclusive as que não
envolvem memória virtual.
Partições
fixas
Memória principal
dividida em um número fixo de partições de tamanho fixo, determinados quando da
inicialização do sistema.
Vantagem :
Simples implementação; pequeno overhead do sistema operacional.
Desvantagem : Uso
ineficiente da memória, por causa da fragmentação interna, ou seja, áreas
livres de memória dentro das partições que abrigam programas menores que o
tamanho da partição na qual estão alocados.
Partições
Dinâmicas
As partições são
criadas de acordo com os tamanhos dos programas alocados.
Vantagem :
nenhuma fragmentação interna
Desvantagem :
grande overhead do sistema operacional, principalmente no que concerne à
compactação necessária para contornar a fragmentação externa, ou seja, áreas
de memória livres tão pequenas que não comportam nenhum programa.
Estratégias de alocação : first-fit : escolhe a primeira partição livre que comporte o
programa
best-fit : escolhe a partição livre cujo tamanho seja o
mais próximo possível do tamanho do programa.
worst-fit : escolhe a partição cujo
tamanho seja o maior possível
Paginação
Simples
Memória principal
é dividida em um número fixo de quadros de tamanhos iguais, chamados molduras. Cada processo é dividido em páginas do mesmo tamanho da moldura da
memória principal. Todas as páginas de cada
processo são alocadas em
molduras não necessariamente contíguas da memória principal.
Vantagem :
Nenhuma fragmentação externa.
Desvantagem : Uma
pequena fragmentação interna
Segmentação
Simples
Cada processo é
dividido logicamente em partes, de tamanho diferentes, chamados segmentos. Todas os segmentos de um
processo são alocados em partições dinâmicas, não necessariamente contíguas.
Vantagem :
nenhuma fragmentação interna
Desvantagem :
Fragmentação externa: quando as áreas livres são tão pequenas que não comportam
nenhum segmento. Overhead comparado ao da partição dinâmica.
Memória
Virtual com Paginação
Mesmo da
paginação simples, com a importante diferença que nem todas as páginas do
processo precisam estar na memória principal : as páginas dos processos são alocadas a medida que são referenciadas. Veremos
que há vários algoritmos para a retirada das páginas da memória principal, de
forma a deixar nesta as mais necessárias.
Vantagem :
nenhuma fragmentação externa; alto grau de multiprogramação ( ou multitarefa )
pois há um grande número de processos na memória principal, com um pequeno
espaço desta destinado a cada um; grande espaço de endereçamento virtual para
cada processo.
Desvantagem :
pequena fragmentação interna; overhead devido ao complexo gerenciamento de
memória
Memória
Virtual com Segmentação
Mesmo da
segmentação simples, com a importante diferença que nem todos os segmentos do
processo precisam estar na memória principal : os segmentos são alocados a medida que são referenciados. Existem
algoritmos para manter na memória os segmentos mais necessários.
Vantagem :
Nenhuma fragmentação interna; alto grau de multiprogramação ( ou multitarefa );
grande espaço de endereçamento virtual para cada processo; suporte à proteção e
compartilhamento.
Desvantagem :
Fragmentação externa; overhead do sistema operacional devido ao complexo
gerenciamento de memória, incluindo a compactação.
Memória
Virtual com Segmentação com Paginação
Mesmo da memória
virtual com segmentação, sendo que cada segmento é dividido em páginas. A
memória física é dividida em molduras, que abrigam as páginas do processo.
Vantagem :
nenhuma fragmentação externa; alto grau de multiprogramação ( ou multitarefa );
suporte à proteção e compartilhamento.
Desvantagem :
pequena fragmentação interna; overhead devido ao complexo gerenciamento de
memória.
I. 3
Endereçamento Físico versus Endereçamento Virtual
Endereço Físico : é o endereço da memória
real. É único no sistema de computação, ou seja, cada célula da memória possui um
e somente um endereço físico e a recíproca é verdadeira: cada endereço físico
refere-se a uma e somente uma célula de memória.
Endereço lógico : é uma referência a um
endereço independente da sua localização na memória real. Como vimos, na figura
relativa à imagem de um processo, o
código deste faz referência a outra parte do código quando há um desvio de
fluxo. O código também faz referência aos dados. Estas referências são feitas
através de endereços. Se o código criado for código absoluto, os endereços serão endereços físicos e este código
só pzação na memória real. Como vimos, na figura relativa à imagem de um processo, o código deste faz
referênci, os endereços ser, os
endereços serão endereços físicos e este código só pzação na memória r, os endereços serão, os endereços
serão endereços físicos e este código só pzação na memória real. Como vimos, na
figura relativa à imagem de um
processo, o código dest, os endereços serão endereços físicos e
este código só pzação na m, os endereços serão endereços físicos e este
código só pzação na memória real. Como vimos, na figura relativa à imagem de um processo, o código deste faz re(registrador
base ou registrador de relocação ) recebe o endereço físico do início
do processo. Um outro registrador recebe o endereço final do processo.
As referências
são feitas aos endereços lógicos.
Para ir buscar um
dado ou instrução na memória principal o endereço lógico é levado a um hardware
que consiste de uma unidade lógica e aritmética, do registrador de relocação e
de um registrador que contém o último endereço dedicado ao processo. Nessa
unidade é feita a soma do registrador base com o endereço lógico, obtendo assim
o endereço físico. Antes de fazer a busca na memória principal é verificado se
este endereço físico obtido encontra-se no intervalo dedicado ao processo, em
caso negativo é feita uma chamada ao sistema operacional.
PARTE II -
MEMÓRIA VIRTUAL
Memória virtual é
uma técnica sofisticada de gerenciamento de memória, cujo objetivo é aumentar a
memória principal, fazendo de uma parte do disco a continuação da memória, para
alocação do processo inteiro. Baseada no Princípio da Localidade, aloca na
memória principal somente as páginas ou segmentos do processo que forem
referenciadas. Veremos alguns algoritmos para a troca de páginas ou segmentos
da memória para o disco, cujo objetivo é manter na memória principal as páginas
ou segmentos mais utilizados.
II. 1 Princípios básicos :
Todos as
referências de memória são feitas aos endereços lógicos, que são transformados
nos endereços físicos em tempo de execução ( ver Mapeamento).
Uma página ou segmento só é alocado
na memória principal quando for referenciado (swapping in). Se não
houver mais espaço na memória principal para alocar a página ou segmento desejado,
alguma página ou segmento deverá ir para o disco ( swapping out ). Para
escolher que página ou segmento deve ser retirado, dos Algoritmos de Troca deve ser utilizado. Esta idéia tem fundamento
na observação do Princípio da Localidade.
O
Princípio da Localidade :
Localidade é a tendência que
os programas tem de fazer referências a posições de memória de forma quase
uniforme, ou seja, a instruções próximas. Isso significa que um processo
tenderá a concentrar suas referências em um mesmo conjunto de páginas durante
determinado período de tempo. Naturalmente, a forma como a aplicação foi
escrita pode aumentar ou diminuir a sua
localidade.
Por exemplo um
programa composto de 30 páginas de código e 5 páginas de dados, com um loop cujo código ocupe duas páginas e
fazendo acesso a dados que ocupem duas páginas. Durante todo o tempo de
execução deste loop, somente essas quatro páginas precisam estar na memória
principal. Essas quatro páginas não
necessariamente são alocadas em molduras contíguas da memória principal.
II . 2 SWAPPING
É uma técnica
auxiliar no gerenciamento de memória virtual.
Todo o código e dados dos processos
ficam alocados numa parte do disco, destinada especificamente para esta
finalidade ( área de swap ).
-
páginas ou segmentos que não foram referenciadas ficam em disco, sendo
somente alocadas quando forem referenciadas ( swapping in )
-
páginas ou segmentos são retiradas da memória principal ( swapping
out ), quando é necessário esvaziar uma moldura para alocar páginas ou
segmentos do mesmo processo ou de outro processo. A escolha é feita pelos
algoritmos de troca. São vários os motivos, inclusive, situações nas quais o
processo ao qual estas páginas ou segmentos pertencem estarem em estado de
espera.
- antes de uma página ou segmento
ser retirado da memória é verificado se houve modificação. Se SIM a página ou
segmento correspondente no disco deve ser ATUALIZADA.
II. 3 MAPEAMENTO
Já vimos que
apenas algumas páginas ou segmentos de um processo podem estar alocadas na
memória principal em um dado instante. E mais ! as páginas ou segmentos não
precisam estar alocadas em regiões contíguas da memória. Como isso é possível ?
Chamamos de mapeamento ao mecanismo
utilizado pelo sistema operacional para fazer a tradução do enderaço localizado
no espaço virtual para o endereço localizado no espaço físico.
Nota : Vamos fazer o estudo para páginação e depois
faremos a extensão para segmentação e paginação com segmentação
Toda a imagem do processo é criada
num espaço
de endereçamento virtual : ou seja, todos os processos criados começam
no endereço virtual zero. Se não houvesse a divisão do processo em páginas e
consequentemente o processo fosse alocado inteiro na memória principal, para
obter qualquer endereço físico, bastaria somar a cada endereço virtual o
primeiro endereço físico do processo, como já vimos anteriormente. Mas, para
utilizar a técnica da paginação, outro
mecanismo terá que ser empregado.
Se imaginássemos que cada página do
processo é um "pequeno processo", poderíamos utilizar a técnica acima
para transformar qualquer endereço virtual dentro da página no seu
correspondente endereço físico, bastando para isso somar o endereço virtual
em questão ao primeiro endereço físico da página. Assim todas as páginas
começariam no endereço virtual zero.
O mecanismo utilizado baseia-se
nesta idéia :
-
Cada processo é dividido em páginas.
-
O endereço virtual é composto do pelo número da página virtual(NPV)
e
pelo deslocamento dentro da página .
-
Cada processo possui uma
tabela, a tabela de páginas do processo, contendo :
-
os números das suas páginas,
-
um bit de validade, que indica se a página está ou não na memória
-
o endereço físico do início da página
-
um bit de modificação, que indica se a página foi ou não
modificada
- Cada página virtual possui
uma única entrada na tabela de páginas (ETP) do processo
Quando um processo é colocado em execução, além dos
registradores da CPU serem restaurados ( caso o processo já tenha entrando
antes em execução ), passa a fazer parte da troca de contexto, a gravação da tabela de páginas do processo, num
hardware específico, denominado memória
associativa ou translation lockside
buffer (TLB).
Assim,
quando a CPU faz referência a um endereço, o está fazendo a um endereço
virtual e não físico. Antes de buscar
este endereço na memória principal, este endereço virtual passa pela TLB
para fazer a transformação :
-
Como a primeira parte do endereço virtual é formada pelo NPV (número da
página virtual), com este número, é feita a entrada na tabela de páginas (ETP)
-
É verificado, através do bit de validade, se a página correspondente
está na memória. Se não estiver, é
gerada uma chamada ao sistema operacional, chamada page fault ( falha de página ),
para que este faça a alocação. O processo fica em estado de espera, até que a
página seja alocada.
-
Se a página está na memória é encontrado, o endereço físico da página.
-
A segunda parte do endereço virtual é formada pelo deslocamento dentro
da página. Somado-se este valor ao obtido no ítem anterior, obtém-se o endereço
físico correspondente ao virtual referenciado.
Agora ficou possível entender porque as páginas do processo não
precisam estar todas alocadas na memória principal ao mesmo tempo e, além disso,
as que o estão, não necessariamente ocupam molduras contíguas.
II. 4 ALGORITMOS DE TROCA
Quando uma página faz-se necessária, mas não está
alocada na memória principal, o sistema operacional deve alocá-la. Se houver
alguma moldura livre na memória principal, basta alocar nesta a página
desejada. Se não houver, o sistema operacional deverá retirar alguma página da memória
principal, para alocar a página desejada. Mas, que página o sistema operacional
escolhe para retirar ?
Há várias estratégias para retirar uma página da memória principal :
-
Aleatória : Nenhum critério é utilizado, escolhe uma
página aleatoriamente, para a retirada. Pouco overhead, pouca ineficiência,
pois todas as páginas possuem a mesma probabilidade de serem retiradas, inclusive
a que está sendo referenciada, ultimamente, com maior frequência.
-
First-in-First-out
(FIFO) : A página que primeiro foi referenciada (first-in), será a primeira a
ser escolhida para sair ( first-out). Pouco overhead, pois a implementação é
simples : consiste apenas de uma fila. Pouca eficiência pois a primeira página
a ser referenciada, pode estar sendo constantemente referenciada.
-
Least-Recently-Used
(LRU) : Seleciona a página utilizada menos recentemente, ou seja, a que está há
mais tempo sem ser refrenciada. Grande overhead, pois a cada referência, deve
haver o registro do momento desta referencia. Além disso o algoritmo de busca
também causa grande overhead.
-
Not-Recently-Used (NRU) : Semelhante ao LRU, porém com
outro tipo de implementação, cujo objetivo é diminuir o overhead : implementa-se um flag
de referência, para indicar se a página foi referenciada ou não.
Inicialmente todas as páginas estão com o flag com valor zero, indicando que
Não foram referenciadas. À medida que as páginas são referenciadas, o flag
associado a cada página é modifcado para 1. Depois de um certo tempo é possível
saber que páginas foram referenciadas ou não.
- Least-Frequently-Used ( LFU ) : Seleciona a página menos
referenciada, ou seja, a que foi referenciada com menor frequência. Neste caso,
implementa-se um contador que é incrementado a cada referência da página.
Depois de um certo tempo estão na memória as páginas mais utilizadas. A única
desvantagem é que as páginas que entrarem mais recentemente podem ser sempre
escolhidas para serem retiradas; e pode acontecer que essas páginas sejam
frequentemente utilizadas.
VALE PARA QUALQUER ESTRATÉGIA UTILIZADA
- Antes de retirar uma página
da memória principal, o sistema operacional verifica, através do bit
de modificação (dirty bit ou modify bit )
se a página foi ou não modificada. Se SIM : deve ser feita uma
cópia para o arquivo de paginação.
- Para retirar um processo da
memória principal o estado do processo e a sua prioridade são observados.
II.5 WORKING SET
Chamamos de taxa
de paginação ao número de páginas que tem que ser alocadas na memória,
para um determinado processo, por tempo de observação. Quando um processo
inicia a sua execução a taxa de paginação é alta e depois vai baixando tendendo
para um baixo valor, que deve estabilizar-se, devido ao Princípio da Localidade
e do algoritmo de troca, se for eficiente.
Dessa análise resulta o
conceito de working set, que é o conjunto de páginas constantemente
utilizadas pelo processo ao longo da sua vida ativa. Para melhor eficiência é
desejável que estas páginas permaneçam na memória principal, a fim de evitar
uma alta taxa de paginação.
Assim, passa-se a trabalhar
com mais uma cota para cada processo : working set
Quanto maior o tamanho do
working set, menor será a taxa de paginação. Entretanto, quanto maior o working
set , menor será o número de processos que poderão compartilhar a memória
principal. Para resolver este dilema, o sistema operacional pode implementar um
tamanho de working set não fixo para cada processo. Pode comparar
evolutivamente o tamanho do working set com a taxa de paginação e fixar, depois
de algum tempo o tamanho do working set para determinado processo.
II. 6 CONSIDERAÇÕES SOBRE O TAMANHO DA PÁGINA
Páginas pequenas provocam menos fragmentação interna, entretanto
resultam maiores taxas de paginação e
maiores tabelas de páginas, sendo que estas últimas provocam maior
overhead na troca de contexto.
Páginas grandes ocasionam
menor compartilhamento da memória e maior fragmentação externa.
II. 7 EXTENSÃO PARA SEGMENTAÇÃO
Neste caso, os programas são divididos de acordo com a sua
estrutura, em partes de tamanhos
desiguais entre si. O mapeamento é
semelhante ao da paginação : são criadas as tabelas de mapeamento dos segmentos (TMS ) e os endereços são
compostos pelo número do segmento e pelo deslocamento dentro do segmento. O
número do segmento indica a entrada na
tabela e segmentos (ETS). O endereço físico de qualquer referência é
calculado pela soma do endereço físico do segmento e do deslocamento dentro do
segmento.
A tabela de mapeamento dos
segmentos contém uma informação adicional : o tamanho do segmento.
A alocação é feita através
de uma das estratégias utilizadas no caso de partições dinâmicas.
Somente os segmentos
referenciados são alocados na memória principal.
Consequências : Com esta
técnica a performance do sistema depende da modularização das aplicações. Se as
aplicações não forem bem modularizadas haverá disperdício na utilização da
memória principal, ou seja, teremos partes dos segmentos sem uso, ocupando a
memória desnecessariamente.
Como no caso das partições
dinâmicas, haverá fragmentação externa.
II. 8 EXTENSÃO PARA SEGMENTAÇÃO COM PAGINAÇÃO
Esta técnica faz a divisão lógica
dos programas em segmentos. Além disso, cada segmento é dividido em páginas.
O endereço é formado pelo
número do segmento ==>entrada na
tabela de segmentos => contém informações das páginas do segmento
número da página dentro do
segmento ==> entrada na tabela de páginas => endereços físicos das páginas
deslocamento dentro da
página ==> somado ao
endereço físico da página => endereço físico
Consequências : não há
fragmentação externa.
há fragmentação interna ( normalmente
bem menor que a externa )
II. 9 PROTEÇÃO
É preciso haver um mecanismo que proteja a área de memória de cada um dos vários processos que a
compartilham e, sobretudo que proteja a área do sistema operacional.
Como descrito acima, a
técnica de memória virtual implica num mapeamento dentro do processo : o
endereço referenciado pela UCP é o endereço virtual. Através das entradas nas
tabelas das páginas/segmentos os endereços virtuais são associados aos endereços físicos que pertencem aquele
processo. Como cada processo tem a sua tabela de páginas/segmentos é impossível
que um processo faça referência à área de memória de outro processo, a menos
que haja compartilhamento explícito de páginas/segmentos entre
processos, como veremos no próximo ítem.
A proteção nos sistemas que
utilizam paginação/segmentação é feita a nível de página/segmento, através de
bits que especificam os acessos permitidos nas tabelas de mapeamento. Se o bit
de leitura ( read ) for 0, não será permitido o acesso para leitura; e o mesmo
para escrita ( write ).
II. 10 COMPARTILHAMENTO EXPLÍCITO
Código reentrante : parte de código de um processo que não pode
ser modificada e pode ser compartilhada por vários processos. Esse compartilhamento traz economia no uso
da memória. Ex : utilitários e aplicativos do sistema.
Com o uso das tabelas de
páginas/segmentos este compartilhamento é feito simplesmente através do
endereço físico. Ex : uma página que
pode ser compartilhada ( acesso somente para leitura ) pertencente ao processo
A já se encontra na memória. Um outro
processo B precisa alocar esta mesma página na memória. Não é necessário fazer
a locação, mas somente escrever o endereço físico desta página já alocada na
tabela de páginas do processo B.