Apostila Fundamentos de Sistemas Operacionais

Propaganda
Apostila da disciplina de Fundamentos
de Sistemas Operacionais
Arquitetura de Sistemas Operacionais
2010
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 0 - A EVOLUÇÃO DOS SISTEMAS OPERACIONAIS ...................................................................... 04
0.1 A Primeira Geração (1945-1955): Válvulas e Painéis com Plugs ........................................................ 04
0.2 A Segunda Geração (1955 - 1965): Transistores e Sistemas Batch .................................................... 05
0.3 A Terceira Geração (1965 - 1980): CIs e Multiprogramação .............................................................. 08
0.4 A Quarta Geração (1980-1990): Computadores Pessoais .................................................................. 11
0.5 1990/97: a Era Windows ................................................................................................................ 13
Capítulo 1 - VISÃO GERAL ........................................................................................................................ 19
1.1 Introdução ..................................................................................................................................... 19
1.2 Funções básicas ............................................................................................................................. 19
1.3 Máquina de níveis .......................................................................................................................... 20
1.4 Tipos de Sistemas Operacionais ....................................................................................................... 22
1.4.1 SOs monoprogramáveis/monotarefa ................................................................................ 22
1.4.2 SOs multiprogramáveis / multitarefa ................................................................................ 23
1.4.2.1 Sistemas Batch ............................................................................................... 25
1.4.2.2 Sistemas de Tempo compartilhado ................................................................... 25
1.4.2.3 Sistemas de Tempo Real ................................................................................. 26
1.4.3 Sistemas com Múltiplos Processadores ............................................................................. 26
1.4.3.1 Sistemas fortemente acoplados ........................................................................ 27
1.4.3.2 Sistemas fracamente acoplados ....................................................................... 28
Capítulo 2 - CONCEITOS DE HARDWARE E SOFTWARE ........................................................................... 31
2.1 Introdução ..................................................................................................................................... 31
2.2 Hardware ....................................................................................................................................... 31
2.2.1 Processador ................................................................................................................... 31
2.2.2 Memória ........................................................................................................................ 32
2.2.3 Memória Cache .............................................................................................................. 32
2.2.4 Memória Principal e Secundaria ....................................................................................... 32
2.2.5 Dispositivos e Entrada/Saída ............................................................................................ 33
2.2.6 Barramentos ou Bus ........................................................................................................ 33
2.2.7 Pipeline .......................................................................................................................... 35
Capítulo 3 - CONCORRÊNCIA .................................................................................................................... 36
3.1 Introdução ..................................................................................................................................... 36
3.2 Interrupção e Exceção .................................................................................................................... 38
3.3 Operações de Entrada/Saída ........................................................................................................... 40
3.4 Buffering ....................................................................................................................................... 42
3.5 Spooling ........................................................................................................................................ 43
3.6 Reentrância .................................................................................................................................. 43
3.7 Proteção do Sistema ....................................................................................................................... 44
Capítulo 4 - ESTRUTURA DO SISTEMA OPERACIONAL ............................................................................ 45
4.1 Introdução .................................................................................................................................... 45
4.2 Principais Funções ......................................................................................................................... 46
4.3 System Calls ................................................................................................................................. 47
4.4 Modos de Acesso .......................................................................................................................... 48
4.5 Arquitetura Monolítica ................................................................................................................... 51
4.6 Arquitetura de Camadas ................................................................................................................ 52
4.7 Máquina Virtual ............................................................................................................................ 53
4.8 Arquitetura Microkernel ................................................................................................................. 55
4.9 Projeto do Sistema ...................................................................................................................... 57
Capítulo 5 - PROCESSO ............................................................................................................................. 58
5.1 Introdução ..................................................................................................................................... 58
5.2 Estrutura do Processo ................................................................................................................... 58
5.2.1 Contexto de hardware .................................................................................................... 59
5.2.2 Contexto de software .................................................................................................... 60
5.2.3 Espaço de endereçamento ............................................................................................. 62
5.2.4 Bloco de controle do processo ........................................................................................ 62
5.3 Estados do Processo ....................................................................................................................... 63
5.4 Mudanças de Estado de Processo ....................................................................................................64
5.5 Criação e Eliminação de Processos .................................................................................................. 66
5.6 Processos Independentes, Subprocessos e Threads ......................................................................... 68
2
Apostila Fundamentos de Sistemas Operacionais
.
5.7 Processos Foreground e Background ............................................................................................... 70
5.8 Processos do Sistema Operacional .................................................................................................. 71
5.9 Processos CPU-Bound e I/O-Bound ................................................................................................ 72
5.10 Sinais ....................................................................................................................................... 73
Capítulo 6 – THREAD ................................................................................................................................ 75
6.1 Introdução ..................................................................................................................................... 75
6.2 Ambiente Monothread .................................................................................................................... 75
6.3 Ambiente Multithread ..................................................................................................................... 77
6.4 Arquitetura e Implementação ......................................................................................................... 82
6.4.1 Threads em Modo Usuário ............................................................................................. 82
6.4.2 Threads em Modo Kernel ............................................................................................... 84
6.4.3 Threads em Modo Híbrido ............................................................................................. 85
6.4.4 Scheduler Activations ..................................................................................................... 86
6.5 Modelos de Programação ................................................................................................................ 87
Capítulo 7 - Sincronização e Comunicação entre processos .................................................................. 88
7.1 Introdução ..................................................................................................................................... 88
7.2 Aplicações Concorrentes ............................................................................................................... 88
7.3 Especificação de Concorrência em Programas .................................................................................. 89
7.4 Problemas de Compartilhamento de Recursos ................................................................................... 91
7.5 Exclusão Mútua ............................................................................................................................. 93
7.5.A Starvation ................................................................................................................... 93
7.5.B Sincronização condicional .............................................................................................. 94
7.5.1 Soluções de Hardware ................................................................................................... 94
7.5.2 Soluções de software ...................................................................................................... 95
7.6 Semáforos .................................................................................................................................... 95
7.7 Monitores ...................................................................................................................................... 97
7.8 Troca de mensagens ..................................................................................................................... 98
7.9 Deadlock ....................................................................................................................................... 99
7.9.1 Prevenção do Deadlock ................................................................................................ 100
7.9.2 Detecção de Deadlock ................................................................................................... 100
7.9.3 Correção do Deadlock ............................................................................................... 100
Capítulo 8 - Gerência do Processador ................................................................................................... 102
8.1 Funções ................................................................................................................................ 102
8.2 Critérios de escalonamento ...................................................................................................... 102
8.3 Escalonamentos Não-Preemptivos e Preemptivos ........................................................................ 103
Capítulo 9 - Gerência de Memória / Memória Virtual .......................................................................... 107
9.1
Introdução ....................................................................................................................... 107
9.2
Funções ........................................................................................................................... 107
9.3
Alocação Contígua Simples ................................................................................................. 108
9.4
Segmentação de Programas ............................................................................................... 109
9.5
Alocação Particionada Estática ............................................................................................ 110
9.6
Alocação Particionada Dinâmica ........................................................................................... 111
9.7
Estratégias de Alocação de Partição ..................................................................................... 112
9.8
Swapping ......................................................................................................................... 113
9.9
Memória Virtual ................................................................................................................ 113
9.10
Algoritmos de substituição de páginas .................................................................................. 116
Capítulo 10 - Gerência de Sistemas de Arquivos .................................................................................. 118
10.1
Estrutura de Diretórios ..................................................................................................... 118
10.2
Sistemas de alocação de arquivos ...................................................................................... 118
10.3
Gerência de espaço livre ................................................................................................... 119
10.4
Proteção de acesso ............................................................................................................ 120
Bibliografia ............................................................................................................................................. 121
3
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 0
A EVOLUÇÃO DOS SISTEMAS OPERACIONAIS
Os sistemas operacionais têm sido historicamente amarrados à
arquitetura dos computadores nos quais iriam rodar. Por isso, veremos como eles
evoluiram nas sucessivas gerações de computadores. Esse mapeamento entre gerações
de computadores e gerações de sistemas operacionais é admissivelmente imaturo, mas
tem algum sentido.
O primeiro computador digital verdadeiro foi projetado pelo matemático
inglês Charles Babbage (1792-1871). Embora Babbage tenha dispendido muito de sua
vida e de sua fortuna tentando construir sua "máquina analítica", ele jamais conseguiu
por o seu projeto em funcionamento porque era simplesmente um modelo matemático e
a tecnologia da época não era capaz de produzir rodas, engrenagens, dentes e outras
partes mecânicas para a alta precisão que necessitava. Desnecessário se dizer que a
máquina analítica não teve um sistema operacional.
0.1 - A Primeira Geração (1945-1955): Válvulas e Painéis com Plugs
Após os esforços sem sucesso de Babbage, pouco progresso se teve na
construção de computadores digitais até a Segunda Guerra Mundial. Em torno de 1940,
Howard Aiken em Harvard, John Von Neumann no Instituto para Estudos Avançados em
Princeton, John Presper Eckert e William Mauchley na Universidade de Pennsylvania e
Konrad Zuse na Alemanha, entre outros, tiveram sucesso na construção de máquinas
calculadoras usando válvulas. Essas máquinas eram enormes, ocupando salas
completas, com dezenas de milhares de válvulas, porém eram muito mais lentas do que
os mais simples computadores pessoais de hoje.
Naqueles dias primitivos, um pequeno grupo de pessoas construiu,
programou, operou e deu manutenção a cada máquina. Toda a programação era feita
em linguagem de máquina, sempre se conectando fios com plugs em painéis para
controlar as funções básicas da máquina. As linguagens de programação não eram
conhecidas (nem a linguagem Assembly). Nem se ouvia falar em sistemas operacionais.
O modo usual de operação consistia no programador elaborar o programa numa folha e
então ir à sala da máquina, inserir os plugs nos painéis do computador e gastar as
próximas horas apelando que nenhuma das 20.000 ou mais válvulas não se queimasse
durante a execução do programa. Na verdade, todos os problemas eram inerentemente
sobre cálculos numéricos tais como gerações de tabelas de senos e cossenos.
Por volta dos anos 50, essa rotina teve uma pequena evolução com a
introdução de cartões perfurados. Era possível, a partir de então, se escrever programas
em cartões e lê-los, em vez do uso de plugs em painéis; no mais, o procedimento era o
mesmo.
4
Apostila Fundamentos de Sistemas Operacionais
.
0.2 - A Segunda Geração (1955 - 1965): Transistores e Sistemas Batch
A introdução do transistor em meados dos anos 50 mudou o quadro radicalmente.
Os computadores tornaram-se bastante confiáveis para que pudessem ser produzidos e
vendidos comercialmente na expectativa de que eles continuassem a funcionar por
bastante tempo para realizar algumas tarefas usuais. A princípio havia uma clara
separação entre projetistas, construtores, operadores, programadores e o pessoal de
manutenção.
Essas máquinas eram alocadas em salas especialmente preparadas com
refrigeração e com apoio de operadores profissionais. Apenas grandes companhias,
agências governamentais, ou universidades, dispunham de condições para pagar um
preço de multimilhões de dólares por essas máquinas. Para rodar um job (isto é, um
programa ou um conjunto de programas), primeiro o programador escrevia o programa
no papel (em FORTRAN ou linguagem Assembly), e então perfurava-o em cartões. Daí,
ele levava o "deck" de cartões à sala de recepção e o entregava a um dos operadores.
Quando o computador encerrava a execução de um job, um operador apanhava
a saída na impressora, a conduzia de volta à sala de recepção onde o programador
poderia coletá-lo posteriormente. Então ele tomava um dos decks de cartões que tinha
sido trazido da sala de recepção e produzia a sua leitura. Se o compilador FORTRAN era
necessário, o operador tinha que pegá-lo de uma sala de arquivos e produzir a sua
leitura. Muito tempo de computador era desperdiçado enquanto os operadores
caminhavam pela sala da máquina para realizarem essas tarefas.
Devido ao alto custo do equipamento, era de se esperar que as pessoas
tentassem reduzir o tempo desperdiçado. A solução geralmente adotada era o sistema
em "batch". A idéia original era colecionar uma bandeja completa de jobs na sala de
recepção e então lê-los para uma fita magnética usando um computador pequeno e
relativamente barato, por exemplo o IBM 1401, que era muito bom na leitura de cartões,
na cópia de fitas e na impressão da saída, porém não era tão bom em cálculo numérico.
Outros computadores, máquinas mais caras, tais como o IBM 7094, eram usados para a
computação real. Essa situação é mostrada na figura 0.1.
5
Apostila Fundamentos de Sistemas Operacionais
Unidade
.
Entrada
Sistema
da Fita
de Fitas
de Fita
Saída
de Fita
Leitora de
Impressora
cartões
1401
(a)
(b)
7094
(c)
(d)
1401
(e)
(f)
Figura 0.1 - Um sistema “batch” antigo.
( a ) Programadores levam cartões ao 1401.
( b ) 1401 lê batch de jobs em fita.
( c ) A operadora acopla fita de entrada no 7094.
( d ) O 7094 faz o processamento.
( e ) A operadora acopla fita de saída no 1401.
( f ) O 1401 imprime a saída.
Após cerca de uma hora coletando-se um lote de jobs, a fita era
rebobinada e levada para a sala da máquina onde era montada numa unidade de fita. O
operador então carregava um programa especial (o antecessor do sistema operacional
de hoje), que lia o primeiro job da fita e o executava. A saída era escrita numa segunda
fita, em vez de ser impressa. Após o fim da execução de cada job, o sistema operacional
automaticamente lia o próximo job da fita e começava a executá-lo. Quando todo o
"batch" era feito, o operador removia as fitas de entrada e de saída, substituia a fita de
entrada pelo próximo "batch" e levava a fita de saída para um 1401 produzir a
impressão "off-line" (isto é, não conectada ao computador principal).
A estrutura de um job de entrada típico é mostrada na figura 0.2. Ele
começa com um cartão $JOB, especificando o tempo máximo de execução em minutos,
o número da conta e o nome do programador. A seguir vinha um cartão $FORTRAN,
avisando ao sistema operacional para carregar o compilador FORTRAN da fita do
sistema. Em seguida vinha um programa a ser compilado, acompanhado de um cartão
$LOAD, informando ao sistema operacional para carregar o programa objeto já
compilado. (Programas compilados eram sempre escritos em fitas selecionadas e tinham
6
Apostila Fundamentos de Sistemas Operacionais
.
de ser carregadas explicitamente). A seguir vinha um cartão $RUN, informando ao
sistema operacional para executar o programa com os dados que vinham a seguir.
Finalmente o cartão $END marcava o fim do job. Esses cartões de controle foram os
precurssores das linguagens de controle de job (JCL) modernas e de interpretadores de
comandos.
Muitos computadores da segunda geração foram usados principalmente
para cálculos científicos e de engenharia, tais como em solução de equações diferenciais
parciais. Eles foram vastamente programados em FORTRAN e em linguagem Assembly.
Sistemas operacionais típicos eram o FMS (Sistema Monitor FORTRAN) e IBSYS (Sistema
Operacional da IBM para o 7094).
$END
Dados para o Programa
$RUN
$LOAD
Programa Fortran
$FORTRAN
$JOB, 10, 429754, TANENBAUM
Figura 0.2 - Estrutura de um típico job FMS
7
Apostila Fundamentos de Sistemas Operacionais
.
0.3 - A Terceira Geração (1965 - 1980): CIs e Multiprogramação
Nos anos 60, muitos fabricantes de computadores tinham duas linhas de
produto distintas e totalmente incompatíveis. Por um lado havia os computadores
científicos, em grande escala, orientado por palavras, tais como o 7094, que era usado
para cálculos numéricos em ciência e engenharia. Por outro lado, havia os computadores
comerciais, orientados por caracter, tais como o 1401, que era vastamente usado para
classificação em fita e impressão, por bancos e companhias de seguros.
O desenvolvimento e a manutenção de duas linhas de produto
completamente diferentes era uma proposta cara para os fabricantes. Além do mais, os
clientes em potencial para aquisição de novos computadores necessitavam inicialmente
de uma máquina pequena, para mais tarde, com o crescimento, terem uma máquina
maior em que pudessem rodar todos os seus programas mais rapidamente.
A IBM, no intuito de resolver ambos os problemas de uma só tacada,
introduziu o sistema /360. O 360 era uma série de máquinas compatíveis por software,
variando de tamanho a partir do 1401 até o mais potente 7094. As máquinas diferiam
apenas em preço e performance (capacidade de memória, velocidade do processador,
número de periféricos I/O permitidos, e assim por diante). Já que todas as máquinas
tinham a mesma arquitetura e o mesmo conjunto de instruções, pelo menos em teoria,
programas escritos para uma máquina poderiam rodar em todas as outras. Além disso, o
360 foi projetado para manusear tanto computação comercial como computação
científica. Assim, uma única família de máquinas poderia satisfazer às necessidades de
todos os clientes. Em anos subsequentes, a IBM apresentou os sucessores compatíveis
com a linha 360, usando uma tecnologia mais moderna, conhecidos como séries 370,
4300, 3080 e 3090.
O 360 foi a primeira linha de computadores a usar (em pequena escala)
circuitos integrados (CIs), fornecendo uma maior vantagem em preço/performance
sobre as máquinas da segunda geração, que eram construidas de transistores
individuais. Isso foi um sucesso imediato e a idéia de uma família de computadores
compatíveis foi logo adotada por todos os outros fabricantes. Os descendentes dessas
máquinas ainda hoje estão em uso em grandes centros de computação.
A maior força da idéia de "uma família" foi simultaneamente a sua maior
durabilidade. A intenção era que todo o software, incluindo o sistema operacional,
deveria trabalhar em todos os modelos. Ele tinha de rodar em sistemas pequenos que
muitas vezes já substituia 1401s para cópias de cartões em fitas e em sistemas muito
grandes, que muitas vezes substituia 7094s para fazer cálculos demorados e outras
computações pesadas. Ele deveria ser bom em sistemas com poucos periféricos e em
sistemas com muitos periféricos. Ele tinha de trabalhar em ambientes comerciais e em
ambientes científicos. Acima de tudo, ele tinha de ser eficiente em todos esses usos
diferentes.
8
Apostila Fundamentos de Sistemas Operacionais
.
Não havia uma maneira através da qual a IBM (ou outra companhia)
pudesse solucionar todas essas exigências conflitantes. O resultado foi um sistema
operacional enorme e extraordinariamente complexo, provavelmente de dois ou três
ordens de magnitude maior do que o FMS. Ele consistia de milhares de linhas de
linguagem assembly escritas por centenas de programadores e continha centenas e
centenas de depurações que necessitavam de contínuas versões a fim de corrigí-los.
Cada nova versão fixava algumas depurações e introduzia outras novas, tal que o
número de depurações provavelmente permanecia constante com o tempo.
A despeito de seu enorme tamanho e de seus problemas, o OS/360 e os
sistemas operacionais similares da terceira geração, produzidos por outros fabricantes,
satisfizeram razoavelmente bem a seus clientes. Eles também popularizaram várias
técnicas ausentes nos sistemas operacionais da segunda geração. Provavelmente, a mais
importante dessas técnicas foi a multiprogramação. No 7094, quando o job que estava
sendo executado tinha uma pausa esperando que uma operação em fita ou em qualquer
outro periférico I/O fosse completada, a CPU simplesmente ficava ociosa até que a
operação I/O fosse encerrada. Em cálculos científicos pesados, as operações de I/O não
são frequentes, e essse tempo ocioso é insignificante. Em processamento de dados
comerciais, as operações de I/O consomem frequentemente entre 80 a 90 porcento do
tempo total, exigindo alguma providência sobre isso.
A solução foi particionar a memória em várias partes, com um job
diferente em cada partição, como mostrado na Fig. 3. Enquanto um job estava
esperando que uma operação I/O fosse concluida, um outro job poderia usar a CPU. Se
vários jobs pudessem ocupar a memória no mesmo instante, a CPU estaria sempre
ocupada quase que em 100% do tempo. Ter múltiplos jobs na memória, por sua vez,
requer hardware especial para proteger cada job contra danos e entrelaçamento entre
eles, e o 360 e outros sistemas da terceira geração eram equipados com esse hardware.
Job 3
Job 2
Partições da Memória
Job 1
Sistema
Operacional
Figura 0.3 - Um sistema de multiprogramação com três jobs na memória
9
Apostila Fundamentos de Sistemas Operacionais
.
Um outro grande aspecto presente nos sistemas operacionais da terceira
geração era a habilidade de ler jobs de cartões para o disco assim que eles eram
trazidos à sala do computador. Assim, sempre que um job tinha a sua execução
encerrada, o sistema operacional poderia carregar um novo job do disco numa nova
partição vazia e executá-lo. Essa técnica é chamada de "spooling" (de "Simultaneous
Perifheral Operation On Line") e também era usada para a saída. Com o "spooling", os
1401s não precisavam ser tão grandes e a utilização da fita diminuiu bastante.
Apesar dos sistemas operacionais da terceira geração terem sido bem
apropriados para a execução de programas envolvendo grandes cálculos científicos e de
processamento de dados comerciais compactos, eles eram ainda, basicamente, sistemas
em "batch". Muitos programadores sentiam saudades dos dias da primeira geração,
quando eles tinham a máquina toda para eles por poucas horas, mas de tal forma que
eles depuravam os seus programas rapidamente. Com os sistemas da terceira geração,
o tempo entre a submissão do job e a obtenção da saída era frequentemente de várias
horas, a ponto da ausência de uma única vírgula causar uma falha na compilação e o
programador desperdiçava quase um dia.
A vontade de ter um tempo de resposta menor abriu espaço para "timesharing", uma variante da multiprogramação, em que cada usuário tem um terminal "online". Num sistema "time-sharing", se 20 usuários estão conectados e 17 deles estão
pensando, falando ou tomando café, a CPU pode ser alocada para os três jobs que
querem serviço. Como as pessoas que depuram programas usualmente editam poucos
comandos (como compilar um programa de cinco páginas) em vez de programas longos
(como classificar mil registros em fita), o computador pode fornecer mais rápido, serviço
interativo a um número maior de usuários e talvez também trabalhar com grandes jobs
em "batch" paralelamente, enquanto a CPU está, por outro lado, ociosa. Embora a
primeira série de sistemas em time-sharing (CTSS) foi desenvolvido no MIT num IBM
7094 especialmente modificado, ele não se tornou verdadeiramente popular até que a
necessidade de proteção de hardware ficasse mais difundida durante a terceira geração.
Após o sucesso do sistema CTSS, o MIT, o Laboratório Bell e a General
Electric (então o maior fabricante de computadores) decidiram embarcar no
desenvolvimento de um "computador utilitário", uma máquina que suportasse milhares
de usuários em "time-sharing" simultaneamente. O seu modelo era baseado no sistema
de distribuição de eletricidade - quando voce precisa de eletricidade, basta por um plug
na tomada da parede e a quantidade que voce precise, terá. Os projetistas desse
sistema, conhecido como MULTICS (MULTiplexed Information and Computing Service),
tinham em mente uma grande máquina que fornecesse serviço de computação para
todos em Boston. A idéia de que máquinas tão poderosas quanto o GE44 seriam
vendidas como computadores pessoais por alguns milhares de dólares apenas vinte anos
mais tarde era, naquela época, pura ficção científica. Para resumir, o MULTICS
introduziu muitas idéias inovadoras na literatura da computação, mas a sua construção
foi mais difícil do que se esperava. O Laboratório Bell saiu do projeto e a General Electric
continuou sozinha. Eventualmente o MULTICS rodava o suficientemente bem para ser
usado num ambiente de produção no MIT e em poucas outros lugares, mas a idéia de
10
Apostila Fundamentos de Sistemas Operacionais
.
um computador utilitário falhou. Mesmo assim, o MULTICS teve uma enorme influência
nos sistemas subsequentes.
Outro importante desenvolvimento durante a terceira geração foi o
crescimento fenomenal de mini-computadores, começando com o DEC PDP-1 em 1961.
O PDP-1 tinha apenas 4 K palavras de 18 bits mas a um custo de 120.000 dólares por
máquina (menos que 5% do preço de um 7094) eles vendiam como bolinhos. Para
certos tipos de trabalhos não-numéricos era quase tão rápido quanto o 7094 e fez surgir
uma nova indústria. Foi rapidamente seguido por uma série de outros PDPs (que
diferentes da família IBM, eram todos incompatíveis) culminando com o PDP-11.
Um dos cientistas do Laboratório Bell que trabalhou no MULTICS, Ken
Thompson, logo depois encontrou um pequeno PDP-7 que ninguém usava e começou a
escrever uma versão simplificada mono-usuário do MULTICS. Brian Kernighan apelidou
esse sistema de UNICS (UNiplexed Information and Computing Service), mas sua grafia
foi mais tarde trocada para UNIX. Posteriormente foi levado para um PDP-11/20, onde
funcionou bem o bastante para convencer a gerência do Laboratório Bell em investir no
PDP-11/45 para continuar o trabalho.
Outro cientista do Laboratório Bell, Dennis Ritchie, juntou-se a Thompson
para reescrever o sistema numa linguagem de alto nível chamada C, projetada e
implementada por Ritchie. O Laboratorio Bell licensiava o UNIX para Universidades quase
de graça e dentro de poucos anos, centenas delas estavam usando-o. O UNIX logo
estendeu-se para o Interdata 7/32, para o VAX, para o MOTOROLA 68000, e para
muitos outros computadores. O UNIX tinha sido transportado para mais
computadores do que qualquer outro sistema operacional da história e seu uso está
ainda aumentando rapidamente.
0.4 - A Quarta Geração (1980-1990): Computadores Pessoais
Com o desenvolvimento de circuitos LSI (Large Scale Integration), chips
contendo milhares de transistores em um centimetro quadrado de silício, a era do
computador pessoal começava. Em termos de arquitetura, os computadores pessoais
não eram diferentes de minicomputadores da classe do PDP-11, mas em termos de
preço eles eram certamente bem diferentes. Enquanto o minicomputador tornou possível
um departamento de uma companhia ou uma universidade ter o seu próprio
computador, o chip micropocessador tornou possível um indivíduo ter o seu próprio
computador.
A grande variedade de capacidade computacional disponível,
especialmente a capacidade de computação altamente interativa com excelentes
facilidades gráficas, fizeram crescer a indústria de produção de software para
computadores pessoais. Muitos desses softwares eram "amigáveis ao usuário",
significando que eles foram projetados para usuários que não tinham conhecimento
11
Apostila Fundamentos de Sistemas Operacionais
.
algum sobre computadores e além do mais não tinha outra intenção a não ser a de
orientá-los no uso. Essa foi certamente a maior mudança do OS/360, cujo JCL era tão
complexo que livros inteiros foram escritos sobre ele.
Dois sistemas operacionais dominaram a utilização do computador
pessoal: o MS-DOS, escrito pela Microsoft para o IBM PC e para outras máquinas que
usavam a CPU Intel 8088 e seus sucessores, e UNIX, que é predominante em máquinas
que usam a CPU da família Motorola 68000. Pode parecer irônico que o descendente
direto do MULTICS, projetado para o gigante computador utilitário, ficou tão popular em
computadores pessoais, mas principalmente mostra como foram boas as idéias sobre o
MULTICS e o UNIX. Apesar da primeira versão do MS-DOS ser primitiva, em versões
subsequentes foram incluidas diversas facilidades do UNIX, o que não é tão
surpreendente já que a Microsoft é um dos maiores fornecedores do UNIX, usando o
nome comercial XENIX.
Um interessante desenvolvimento que começou em meados dos anos 80
foi o crescimento de redes de computadores pessoais rodando sistemas operacionais
para rede e sistemas operacionais distribuidos. Num sistema operacional para rede, os
usuários têm consciência da existência de múltiplos computadores e podem se conectar
com máquinas remotas e copiar arquivos de uma máquina para outra. Cada máquina
roda o seu próprio sistema operacional local e tem o seu próprio usuário (ou usuários).
Um sistema operacional distribuido, em contraste, aparece para o usuário
como um sistema tradicional de um único processador, mesmo sendo composto
realmente de múltiplos processadores. Num verdadeiro sistema distribuido, os usuários
não têm consciência de onde os seus programas estão sendo rodados ou onde seus
arquivos estão localizados; tudo é manuseado automática e eficientemente pelo sistema
operacional.
Os sistemas operacionais em rede não são fundamentalmente diferentes
dos sistemas operacionais de um único processador. Eles obviamente necessitam de um
controlador de interface de rede e de algum software de alto nível para gerenciá-lo, bem
como de programas para concluir com êxito uma conexão remota e o acesso a arquivos
remotos, mas essas adições não mudam a estrutura essencial do sistema operacional.
Os sistemas operacionais distribuidos requerem mais do que a adição de
códigos a um sistema operacional de um processador porque sistemas distribuidos e
centralizados diferem em modos críticos. Sistemas distribuidos, por exemplo,
frequentemente admitem rodar programas em vários processadores ao mesmo tempo, e
daí exigem algorítmos de escalonamento de processadores para otimimizar a quantidade
de paralelismo que deve ser concluído com êxito.
O atraso de comunicação em uma rede frequentemente significa que
esses (e outros) algorítmos devem rodar com informação incompleta, desatualizada ou
às vezes incorreta. Essa situação é radicalmente diferente de um sistema de um único
processador no qual o sistema operacional tem a informação completa sobre o estado
do sistema.
12
Apostila Fundamentos de Sistemas Operacionais
.
Tolerância a falhas é uma outra área em que os sistemas distribuidos são
diferentes. É comum para um sistema distribuido ser projetado com a expectativa de
que continuará rodando mesmo que parte do hardware deixe de funcionar.
Desnecessário se dizer que uma exigência adicional ao projeto tem enormes implicações
para o sistema operacional.
0.5 A Era Windows (1990/97)
Se o mundo da computação estava procurando por um novo padrão ou
não, ele encontrou um em maio de 1990, quando a Microsoft finalmente lançou o
Windows 3.0.
O Windows 3.0 era executado sobre o DOS e, portanto, oferecia
compatibilidade com os programas DOS. Ele se beneficiava do processador 386,
podendo fazer a multitarefa com programas DOS e também com programas Windows.
A interface com o usuário foi projetada para se parecer com o Presentation Manager,
trazendo um Gerenciador de Programas baseado em ícones e um Gerenciador de
Arquivos em estilo árvore, incluindo avanços como ícones sombreados. Embora o
Windows 3.0 tenha exigido revisões mínimas de praticamente todos os programas
Windows existentes na época, não havia muito a ser revisado. Além do mais,
imediatamente após a introdução do Windows 3.0, começaram a aparecer os aplicativos,
liderados pela divisão de aplicativos da própria Microsoft e seguidos por praticamente
todos os outros grandes desenvolvedores. Mesmo depois do anúncio do Windows 3.0, a
Microsoft e a IBM continuavam falando sobre o OS/2 e, especialmente, sobre o OS/2
2.0, a primeira versão 32 bits real que viria a aparecer, finalmente, em 1992.
Para contundir ainda mais as coisas, enquanto a IBM posicionava o
OS/2 como o futuro sistema operacional para todos os usuários, a Microsoft posicionava
o OS/2 como um topo de linha, apenas para os aplicativos missão crítica e baseados em
servidor. Em vez disto, a Microsoft começou a falar sobre o OS/2 3.0
(não confundir
com o posterior IBM OS/2 Warp 3.0), que adicionaria segurança e suporte avançados a
multiprocessador, sendo capaz de executar aplicativos Windows e Posix diretamente.
Neste cenário, o Windows NT era o núcleo sobre o qual se apoiariam o DOS, o Windows,
o OS/2 e o Posix.
As duas companhias finalmente separaram suas estratégias no início de
1991, com Jim Cannavino, da IBM, e Bill Gates, da Microsoft, brigando como um casal
durante um divórcio litigioso. O OS/2 conquistou um forte nicho em algumas grandes
aplicações corporativas, auxiliado por sua estabilidade e robustez, comparadas ao
Windows 3.x. Mais tarde, a IBM faria uma última tentativa de fazer do OS/2 o principal
sistema operacional com seu OS/2 Warp 3.0, mais orientado ao consumidor comum e
lançado no final de 1994. Ele venderia milhões de cópias mas não diminuiria a grande
inclinação da indústria pelo Windows.
13
Apostila Fundamentos de Sistemas Operacionais
.
A Microsoft viria a transformar seu antigo "OS/2 3.0" no Windows NT 3. 1, que foi
lançado em 1993 sem o suporte gráfico ao OS/2 e recebido, inicialmente, como um
sistema operacional para servidores de aplicativos, concorrendo, principalmente, com o
OS/2 da IBM.
Para a maioria dos usuários de PCs, a Microsoft ofereceu o Wlndows 3.1 avançado
no final de 1991, que adicionava uma melhor integração de aplicativos, recursos
arrastar-e-soltar e uma maior estabilidade. No início dos anos 90, ele se tornou o
padrão dominante para os aplicativos para PC e a Microsoft ocupou o papel de líder na
definição das especificações multimídia.
A Microsoft viria a dominar muitas áreas mais na computação por esta
mesma época.
Seus produtos Visual Basic e Visual C++ venceram a grande
concorrência da Borland no domínio de linguagens de programação. Além disto, os
aplicativos Microsoft - liderados pelo pacote Office, contendo o Word, o Excel, o
PowerPoint e, mais tarde, o Access tomaram grande parte do mercado de programas
aplicativos (o que foi auxiliado, em parte, pelos atrasos nas versões do Lotus 1-2-3,
WordPerfect e DBASE para Windows, sendo que este último foi adquirido pela Borland).
Neste período, o Macintosh, da Apple, continuava a crescer e
expandir-se e encontrou nichos nas artes gráficas, na multimídia e na educação. Mas,
na maioria das empresas e órgãos governamentais, o principal sistema comercial era
aquele que seguia os padrões do PC original. Àquela época, o termo compatível com IBM
já tinha saído de moda, para ser substituído pelo Processador como a principal peça
descritiva de hardware.
A era do 286 já havia terminado no final de 1988, após a introdução do
386SX da Intel, um Processador que possuía os componentes internos de 32 bits do 386
e um barramento de dados 16 bits como o 286, o que o tornava barato. Este e o 386
original rebatizado como 386DX dominaram as vendas de computadores durante anos.
Em abril de 1989, a Intel apareceu com seus processadores 486. Com 1,2 milhões de
transistores, o 486 era, efetivamente, uma versão mais rápida e mais refinada do 386
somada a um co-processador matemático que executava todos os aplicativos escritos
para o 386 sem quaisquer problemas.
Desta vez, ninguém esperou pela IBM ou pela Compaq. Dezenas de
desenvolvedores se apressaram para tornar disponíveis suas máquinas 486 o mais
rápido possível após a introdução da Intel, e estas máquinas tinham uma velocidade de
execução 50 vezes maior que o IBM PC original.
A Intel introduziu seu Processador Pentium de 60 MHz em março de
1993, mas não eram apenas os processadores que continuavam a avançar. Os discos
rígidos ficavam cada vez maiores e mais velozes. E a tecnologia de exibição gráfica
progrediu das placas de vídeo de "buffer de quadro" para as aceleradores gráficas, que
trabalhavam diretamente com o Windows a fim de aumentar os tempos de resposta de
tela e melhorar os gráficos em geral.
14
Apostila Fundamentos de Sistemas Operacionais
.
Neste período, as redes locais corporativas realmente começaram a decolar. A
IBM promovia, então, o Office Vision, que deveria ser executado em todas as
plataformas SAA, inclusive sobre o OS/2. E praticamente todos os gigantes do
Desenvolvimento de sistemas tinham suas estratégias multiplataforma para a automação
de escritórios, como o All-In-One da DEC. Quase todos fracassariam dentro de um
espaço de tempo relativamente curto. Quem realmente alcançou o sucesso foram os
servidores de PC, que abrigavam seus próprios dados e podiam fazer ligações com
grandes bases de dados corporativas. No fronte do hardware, o Compaq Systempro,
introduzido em 1989, liderava os grandes aplicativos que antes viviam em
minicomputadores e outros grandes sistemas. No lado do software, chegava ao
mercado o SQL, e companhias como a Oracle e a Sybase começavam a ter como alvos
os desenvolvedores para PC. As ferramentas de desenvolvimento rápido de aplicativos,
ou RAD, logo facilitaram a criação de boas interfaces com o usuário para o acesso a
dados corporativos.
O correio eletrônico (email) é aceito no dia-a-dia das corporações
com produtos, como o cc:Mail, mais tarde adquirido pela Lotus, e mais um punhado de
concorrentes menores. Em dezembro de 1989, a Lotus mudou a fórmula com o Lotus
Notes, o primeiro aplicativo de "groupware".
Em 1994, a Microsoft e a Intel já vestiam o manto da liderança na
indústria do PC, o Windows tinha-se estabelecido como o padrão para aplicativos e as
redes estavam definitivamente no mercado comum.
No começo de 1995, poderíamos esperar que novos sistemas
operacionais da Microsoft e novos chips da Intel continuassem sendo o carro-chefe da
computação ainda por muitos anos, levando-se em conta o histórico dos anos anteriores.
Eles ainda são importantes, mas talvez a mudança mais importante destes últimos anos
tenha vindo de um grupo de estudantes da Universidade de Illinois. Foi lá que, no início
de 1993, Marc Andreessen, Eric Bina e outros que trabalhavam para o National Center
for Supercomputing Applications (NCSA) apareceram com o Mosaic, uma ferramenta que
seria utilizada para paginar a Internet.
A Internet, é claro, já existia há muitos anos, datando do início dos
anos 60, quando o órgão de Defesa de Projetos de Pesquisa Avançada (DARPA) do
Pentágono estabeleceu as conexões com muitos computadores de universidades.
Enquanto a Internet crescia, o governo transferiu seu controle para os sites individuais e
comitês técnicos. E, em 1990, Tim Berners-Lee, então no laboratório de física CERN,
em Genebra, Suíça, criou a Linguagem de Marcação de Hipertexto (HTML), uma maneira
simples de ligar informações entre sites da Internet. Isto, por sua vez, gerou a World
Wide Web (www), que apenas aguardava por um paginador gráfico para começar a
crescer.
Após o lançamento do Mosaic ao público, no final de 1993,
repentinamente, a Internet - e, em particular, a Web - podiam ser acessadas por
qualquer pessoa que tivesse um computador pessoal, fato auxiliado, em parte, nela
possibilidade de transferir livremente a versão mais recente de vários paginadores
15
Apostila Fundamentos de Sistemas Operacionais
.
diferentes. E, dentro de pouco tempo, parecia que todo o mundo - e todas as
companhias - estava inaugurando seu site na Web.
Novas versões de paginadores da Web também chegaram
rapidamente. A Netscape Corp. - uma nova companhia formada por Andreessen e Jim
Clark, que havia sido um dos fundadores da Silicon Graphics - logo começou a dominar o
ramo de paginadores Web. O Netscape Navigator acrescentou vários recursos, inclusive
o suporte a extensões (o que, por sua vez, levou a diversas extensões multimídia) e a
máquina virtual Java (que permitia aos desenvolvedores elaborar aplicativos Java que
podiam ser executados dentro do paginador).
A tremenda empolgação ocasionada pela explosão da World Wide
Web chegou perto de eclipsar o maior anúncio da Microsoft neste período: o Windows
95. Introduzido em agosto de 1995, a estréia do software foi acompanhada por um
entusiasmo maior do que qualquer outro anúncio de computação da era.
O Windows 95 era a versão do Windows pela qual muitos usuários
estiveram esperando. Ele permitia a utilização de aplicativos totalmente 32 bits, tinha a
multitarefa preemptiva, era compatível com Plug-and-Play, suportava novos padrões de
e-mail e comunicações e, logicarnente, trazia uma nova interface com o usuário. Na
verdade, muitos usuários pensavam que a nova interface, que incluía um menu "Iniciar"
e uma área de trabalho de programas com pastas e ícones, deixaria o Windows muito
mais próximo do projeto Lisa original ou do Macintosh de dez anos atrás.
A Microsoft passou anos prometendo um Windows 32 bits, chegando a
dizer que ele estaria pronto em 1992, e os desenvolvedores passaram um longo tempo
aguardando pelo "Chicago", como era conhecido o Windows 95 durante o
desenvolvimento. Urna vez lançado, o Windows 95 rapidamente tornou-se o padrão
para a computação de usuário final, fazendo com que muitos desenvolvedores tivessem
suas versões de aplicativos 32 bits prontas no lançamento do SO ou imediatamente
após. A Microsoft fez seguir ao Windows 95, menos de um ano mais tarde, o Windows
NT 4.0, que incorporava a mesma interface com o usuário e executava a maioria dos
mesmos aplicativos, utilizando interfaces de programação Win32. O Windows NT
agradou rapidamente os gerentes de IT corporativos, devido a seu projeto mais estável.
Mas ainda existe um grande espaço para avanços nos sistemas
operacionais.
Durante anos, os desenvolvedores de software falaram sobre as
linguagens orientadas a objetos (como o C++) e sobre um sistema operacional mais
orientado a objetos. Num projeto como este, dados e aplicativos deveriam ser divididos,
para que os usuários pudessem trabalhar com os dados independentemente dos
aplicativos individuais. O ideal seria que os dados pudessem ser disseminados ou
distribuídos por diversos computadores.
A Microsoft vem falando sobre este conceito há anos, em especial na
palestra "A Informação nas Pontas de Seus Dedos" de Bill Gates, realizada em novembro
de 1990, que enfatizava o conceito de que todos os dados de que um usuário pode
necessitar poderiam, algum dia, ser acessados por meio de um computador pessoal,
16
Apostila Fundamentos de Sistemas Operacionais
.
independente do local onde os dados realmente residem. A idéia, disse ele, iria além
dos aplicativos e consideraria apenas os dados. Este caminho levou à ênfase dada pela
Microsoft aos documentos compostos, macros que funcionam através dos aplicativos, e
a um novo sistema de arquivos. Algumas peças desta visão - chamada Cairo - fazem
parte da interface do windows 95 e do OLE (Object Linking and Embedding). Outras
ainda estão na prancheta de desenhos. É claro que os concorrentes da Microsoft
continuaram seguindo seus próprios caminhos. Em 1989, a NEXT Computer de Steve
Jobs apareceu com um SO orientado a objetos, destinado aos clientes corporativos e
recentemente adquirido pela Apple Computer. No início dos anos 90, a IBM e a Apple
fundiram dois de seus projetos - o SO "Pink" da Apple e o experimento IBM/Metaphor,
chamado de Patriot Partners - para criar o Taligent. Este projeto resultou numa série
um tanto extensa de estruturas, para uso dos desenvolvedores, na criação de aplicativos
baseados em objetos.
Mas, embora as estruturas tenham sido recentemente
adicionadas ao OS/2, os planos para o Taligent como um SO isolado foram arquivados.
Uma outra tecnologia baseada em objetos está em vários estágios de
desenvolvimento.
O OLE, da Microsoft, que permite a criação de documentos
compostos, tem sido aprimorado e hoje faz parte da especificação ActiveX, da mesma
companhia. A Apple, a IBM e outras companhias surgiam com uma especificação
alternativa chamada OpenDoc e tais componentes são hoje conhecidos como
LiveObjects. A IBM definiu um padrão para que os objetos trabalhassem em conjunto
ao longo de uma rede chamada Systems Object Model (SOM, ou Modelo de Objeto de
Sistema), que concorre com o Component Object Model (COM, ou Modelo de Objeto
Componente), da Microsoft.
Mas tudo isto tem sido eclipsado nos últimos meses pelo Java, da Sun
Microsystems, que começou sua vida como uma variação do C++ projetada para uso na
Internet. No ano passado, ele passou a incluir uma implementação de máquina virtual
que foi incorporada aos paginadores da Netscape e da Microsoft e também à mais nova
versão do sistema operacional da IBM, o OS/2 Warp. Muitos desenvolvedores estão
atualmente desenvolvendo applets (pequenos aplicativos) e até mesmo aplicativos
completos dentro do Java, na esperança de que isto venha a livrá-los de terem que se
apoiar nos padrões Microsoft. Mais recentemente, a Sun, a Netscape e outras
companhias estiveram promovendo a especifieação Java-Beans como um ótimo método
de ligação de objetos.
Na própria Web, um dos atuais esforços são as tecnologias e produtos
que permitem o fornecimento automático do conteúdo sobre a Internet, para que os
usuários não precisem pesquisar informações específicas. Apresentada pela primeira vez
pela PointCast, que implementou uma tela de descanso que coleta as informações da
várias fontes, esta abordagem está sendo perseguida por diversos concorrentes novos,
como a Castanet e a BackWeb. E tanto a Netscape quanto a Microsoft agora prometem
o fornecimento de conteúdo Internet em segundo plano, com a Microsoft sempre
falando em fazer disto uma parte da área de trabalho do Windows.
17
Apostila Fundamentos de Sistemas Operacionais
.
Quantas e quais destas iniciativas em equipamentos, programas e rede
terão sucesso? Como sempre, é difícil dizer. Mas está claro que a Internet e a Web
serão os principais fatores nos próximos anos, assim como os inevitáveis avanços nas
capacidades de hardware e software.
18
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 1
VISÃO GERAL
1.1 Introdução:
Sistema Operacional nada mais é do que um conjunto de instruções executadas
pelo processador. Sua função é controlar o funcionamento de um computador,
gerenciando a utilização e o compartilhamento dos seus diversos recursos, como
processadores, memórias e dispositivos de entrada e saída.
Sem SO, usuário deveria conhecer profundamente o computador para poder
interagir com ele. Implicaria em trabalho lento e com possibilidade de erros.
A diferença entre um SO e aplicações convencionais é a maneira como as rotinas
são executadas em função do tempo. O SO não tem início, meio e fim como as
aplicações. Dependem de eventos assíncronos. Também pode ser chamado de Programa
monitor, Executivo, supervisor ou Controlador.
1.2 Funções básicas:
- Facilidade de acesso aos recursos do sistema: Usuário não precisa se
preocupar como é feita a comunicação com monitores, discos, impressoras, etc. O SO é
uma interface entre o usuário e os recursos do sistema. Este conceito de ambiente
simulado pelo SO também é chamado de Máquina Virtual (figura 1.1)
Compiladores, linkers, bibliotecas, depuradores e outras ferramentas são
utilitários que facilitam a interação do usuário com o computador.
- Compartilhamento de recursos de forma organizada e protegida: Em
sistemas onde diversos usuários compartilham recursos, é necessário controlar o uso
concorrente destes recursos. Ex: Impressora, a impressão de um usuário não deve
interferir na do outro. O SO controla estes acessos concorrentes. O compartilhamento
também permite redução de custos, quando diversos usuários podem compartilhar
periféricos como impressoras, discos, etc.
Dependendo do SO, podemos executar diversas tarefas ao mesmo tempo, como
imprimir um documento e baixar um arquivo da Internet. E é o SO que controla estas
atividades concorrentes.
19
Apostila Fundamentos de Sistemas Operacionais
programadores
e analistas
.
usuários
programas,
sistemas e
aplicativos
Usuários
Sistema Operacional
memória
discos
Hardware
fitas
UCP
impressoras
monitores
Fig. 1.1 - Visão do Sistema Operacional
1.3 Máquina de níveis:
Uma máquina, do ponto de vista do hardware, tem pouca utilidade. É através do
software que esta máquina ganha utilidade (como armazenamento de dados, impressão,
etc.) Uma operação efetuada por software pode ser implementada em hardware, bem
como uma função executada pelo hardware pode ser simulada via software.
Os primeiros computadores eram programados através de fios ligados em painéis,
criando grandes dificuldades e exigindo grande conhecimento da máquina.
A solução veio com o surgimento do SO, tornando a interação com o usuário mais
simples, confiável e eficiente. (Figura 1.2)
20
Apostila Fundamentos de Sistemas Operacionais
.
usuários
Sistema Operacional
Hardware
Fig. 1.2 - Visão do computador pelo usuário
O computador pode ser visualizado como uma máquina de níveis ou máquina de
camadas. Inicialmente vemos apenas dois níveis: hardware (nível 0) e SO (nível 1).
Assim, o usuário pode enxergar a máquina como sendo apenas o SO, como se o
hardware não existisse. Esta visão é chamada de máquina virtual.
Na verdade não existem apenas dois níveis, e sim tanto quantos forem
necessários para adequar o usuário às suas diversas aplicações. A figura 1.3 representa
a estrutura da maioria dos computadores, podendo conter mais ou menos camadas. A
linguagem utilizada em cada um destes níveis é diferente, variando da mais elementar
(baixo nível) à mais sofisticada (alto nível).
Aplicativos
Utilitários
Sistema Operacional
Linguagem de Máquina
Microprogramação
Circuitos Eletrônicos
Fig. 1.3 - Máquina de Níveis
21
Apostila Fundamentos de Sistemas Operacionais
.
1.4 Tipos de Sistemas Operacionais:
Os tipos de SOs e sua evolução estão diretamente relacionados com a evolução
do hardware e das aplicações por ele suportadas. A figura 1.4 sintetiza os diversos tipos
de SOs, cujas características, vantagens e desvantagens serão abordadas em seguida.
Tipos de
Sistemas Operacionais
Sistemas
Monoprogramáveis/
Monotarefa
Sistemas
Multiprogramáveis/
Multitarefa
Sistemas
com Múltiplos
Processadores
Fig. 1.4 - Tipos de Sistemas Operacionais
1.4.1 SOs monoprogramáveis/monotarefa:
Os primeiros SOs eram voltados para a execução de um único programa.
Qualquer outra aplicação deveria aguardar a aplicação concorrente terminar, para ser
executada. Estes sistemas vieram a ser conhecidos como sistemas monoprogramáveis e
se caracterizavam por permitir que o processador, a memória e os periféricos estejam
exclusivamente dedicados à execução de um único programa.
Este tipo de SO está relacionado aos primeiros computadores da década de 60.
Voltou a ser utilizado na década de 70 em estações de trabalho. Nos sistemas
monotarefas, como também são conhecidos, todos recursos do sistema ficam
exclusivamente dedicados a uma única tarefa.
Neste tipo de SO, o processador fica ocioso, por exemplo, quando espera a
digitação de um dado. A memória é sub-utilizada caso não seja preenchida totalmente, e
os periféricos, como discos e impressoras, estão dedicadas a um único usuário, nem
sempre de forma integral (Figura 1.5).
22
Apostila Fundamentos de Sistemas Operacionais
.
UCP
Memória
Principal
programa/
tarefa
Dispositivos
de E/ S
Fig. 1.5 - Sistemas monoprogramáveis / monotarefa.
1.4.2 SOs multiprogramáveis / multitarefa:
Os SOs multiprogramáveis ou multitarefas são uma evolução do SO
monoprogramáveis. Neste tipo de SO os recursos computacionais são compartilhados
entre diversos usuários e aplicações. Aqui várias aplicações compartilham esses mesmos
recursos.
Aqui também, enquanto um programa espera por uma operação de leitura ou
gravação em disco, outros programas podem estar sendo processados neste intervalo de
tempo. Neste exemplo, observamos o compartilhamento da memória e do processador.
O SO se preocupa em gerenciar o acesso concorrente a seus diversos recursos, de forma
ordenada e protegida, entre os diversos programas (Figura 1.6).
23
Apostila Fundamentos de Sistemas Operacionais
programa/
tarefa
.
programa/
tarefa
UCP
Memória
Principal
Dispositivos
de E/ S
programa/
tarefa
programa/
tarefa
programa/
tarefa
Fig. 1.6 – Sistemas multiprogramáveis / multitarefa
A vantagem deste tipo de SO é a redução do tempo de resposta das aplicações
processadas no ambiente e de custos, a partir do compartilhamento de recursos do
sistema entre diferentes aplicações. Apesar de mais eficientes, os SO multiprogramável
tem implementação muito mais complexa.
Baseado no número de usuários que interagem com o sistema, o SO
multiprogramável pode ser classificado como monousuário ou multiusuário. Os sistemas
multiprogramáveis monousuário são encontrados em computadores pessoais e estações
de trabalho, onde apenas um usuário interage com o sistema. Por exemplo, um usuário
pode executar um editor de texto, ao mesmo tempo em que acessa a Internet e imprime
um documento. Nos sistemas multiusuários, permite-se que diversos usuários
conectarem-se ao sistema simultaneamente. A tabela 1.1 relaciona os tipos de sistemas
em função do número de usuários.
Monoprogramação / Monotarefa
Multiprogramação / Multitarefa
Um usuário
Monousuário
Monousuário
Dois ou mais usuários
Não disponível
Multiusuário
Tabela 1.1 – Sistemas x Usuários
24
Apostila Fundamentos de Sistemas Operacionais
.
Os SO multiprogramáveis ou multitarefa, podem ainda ser classificados pela forma
com que suas aplicações são gerenciadas, podendo ser divididos em sistemas batch, de
tempo compartilhado ou de tempo real. Um SO pode suportar um ou mais destes tipos
de processamento, dependendo de sua implementação (Figura 1.7).
Sistemas
Multiprogramáveis/
Multi tarefa
Sistemas
Batch
Sistemas de
Tempo Compartilhado
Sistemas de
Tempo Real
Fig. 1.7 – Tipos de sistemas multiprogramáveis / multitarefa.
1.4.2.1 Sistemas Batch:
Os sistemas batch foram os primeiros SOs multiprogramáveis implantados na década
de 60. Os programas, também chamados de jobs, eram executados através de cartões
perfurados e armazenados em discos ou fitas, onde aguardavam para serem
processados. Posteriormente, em função da disponibilidade de espaço na memória
principal, os jobs eram executados, produzindo uma saída em disco ou fita.
Este tipo de processamento se caracteriza por não exigir a atenção do usuário com a
aplicação. Todas entradas e saídas eram implementadas por algum tipo de memória
secundaria, geralmente discos. Cálculos numéricos, compilações, ordenações e backups
são exemplos de aplicações batch.
Estes sistemas podem ser bastante eficientes, por utilizar melhor o processador,
entretanto, podem oferecer tempos de resposta longos. Atualmente não existem
sistemas exclusivamente batch, sendo executados através de simulações quando
necessário.
1.4.2.2 Sistemas de Tempo compartilhado:
Os sistemas de tempo compartilhado (time-sharing), permitem que diversos
programas sejam executados a partir da divisão de tempo do processador em pequenos
intervalos, chamados de fatia de tempo (time-slice). Caso o tempo disponibilizado não
seja suficiente para a conclusão do programa, este é interrompido pelo SO e substituído
por um outro, enquanto fica aguardando por uma nova fatia de tempo. Este ambiente
dá a impressão que todo o sistema esta dedicado, exclusivamente, para cada usuário.
25
Apostila Fundamentos de Sistemas Operacionais
.
Geralmente, nestes sistemas a interação com o usuário se dá através de terminais
de vídeo, teclado e mouse. Estes sistemas possuem uma linguagem de controle própria,
permitindo ao usuário comunicar-se diretamente com o SO através de comandos. Assim,
é possível por exemplo, a verificar arquivos armazenados num disco, ou cancelar a
execução de um programa.
Devido a este tipo de interação, os sistemas de tempo compartilhado também são
chamados de sistemas on-line.
A maioria das aplicações comerciais atuais são processadas em sistemas de tempo
compartilhado, pois oferecem tempos baixos de resposta aos usuários e menores custos,
em função da utilização compartilhada de diversos recursos.
1.4.2.3 Sistemas de Tempo Real:
Os sistemas de tempo real (real-time) são implementados de forma semelhante à
dos sistemas de tempo compartilhado. A diferença é o tempo de resposta exigido no
processamento das aplicações.
Nos sistemas de tempo compartilhado, o tempo de resposta pode variar sem
comprometer as aplicações em execução. Nos de tempo real, os tempos de resposta
devem estar dentro de limites rígidos, que devem ser obedecidos, caso contrario
poderão ocorrer sérios problemas.
No sistema de tempo real não existe a idéia de fatia de tempo. Um programa utiliza o
processador o tempo que necessitar, ou ate que apareça outro mais prioritário. A
prioridade de execução é definida pela própria aplicação e não pelo SO.
Estes sistemas podem ser encontrados em aplicações de controle de processos, como
no monitoramento de refinarias de petróleo, controle de trafego aéreo, de usinas
termoelétricas e nucleares, ou qualquer outra onde o tempo de resposta é fator
fundamental.
1.4.3 Sistemas com Múltiplos Processadores:
Os sistemas com múltiplos processadores caracterizam-se por possuir dois ou mais
processadores interligados e trabalhando em conjunto. Este tipo de sistema permite que
vários programas sejam executados ao mesmo tempo, ou que um único programa seja
subdividido em partes para serem executados simultaneamente em mais de um
processador.
O uso de múltiplos processadores permitiu a criação de sistemas voltados para
processamento científico (como a criação do mapa genético), no desenvolvimento
aeroespacial, prospecção de petróleo, simulações, processamento de imagens, CAD e
previsão do tempo. Pode-se afirmar que qualquer aplicação que faca uso intensivo do
processador, será beneficiada pelo acréscimo de processadores ao sistema. A evolução
destes sistemas se deve em grande parte, ao elevado custo de desenvolvimento de
26
Apostila Fundamentos de Sistemas Operacionais
.
processadores de alto desempenho. É menos custoso
processadores menores do que desenvolver um mais poderoso.
interligar
diversos
Além dos mesmos benefícios dos sistemas multiprogramáveis, o sistema com
múltiplos processadores apresentam vantagens como:
Escalabilidade : é a possibilidade de se aumentar o poder computacional do
sistema, adicionando-se novos processadores.
Disponibilidade : é a capacidade de manter o sistema em operação mesmo em
caso de falha de uma ou mais maquinas. No caso de uma falha, as outras máquinas
assumem suas funções de maneira transparente ao usuário, embora com menor poder
de computação.
Balanceamento de carga : é a possibilidade de distribuir o processamento entre
os diversos processadores, melhorando assim o desempenho do sistema como um todo.
Um fator-chave na criação de SOs com múltiplos processadores é a forma de
comunicação entre eles e o grau de compartilhamento da memória e dos dispositivos de
entrada e saída. Assim, podemos classificar os sistemas com múltiplos processadores em
fortemente acoplados ou fracamente acoplados (Figura 1.8).
Sistemas
Com Múltiplos
Processadores
Sistemas
Fortemente
Acoplados
Sistemas
Fracamente
Acoplados
Fig. 1.8 – Tipos de Sistemas com múltiplos processadores
1.4.3.1 Sistemas fortemente acoplados:
Nos sistemas fortemente acoplados (tightly coupled) vários processadores
compartilham uma única memória física (shared memory) e dispositivos de entrada e
saída, sendo gerenciados por um único SO (Figura 1.9).
27
Apostila Fundamentos de Sistemas Operacionais
UCP
.
Memória
Principal
Dispositivos
de E/ S
UCP
Dispositivos
de E/ S
Fig 1.9 – Sistemas fortemente acoplados
Em virtude disso, este tipo de sistema também é chamado de multiprocessador.
Os sistemas multiprocessadores dividem-se ainda em SMP (Symmetric
MultiProcessor) e NUMA (Non-Uniform Memory Access). Os sistemas SMP possuem
tempo uniforme de acesso à memória principal pelos diversos processadores. Os
sistemas NUMA apresentam diversos conjuntos reunindo processadores e memória
principal, sendo que cada conjunto é conectado aos outros através de uma rede de
interconexão. O tempo de acesso à memória pelos processadores varia em função da
sua localização física.
Nos sistemas SMP e NUMA todos processadores têm as mesmas funções.
Inicialmente, os sistemas multiprocessadores limitavam-se a sistemas de grande porte.
Com a evolução dos computadores pessoais, os sistemas multitarefa também evoluíram
para permitir a existência de vários processadores no modelo simétrico. Atualmente,
sistemas como Unix, Linux, Windows 200 e Windows XP implementam esta
funcionalidade.
1.4.3.2 Sistemas fracamente acoplados:
Os sistemas fracamente acoplados (loosely coupled), caracterizam-se por possuir
dois ou mais sistemas computacionais conectados através de linhas de comunicação.
Cada sistema funciona de forma independente, possuindo seu próprio sistema
operacional e gerenciando seus próprios recursos, como processador, memória e
dispositivos de entrada e saída (Figura 1.10).
28
Apostila Fundamentos de Sistemas Operacionais
.
link de comunicação
UCP
Memória
Principal
UCP
Dispositivos
de E/ S
Memória
Principal
Dispositivos
de E/ S
Fig. 1.10 Sistemas fracamente acoplados
Em função destas características, os sistemas fracamente acoplados também são
conhecidos como multicomputadores. Neste modelo, cada sistema computacional
também pode ser formado por um ou mais processadores.
Até meados dos anos 80, as aplicações eram centralizadas em sistemas de grande
porte, com um ou mais processadores. Nesta configuração, os usuários utilizavam
terminais não-inteligentes conectados a linhas seriais dedicadas ou mesmo a linhas
telefônicas públicas para comunicação interativa com estes sistemas. No modelo
centralizado, os terminais não tem poder de processamento. A solicitação de uma tarefa
ao sistema é feita através de linhas de comunicação.
A evolução dos computadores pessoais e também das telecomunicações, fez com
que um novo modelo de computação surgisse, chamado de modelo de rede de
computadores. Em uma rede existem dois ou mais sistemas independentes (hosts),
interligados através de linhas de comunicação, oferecendo algum tipo de serviço aos
demais. Assim, a informação deixa de ser centralizada em sistemas de grande porte e
passa a ser distribuída pelos diversos sistemas da rede.
Baseando-se no grau de integração dos hosts da rede, dividimos os sistemas
fracamente acoplados em sistemas operacionais de rede e sistemas distribuídos. A
diferença básica entre eles é a capacidade do SO criar uma imagem única dos serviços
disponibilizados pela rede.
Os sistemas operacionais de rede (SORs) permitem que um host compartilhe seus
recursos como impressora ou disco, com os demais hosts da rede. Um exemplo disto são
as redes locais.
Nos sistemas distribuídos o sistema operacional esconde os detalhes dos hosts
individuais e passa a tratá-los como um conjunto único, como se fosse um sistema
fortemente acoplado. Nos sistemas distribuídos, uma aplicação pode ser dividida em
29
Apostila Fundamentos de Sistemas Operacionais
.
partes e cada parte pode ser executada por hosts diferentes da rede de computadores.
Para os usuários e suas aplicações, é como se não existisse a rede de computadores, e
sim um único sistema centralizado.
Outro exemplo de sistema distribuído são os clusters. Em um cluster existem dois
ou mais servidores ligados, através de uma conexão de alto desempenho. O usuário não
conhece os nomes dos membros do cluster e não sabe quantos são. Basta solicitar um
serviço ao cluster para obtê-lo. Este tipo de sistema é usado atualmente em sistemas de
banco de dados e Web, garantindo alta disponibilidade, escalabilidade e balanceamento
de carga à solução.
30
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 2
CONCEITOS DE HARDWARE E SOFTWARE
2.1 Introdução:
Neste capítulo serão apresentados brevemente, conceitos básicos de hardware e
software, para compreensão dos capítulos seguintes.
2.2 Hardware:
Um sistema computacional é um conjunto de circuitos eletrônicos interligados,
formado por Processador ou unidade central de processamento, memória principal e
dispositivos de entrada/saída.
Processador / UCP
Unidade Lógica
e Aritmética
Unidade de
Controle
Memória
Principal
Registradores
Dispositivos
de E/ S
Fig. 2.1 Sistema Computacional
2.2.1 Processador:
Um processador é composto por unidade de controle, unidade lógica e aritmética,
e registradores. A unidade de controle (UC) é responsável por gerenciar as atividades de
todos os componentes do computador, como a gravação de dados em discos ou a busca
de instruções na memória. A unidade lógica e aritmética (ULA), como o nome indica, é
responsável pela realização de operações lógicas (testes e comparações) e aritméticas
(somas e subtrações).
31
Apostila Fundamentos de Sistemas Operacionais
.
2.2.2 Memória:
A memória é composta por unidades de acesso chamadas células, sendo cada
célula composta por um determinado número de bits. Atualmente, a grande maioria dos
computadores utiliza o byte (8 bits) como tamanho de célula.
Memórias voláteis precisam estar sempre energizadas para manter suas
informações, o que não acontece com as não-voláteis.
0
instrução ou dado
1
endereços
2
16
2 -1
célula = 8 bits
Fig. 2.2 – Memória principal com 64 Kbytes
2.2.3 Memória Cache:
A memória cache é uma memória volátil de alta velocidade, porém com pequena
capacidade de armazenamento. O tempo de acesso a um dado nela contido é muito
menor que se o mesmo estivesse na memória principal. O propósito do uso da memória
cache é minimizar a disparidade existente entre a velocidade com que o processador
executa instruções e a velocidade com que dados são acessados na memória principal.
2.2.4 Memória Principal e Secundaria:
A memória principal é um dispositivo de armazenamento, em geral volátil, onde
são armazenados instruções e dados utilizados pelo processador durante a execução de
programas. A memória secundária é um dispositivo não-volátil com maior capacidade de
armazenamento, porém com menor velocidade de acesso aos seus dados armazenados.
32
Apostila Fundamentos de Sistemas Operacionais
.
Registradores
Memória Cache
maior
capacidade de
armazenamento
Memória Principal
maior custo e
velocidade
de acesso
Memória Secundária
Fig. 2.3 – Relação entre dispositivos de armazenamento
2.2.5 Dispositivos e Entrada/Saída:
Os dispositivos de entrada e saída podem ser divididos em duas categorias: os
que são utilizados como memória secundária e os que servem para a interface usuáriomáquina. Os dispositivos utilizados como memória secundária (discos e fitas magnéticas)
caracterizam-se por ter capacidade de armazenamento bastante superior ao da memória
principal. Seu custo é relativamente baixo, porém o tempo de acesso à memória
secundária é bem superior ao da memória principal. Outros dispositivos têm como
finalidade a comunicação usuário-máquina, como teclados, monitores de vídeo,
impressoras e plotters.
2.2.6 Barramentos ou Bus:
Barramentos é o meio físico de comunicação entre as unidades funcionais de um
sistema computacional. Os barramentos processador-memória são de curta extensão e
alta velocidade para que seja otimizada a transferência de informação entre
processadores e memórias. Os barramentos de E/S possuem maior extensão, são mais
lentos e permitem a conexão de diferentes dispositivos. O barramento de backplane
tem a função de integrar os dois barramentos anteriores.
33
Apostila Fundamentos de Sistemas Operacionais
.
Memória
Principal
UCP
Barramento processador-memória
Barramento de E/ S
Adaptador
Barramento de E/ S
Adaptador
Fig. 2.4 – Barramentos processador-memória e de E/S
Memória
Principal
UCP
Barramento processador-memória
Barramento
de backplane
Adaptador
Adaptador
Barramento de E/ S
Barramento de E/ S
Adaptador
Fig. 2.5 – Barramento de Backplane
34
Apostila Fundamentos de Sistemas Operacionais
.
2.2.7 Pipeline:
É uma técnica que permite ao processador executar múltiplas instruções
paralelamente em estágios diferentes.
P1
P2
P3
P4
Unidade de
busca da
instrução
Analisador
da
instrução
Unidade de
busca dos
dados
Unidade de
execução da
instrução
P1
Instr.1 Instr.2 Instr.3 Instr.4 Instr.5 Instr.6 Instr.7
P2
Instr.1 Instr.2 Instr.3 Instr.4 Instr.5 Instr.6
P3
Instr.1 Instr.2 Instr.3 Instr.4 Instr.5
P4
Instr.1 Instr.2 Instr.3 Instr.4
tempo
Fig. 2.6 – Arquitetura pipeline com quatro estágios
35
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 3
CONCORRÊNCIA
3.1 Introdução:
Os sistemas operacionais podem ser vistos como um conjunto de rotinas que
executam concorrentemente de forma ordenada. A possibilidade de o processador
executar instruções em paralelo com operações de E/S permite que diversas tarefas
sejam executadas concorrentemente. Concorrência é o princípio básico para projeto e
implementação dos sistemas operacionais multiprogramáveis.
Os SOs monoprogramáveis eram limitados por seus recursos não serem utilizados
de forma eficiente, limitando seu desempenho. Muitos recursos (alguns de alto custo),
permaneciam ociosos por longos períodos de tempo.
O disperdício dos SOs monoprogramáveis pode ser representado na Figura 3.1a,
pois enquanto uma leitura em disco é realizada, o processador permanece ocioso. O
tempo de espera é relativamente longo, pois as operações de E/S são lentas comparadas
às operações dos processadores.
E/ S
UCP
1
E/ S
UCP
livre
1
2
1
tempo
(a) Sistema Monoprogramável
tempo
(b) Sistema Multiprogramável
Fig. 3.1 – Sistema monoprogramável x sistema multiprogramável
A tabela 3.1 apresenta um exemplo de um programa que lê registros de um
arquivo e executa, em média, 100 instruções por registro lido. Neste caso, o processador
gasta cerca de 93% do tempo esperando o dispositivo de E/S concluir sua operação para
então continuar o processamento.
Leitura de um registro
0,0015 s
Execução de 100 instruções
0,0001 s
Total
0,0016 s
% utilização da CPU (0,0001 / 0,0015) = 0,066 = 6,6 %
Tabela 3.1 Exemplo de utilização do sistema
36
Apostila Fundamentos de Sistemas Operacionais
.
A memória principal também é subutilizada se o programa não a ocupa
totalmente, deixando áreas livres. Nos SOs multiprogramáveis, vários programas podem
estar residentes em memória, concorrendo pela utilização do processador. Assim, o
processador permanece menos tempo ocioso (Figura 3.1 b) e a memória é utilizada de
forma mais eficiente, pois vários programas se revezam na utilização do processador.
A utilização concorrente do processador deve ser implementada de forma que,
quando um programa perde o uso do processador, e depois retorna sua execução,
deverá continuá-la na instrução seguinte àquela em que fora interrompido. Para o
usuário, parece que nada aconteceu. Em sistemas de tempo compartilhado, existe a
impressão de o sistema está inteiramente dedicado a ele.
Em sistema monoprogramáveis, temos periféricos (como impressoras e discos)
parados por grandes períodos de tempo esperando ações de um único usuário.
Na tabela 3.2 temos as vantagens de um sistema multiprogramável, com um
disco, um terminal e uma impressora. Nesta configuração, são executados três
programas distintos (Prog1, Prog2 e Prog3).
Pela tabela, percebemos que Prog1 não realiza operações de E/S, ao contrário de
Prog2 e Prog3.
Características
Utilização do processador
Operações de E/S
Tempo de processamento
Memória utilizada
Utilização de disco
Utilização de terminal
Utilização de impressora
Prog1
Alta
Poucas
5 min
50 Kb
Não
Não
Não
Prog2
Baixa
Muitas
15 min
100 Kb
Não
Sim
Não
Prog3
Baixa
Muitas
10 min
80 Kb
Sim
Não
Sim
Tabela 3.2 – Características de execução do programas
Se fossem realizados num ambiente monoprogramável, seriam executados em
seqüência, totalizando 30 minutos. Se fossem executados em ambiente
multiprogramável, os ganhos são consideráveis, conforme mostra a tabela 3.3.
Características
Utilização do processador
Utilização da memória
Utilização de disco
Utilização de impressora
Tempo total de processamento
Taxa de processamento
Monoprogramação
17 %
30 %
33%
33 %
30 min.
6 progr. / hora
Multiprogramação
33 %
67 %
67 %
67%
15 min.
12 progr. / hora
Tabela 3.3 – Comparação entre Mono e multiprogramação
37
Apostila Fundamentos de Sistemas Operacionais
.
A seguir, será apresentado técnicas de implementação da concorrência, essencial
num sistema multiprogramável.
3.2 Interrupção e Exceção:
Durante a execução de um programa, eventos inesperados podem ocorrer,
ocasionando um desvio forcado em seu fluxo de execução. Estes tipos de eventos são
conhecidos por interrupção ou exceção e podem ser conseqüência da sinalização de
algum hardware externo ou da execução de instruções do próprio programa. A diferença
entre interrupção e exceção e dada pelo tipo de evento ocorrido. Porém, nem sempre é
feita esta distinção.
A interrupção permitiu a implementação da concorrência nos computadores. Com
este mecanismo, o SO sincroniza a execução de todas suas rotinas e dos programas dos
usuários, além de controlar dispositivos.
Uma interrupção é gerada por algum evento externo ao programa e independe da
instrução que esta sendo executada. Um exemplo de interrupção ocorre quando um
disco avisa ao processador que uma operação de leitura ou escrita está completa. Neste
caso, o processador interrompe o programa e trata o término da operação.
Ao final da execução de cada instrução, a unidade de controle verifica a
ocorrência de algum tipo de interrupção. Neste caso, o programa é desviado para uma
rotina de tratamento de interrupção. Para o programa prosseguir posteriormente, as
informações do programa executado são armazenadas em registradores no processador
(Figura 3.2).
Fig. 3.2 – Mecanismos de interrupção e exceção
38
Apostila Fundamentos de Sistemas Operacionais
.
A tabela 3.4 descreve o mecanismo de interrupção, que pode ser realizado por
hardware ou software.
Para cada tipo de interrupção existe uma rotina de tratamento associada. A
identificação do tipo de interrupção é fundamental para determinar o endereço da rotina
de tratamento.
Existem dois métodos utilizados no tratamento das interrupções. O primeiro utiliza
uma estrutura de dados chamada de vetor de interrupção, que contem o endereço inicial
de todas as rotinas de tratamento existentes, associadas a cada evento. Um segundo
método utiliza um registrador de status que armazena o tipo do evento ocorrido. Neste
método, só existe uma única rotina de tratamento, que no seu inicio testa o registrador
para identificar o tipo de interrupção e tratá-la de maneira adequada.
Via Hardware
Via Software
1. Um sinal de interrupção é gerado para o processador
2. Após o termino da execução da instrução corrente, o
processador identifica o pedido de interrupção
3. Os conteúdos dos registradores apropriados são salvos
4. O processador identifica qual a rotina de tratamento que será
executada e carrega um registrador com o endereço inicial
desta rotina
5. A rotina de tratamento salva o conteúdo dos demais
registradores na pilha de controle de programas
6. A rotina de tratamento é executada
7. Após o termino da execução da rotina, os registradores são
restaurados, retomando a execução do programa
interrompido
Tabela 3.4 – Mecanismo de interrupção
As interrupções são decorrentes de eventos assíncronos (não relacionados à
instrução do programa). Estes eventos podem ser imprevisíveis e podem ocorrer
múltiplas vezes. Isso possibilitaria a ocorrência de múltiplas interrupções simultâneas.
Par evitar esta situação, é a rotina de tratamento inibir as demais interrupções. Assim,
as interrupções posteriores seriam ignoradas durante a execução da rotina de
tratamento, ou seja, não receberiam tratamento. Interrupções com estas características
são chamadas de interrupções mascaráveis.
Alguns processadores não permitem que interrupções sejam desabilitadas. Neste
caso, o processador precisa saber a ordem em que ocorreram as interrupções
concorrentes. Para isso, as interrupções devem possuir prioridades, em função de sua
importância. Normalmente, um dispositivo denominado controlador déb pedidos de
interrupção, é o responsável por avaliar as interrupções geradas e suas prioridades.
39
Apostila Fundamentos de Sistemas Operacionais
.
Uma exceção é semelhante a uma interrupção, sendo a principal diferença, o
motivo pelo qual o evento é gerado. A exceção é resultado direto da execução de uma
instrução do próprio programa, como a divisão de um número por zero, ou a ocorrência
de um “overflow” e operações aritméticas. Portanto, a exceção é gerada por um evento
síncrono. Tais eventos são portanto previsíveis e só podem ocorrer um único de cada
vez. Um programa com este tipo de evento que seja reexecutado a exceção ocorrera
sempre na mesma instrução.
Assim como a interrupção, o programa interrompido é desviado para uma rotina
de tratamento de exceção (Figura 3.2). O mecanismo de tratamento de exceções muitas
vezes pode ser escrito pelo próprio programador. Assim, é possível evitar que um
programa seja encerrado de ocorrer, por exemplo, um overflow.
3.3 Operações de Entrada/Saída:
Nos primeiros SOs, existiam instruções especiais para controlar periféricos,
denominadas de instruções de entrada/saída. Estas instruções continham detalhes de
cada periférico, como por exemplo, na gravação de um bloco de dados em disco, deveria
se especificar em qual trilha e setor ocorreria a gravação. Isto provocava uma forte
dependência entre processador e os dispositivos de E/S.
O controlador de interface surgiu para permitir que o processador fique mais
independente dos periféricos. Desta forma, o processador não se comunica mais
diretamente com os dispositivos de E/S, mas sim através do controlador (Figura 3.3).
Memória
Principal
UCP
Controlador
Dispositivos de E/ S
Fig. 3.3 – Controlador de dispositivos de E/S
40
Apostila Fundamentos de Sistemas Operacionais
.
O controlador simplificou as instruções de E/S, pois o processador não
necessitaria utilizar instruções detalhadas.
Com a utilização do controlador, existiam duas maneiras básicas pelas quais o
processador gerenciava as operações de E/S:
- Na primeira, o processador sincroniza-se com o periférico para o inicio da
troca de dados entre eles, e depois de iniciada a transferência, o sistema ficava
permanentemente testando o estado dos periféricos para saber quando a operação de
E/S terminaria. Este tipo de controle, chamado de E/S controlada por programa,
mantinha o processador ocupado até o fim da operação de E/S (busy wait). Isto
provocava um desperdício de tempo, pois o processador executa uma instrução muito
mais rapidamente que a realização de uma operação de E/S.
- Na segunda, há uma evolução do modo anterior, onde uma vez iniciada a
transferência de dados, o processador permanece livre para realizar outras tarefas.
Neste caso, em determinados intervalos de tempo, o SO deve testar os dispositivos para
saber do término da operação de E/S (polling). Esta técnica permitiu um tipo de
paralelismo, sendo a base dos sistemas multiprogramáveis. O único inconveniente desta
técnica, é que caso haja muitos periféricos, o processamento será interrompido
freqüentemente.
Com o mecanismo de interrupção, as operações de E/S se tornaram mais
eficientes, uma vez que o controlador interrompe o processador para avisar o fim de
uma operação, ao invés do processador ficar constantemente verificando as operações
pendentes (E/S controlada por interrupção).
Esta última técnica é mais eficiente do que a controlada por programa, pois
elimina a necessidade do processador esperar pelo término da operação, alem de
permitir varias operações de E/S simultâneas.
Ainda existe um outro inconveniente neste processo. É o caso em que há uma
grande quantidade de dados, onde as muitas intervenções do processador acabam por
reduzir sua eficiência. Uma solução pensada para este problema, foi a técnica de
transferência de dados chamada de DMA (Direct Memory Address).
A técnica DMA permite que um bloco de dados seja transferido entre a memória
principal e um dispositivo de E/S, sem a intervenção do processador, exceto no inicio e
no fim da transferência. Quando o sistema deseja ler ou gravar um bloco de dados, o
processador informa ao controlador sua localização, o dispositivo de E/S, a posição inicia
da memória onde os dados serão lidos ou gravados e o tamanho do bloco. Com estas
informações, o controlador realiza a transferência entre o periférico e a memória
principal, e o processador será interrompido somente no final da operação. A área de
memória utilizada pelo controlador na técnica de DMA é chamada de buffer de
entrada/saída.
41
Apostila Fundamentos de Sistemas Operacionais
.
Na técnica de DMA, o controlador assume momentaneamente o controle do
barramento. Neste caso, a utilização do barramento passa ser exclusiva do periférico, e
o processador suspende temporariamente o acesso ao barramento. O processador pode
nestas horas, realizar tarefas que não dependa, do barramento, como por exemplo,
acesso à memória cache.
3.4 Buffering:
A técnica de buffering consiste na utilização de uma área na memória principal,
denominada buffer, para a transferência de dados entre os dispositivos de E/S e a
memória. Esta técnica permite que em uma operação de leitura, o dado seja
primeiramente transferido para o buffer, liberando imediatamente o dispositivo para uma
nova leitura. Assim, enquanto o processador processa o dado localizado no buffer, o
periférico realiza outra operação de leitura, simultaneamente. O mesmo mecanismo
pode ser aplicado às gravações (Figura 3.4)
Memória
Principal
gravação
UCP
gravação
Controlador
Buffer
leitura
leitura
Fig. 3.4 – Operações de E/S utilizando buffer
O objetivo desta técnica é manter, na maior parte do tempo, processador e
dispositivos de E/S ocupados, pois minimiza o problema da disparidade da velocidade de
processamento entre o processador e os dispositivos.
A unidade de transferência utilizada no buffering é o registro, que tem seu
tamanho definido em função:
- Da natureza do dispositivo. Por exemplo, uma linha gerada por uma
impressora, ou um caractere de um teclado.
- Da aplicação, definido em arquivo.
Logicamente o buffer deve permitir armazenar diversos registros, de forma que
hajam dados lidos e ainda não processados, ou processados mas ainda não gravados.
Isto torna o processo bastante eficiente, pois é possível compatibilizar a diferença
existente entre o tempo em que o processador executa instruções e o tempo em que o
dispositivo de E/S realiza suas operações de leitura e gravação.
42
Apostila Fundamentos de Sistemas Operacionais
.
3.5 Spooling:
A técnica de spooling (simultaneous peripheral operation on-line), introduzida no
final dos anos 50, visa aumentar o grau de concorrência e a eficiência dos SOs.
Semelhante à técnica de buffering, a técnica de spooling utiliza uma área em
disco como se fosse um grande buffer. Neste caso, os dados podem ser lidos ou
gravados em disco, enquanto programas são executados concorrentemente.
Esta técnica esta presente na maioria dos SOs, utilizada no gerenciamento de
impressão. No momento em que um comando de impressão é executado, as
informações a serem impressas são gravadas antes em um arquivo em disco, conhecido
como arquivo de spool, liberando o programa para outras atividades. Posteriormente, o
SO se encarrega de direcionar o conteúdo do arquivo de spool para a impressora (Figura
3.5).
Sistema Operacional
Programa
Arquivo
de Spool
Impressora
Fig. 3.5 – Técnica de Spooling
Esta técnica desvincula o programa do dispositivo impressor, impedindo que um
programa reserve a impressora para uso exclusivo. O SO gerencia a seqüência de
impressões solicitadas pelos programas, seguindo critérios de segurança e de uso
eficiente das impressoras.
3.6 Reentrância:
Em sistemas multiprogramáveis, vários usuários podem utilizar o mesmo
aplicativo simultaneamente. Se cada um deles trouxesse o programa para uma área de
memória, haveria desperdício de recursos (espaço em memória).
Chamamos de reentrância, a capacidade de um código executável (código
reentrante) ser compartilhado entre vários usuários, exigindo apenas uma cópia do
programa em memória. Esta técnica permite que cada usuário possa estar em um ponto
diferente do código reentrante, manipulando dados próprios e exclusivos de cada
usuário (Figura 3.6).
43
Apostila Fundamentos de Sistemas Operacionais
.
usuário A
usuário C
código reentrante
usuário B
usuário D
área de dados do usuário A
área de dados do usuário B
área de dados do usuário C
área de dados do usuário D
Memória Principal
Fig. 3.6 – Reentrância
3.7 Proteção do Sistema:
A complexidade de um sistema multiprogramável resulta em alguns problemas de
proteção. Considerando que diversos usuários compartilham os mesmos recursos, como
memória e processador, deve existir uma preocupação com a confiabilidade e
integridade dos dados e programas dos usuários, alem do próprio SO.
Como vários programas ocupam a memória simultaneamente, cada usuário possui
uma área reservada onde seus dados e código são armazenados. O SO deve preservar
estas informações. Caso um programa tente acessar uma posição de memória fora de
sua área, um erro indicando a violação deve ocorrer.
Semelhante ao compartilhamento de memória, um disco armazena arquivos de
diferentes usuários. Novamente o SO deve garantir a integridade e confidencialidade dos
dados de cada usuário. O compartilhamento de arquivos em disco permite que dois ou
mais usuários acessem um mesmo arquivo simultaneamente pelo SO.
No sistema multiprogramável, diversos programas compartilham o processador.
Portanto, deve ser tarefa do SO também, o controle da utilização do processador,
evitando que algum programa monopolize seu uso.
Assim, o SO deve implementar diversos mecanismos de proteção que controlem o
acesso concorrente aos diversos recursos do sistema. Estes mecanismos serão
abordados em capítulos posteriores.
44
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 4
ESTRUTURA DO SISTEMA OPERACIONAL
4.1 Introdução:
O Sistema Operacional é formado por um conjunto de rotinas que oferecem
serviços aos usuários, às suas aplicações, e ao próprio sistema. Este conjunto de rotinas
é denominado núcleo do sistema ou kernel.
Não confundir o núcleo do sistema com aplicações, utilitários ou interpretadores
de comando, que acompanham o SO. (Figura 4.1). As aplicações são utilizadas pelos
usuários e não mostram os detalhes da interação com o sistema. Os utilitários, como
compiladores e editores de texto, e os interpretadores de comando, permitem aos
usuários, administradores e desenvolvedores, uma interação amigável com o sistema.
Aplicativos
Utilitários
Núcleo do
Sistema Operacional
Hardware
Fig. 4.1 – Sistema Computacional
Uma das dificuldades de se compreender o funcionamento de um SO, é devido ao
fato que ele não possui um início, um meio e um fim, como outras aplicações. Suas
ações dependem de eventos que não ocorrem em uma ordem pré-definida. Muitos
eventos estão relacionados ao hardware e ao próprio sistema.
45
Apostila Fundamentos de Sistemas Operacionais
.
4.2 Principais Funções:
As principais funções do núcleo na maioria dos SOs estão listadas a seguir:
 Tratamento de interrupções e exceções: já explicados anteriormente, em
detalhes;
 Criação e eliminação de processos: função responsável por alocar em
memória todos os recursos necessários à execução do processo. É esta função
que aloca em memória, além do executável, o contexto do processo, o buffer de
leitura/gravação (se necessário), além de listas e estruturas de controle utilizadas
pelo sistema operacional. Nesta função também são estabelecidos vínculos físicos
a arquivos em disco, fitas e outros periféricos que serão usados no
processamento. Quando do fim da execução do programa, é esta função que
desaloca todos os espaços em memória ocupados pelo processo, liberando-os
para futuras alocações a outros processos;
 Escalonamento e controle de processos: função responsável por organizar a
fila de acesso ao processador. Utiliza parâmetros do sistema e do perfil do usuário
para estabelecer a ordem em que os processos permanecerão à espera pela
liberação da CPU, para então entrarem em execução;
 Gerência de memória: função responsável por fornecer à função de
criação/eliminação de processos os endereços em memória disponíveis para
alocação;
 Gerência de sistemas de arquivos: responsável pelo gerenciamento dos
arquivos, bem como seu compartilhamento pelos diversos usuários,
implementando mecanismos de controle da segurança e direitos de acesso às
áreas utilizadas pelos usuários nos diversos dispositivos;
 Gerência de dispositivos de E/S: responsável por gerenciar os dispositivos,
prestando auxílio à criação/eliminação de processos e á gerência de sistemas de
arquivos no que diz respeito ao endereçamento e associação de arquivos em
periféricos;
 Suporte a redes e teleprocessamento: é esta função que executa todos os
serviços de rede, fazendo o empacotamento das mensagens vindas dos terminais
para a CPU central e vice-versa, além de controlar e confirmar o envio e
recebimento de todas as mensagens que trafegam pela rede;
 Contabilização de uso do sistema: responsável por contabilizar o uso de
todos os recursos do sistema consumidos pelos usuários e suas aplicações. São
registrados: tempo de CPU, tempo corrido, quantidade de área alocada em
memória, em disco, linhas impressas, páginas de papel, entre outros. Isto se faz
necessário para servir de subsídio para análise de performance, estatísticas de
46
Apostila Fundamentos de Sistemas Operacionais
.
gastos com material de consumo e também para definição de custos de
processamento.;
 Auditoria e segurança do sistema: função extremamente importante, pois
detecta e registra (num arquivo especial de LOG) todas as ocorrências de erro e
violação de direitos de acesso ao sistema, aos arquivos, à memória e a todos os
recursos do sistema. O arquivo de LOG é usado pela gerência de sistemas, com o
intuito de verificar e aperfeiçoar os mecanismos de segurança e proteção ao
sistema.
A forma como o código do sistema é organizado e o relacionamento com seus diversos
componentes varia de acordo com o projeto do SO.
4.3 System Calls:
Uma grande preocupação no projeto de um SO, é quanto a sua integridade, ou seja,
a proteção do núcleo do sistema contra possíveis acessos não-autorizados.
As system calls (chamadas ao sistema) podem ser entendidas como uma porta de
entrada para o acesso ao núcleo do sistema e seus serviços. Quando um usuário ou
aplicação necessitar de algum serviço do sistema, é feita uma chamada a uma de suas
rotinas através de uma system call. O termo system call é típico de ambientes Unix, no
ambiente Windows é conhecida como API (Application Program Inteface).
Para cada serviço disponível existe uma system call associada. Cada SO tem seu
próprio conjunto de chamadas diferentes (Figura 4.2). Isto explica o fato de uma
aplicação desenvolvida para um SO, não pode ser executada em outro.
System Call
Aplicação
Núcleo do
Sistema Operacional
Biblioteca
Hardware
Fig. 4.2 System call
Algumas tentativas foram feitas para padronizar uma biblioteca de chamadas. O
padrão POSIX (Portable Operating System Interface for Unix), por exemplo, foi
estabelecido com a intenção de unificar as diversas versões do Unix existentes.
Através de parâmetros fornecidos nas system calls, a solicitação é processada e uma
resposta é retornada à aplicação, junto com um status indicando erro ou não. A ativação
e comunicação entre programas e o SO, é semelhante a uma sub-rotina de um
programa.
47
Apostila Fundamentos de Sistemas Operacionais
.
As system calls podem ser divididas em grupos de funções (Tabela 4.1)
Muitos usuários e mesmo programadores não imaginam os detalhes que envolvem
um simples comando de leitura de um arquivo, quando se utiliza uma linguagem de
programação de alto nível. O compilador converte este comando de alto nível para uma
system call específica, que quando executada, verifica a ocorrência de erros e retorna os
dados ao programa, de forma transparente ao usuário.
Funções
System Calls
Gerência de processos e threads
Criação e eliminação de processos e threads
Alteração das características de processos e
threads
Sincronização e comunicação entre processos
e threads
Obtenção de informação sobre processos e
threads
Gerência de memória
Gerência de sistema de arquivos
Alocação e desalocação de memória
Gerência de dispositivos
Criação e eliminação de arquivos e diretórios
Alteração das características de arquivos e
diretórios
Abrir e fechar arquivos
Obtenção de informações sobre arquivos e
diretórios
Alocação e desalocação de dispositivos
Operações de entrada/saída em dispositivos
Obtenção de informações sobre dispositivos
Tabela 4.1 – Funções das system calls
4.4 Modos de Acesso:
Algumas instruções não podem ser colocadas diretamente à disposição das
aplicações, pois sua utilização indevida poderia ocasionar problemas à integridade do
sistema. Por exemplo, uma aplicação que atualize um arquivo em disco. O programa por
si só, não pode especificar diretamente as instruções que acessam seus dados no disco.
Como o disco é um recurso compartilhado, quem gerencia exclusivamente sua
utilização é o SO. Assim se evita que a aplicação acesse qualquer parte do disco
indiscriminadamente, o que poderia comprometer a segurança e integridade do sistema
de arquivos.
48
Apostila Fundamentos de Sistemas Operacionais
.
Portanto, fica claro que certas instruções só devem ser executadas pelo SO ou sob
sua supervisão, impedindo assim riscos de segurança e integridade. As instruções que
possuem o poder de comprometer o sistema são conhecidas como instruções
privilegiadas, enquanto que as não-privilegiadas não oferecem estes riscos.
Para que uma aplicação não execute uma instrução privilegiada, deve ser
implementado no processador um mecanismo de proteção, conhecido como modos de
acesso. São basicamente dois os modos de acesso implementados pelo processador. O
primeiro é o modo usuário, onde a aplicação só poderá executar instruções nãoprivilegiadas, tendo acesso a um numero reduzido de instruções. O segundo modo é o
modo kernel ou supervisor, onde a aplicação tem acesso ao conjunto total de instruções
do processador.
O modo de acesso de uma aplicação é determinado por um registrador de status do
processador (chamado de PSW), Dependendo do conteúdo deste registrador, o
hardware verifica se a instrução pode ou não ser executada pela aplicação.
Apenas o SO deve ter acesso às instruções privilegiadas. Portanto, se uma aplicação
necessitar executar uma instrução privilegiada, deve solicitar sua execução através de
uma system call. A system call altera o status do PSW para modo kernel, e ao termino
de sua execução retorna ao modo usuário (Figura 4.3). Caso uma aplicação tente
executar uma instrução privilegiada em modo usuário, o processador sinaliza um erro,
uma exceção será gerada e o programa será interrompido.
No mesmo exemplo do acesso ao disco, para o programa atualizar um arquivo, a
aplicação deve solicitar a operação ao SO por meio de uma system call, que altera o
modo de acesso para kernel. Após efetuar a atualização, retorna-se ao modo usuário.
O mecanismo de modos de acesso também é uma boa forma de proteger o próprio
núcleo do sistema residente em memória. Por exemplo, se uma aplicação tivesse acesso
à área de memória onde está o SO, um programador mal-intencionado ou um erro de
programação poderia ter acessar esta área e acabar danificando o sistema. Com os
modos de acesso, apenas em modo kernel poderia se efetuar tal tarefa.
49
Apostila Fundamentos de Sistemas Operacionais
.
Fig. 4.3 – Chamada a uma rotina do sistema
50
Apostila Fundamentos de Sistemas Operacionais
.
4.5 Arquitetura Monolítica:
A arquitetura monolítica pode ser comparada com uma aplicação formada por vários
módulos que são compilados separadamente e depois linkados, formando um grande e
único programa executável, onde os módulos podem interagir livremente. Os primeiros
SOs baseavam-se neste modelo, tornando seu desenvolvimento e sua manutenção
bastante difíceis. A estrutura monolítica apresenta simplicidade e bom desempenho, por
isso foi usada no projeto do MS-DOS e nos primeiros sistemas Unix (Figura 4.4).
aplicação
aplicação
Modo usuário
Modo kernel
System call
Hardware
Fig. 4.4 – Arquitetura monolítica
51
Apostila Fundamentos de Sistemas Operacionais
.
4.6 Arquitetura de Camadas:
Os sistemas operacionais tornaram-se mais complexos e maiores em tamanho, por
isso, novas técnicas de programação estruturada e modular foram incorporadas ao seu
projeto. Na arquitetura de camadas, o sistema é dividido em níveis sobrepostos. Cada
camada oferece um conjunto de funções que podem ser utilizadas apenas pelas
camadas superiores.
O primeiro SO a usar este conceito, surgiu em 1968 na Holanda e utilizava seis
camadas. Posteriormente, sistemas como MULTICS e OpenVMS também implementaram
o conceito de camadas, agora sob forma concêntrica (Figura 4.5). Neste formato, as
camadas mais internas são mais privilegiadas que as externas.
Fig. 4.5 – Arquitetura em camadas do OpenVMS
A vantagem da arquitetura em camadas é isolar as funções do SO, facilitando sua
manutenção e depuração, alem de criar uma hierarquia de níveis de modos de acesso,
protegendo as camadas mais internas. Porém, seu desempenho é inferior ao modelo
monolítico. Cada nova camada implica uma mudança no modo de acesso. Por exemplo,
no caso do OpenVMS, para ter acesso aos serviços oferecidos pelo kernel é preciso
passar por três camadas ou três mudanças no modo de acesso.
Atualmente, a maioria dos SOs utiliza o modelo de duas camadas, onde existem
módulos de acesso usuário (não-privilegiado) e kernel (privilegiado). A maioria das
versões do Unix e do Windows 2000 baseiam-se neste modelo.
52
Apostila Fundamentos de Sistemas Operacionais
.
4.7 – Máquina Virtual:
Um sistema computacional é formado por níveis, onde a camada de nível mais baixo
é o hardware. Acima dele, encontramos o SO, que oferece suporte para as aplicações,
como visto na Figura 4.1. O modelo de máquina virtual, ou virtual machine (VM), cria
um nível intermediário entre o hardware e o SO, denominado gerência de máquinas
virtuais (Figura 4.6). Este nível cria diversas maquinas virtuais independentes, onde cada
uma oferece uma cópia virtual do hardware, incluindo os modos de acesso, interrupções,
dispositivos de E/S, etc.
Como cada VM é independente das demais, é possível que cada uma tenha seu
próprio SO e que seus usuários executem suas aplicações como se todo o computador
estivesse dedicado a cada um deles, Na década de 60, a IBM implantou este modelo no
VM/370, permitindo aplicações batch, desenvolvidas em antigos sistemas OS/360 e
aplicações de tempo compartilhado pudessem conviver na mesma máquina de forma
transparente aos usuários e aplicações.
VM 1
VM 2
VM n
Além de permitir SOs diferentes no mesmo computador, este modelo cria o
isolamento total entre cada VM, oferecendo grande segurança para cada uma delas. Por
exemplo, se uma VM executar uma aplicação que comprometa o funcionamento de seu
SO, as demais VMs não sofrerão qualquer problema. A maior desvantagem desta
arquitetura é sua complexidade, que necessita compartilhar e gerenciar os recursos de
hardware entre as diversas VMs.
Ap1
Ap2
Apn
SO1
SO2
SOn
HV1
HV2
HVn
Gerência de Máquinas Virtuais
Hardware
Fig. 4.6 – Máquina Virtual
53
Apostila Fundamentos de Sistemas Operacionais
.
Temos outro exemplo desta arquitetura, na linguagem Java, criada pela Sun
Microsystems. Para executar um programa em Java, é necessário uma máquina virtual
Java (ou Java Virtual Machine – JVM). Qualquer SO pode suportar uma aplicação Java,
desde que exista uma JVM desenvolvida para ele. Assim, a aplicação não precisa ser
compilada para cada sistema, tornando-se independente do hardware e SO utilizado
(Figura 4.7).
Aplicação
Máquina Virtual Java
Sistema Operacional
Hardware
Fig. 4.7 – Máquina Virtual Java
54
Apostila Fundamentos de Sistemas Operacionais
.
4.8 Arquitetura Microkernel:
Uma tendência nos SOs modernos é tornar o núcleo do sistema operacional o menor
e mais simples possível. Para implementar esta idéia, os serviços do sistema são
disponibilizados através de processos, onde cada um é responsável por oferecer um
conjunto específico de funções, como gerência de arquivos, de processos, de memória e
escalonamento.
me
n
m
ge
sa
Modo kernel
n
me
Modo usuário
sa
g
em
Se uma aplicação desejar algum serviço, é realizada uma solicitação ao processo
responsável. Neste caso, a aplicação é chamada de cliente e o processo que responde é
chamado de servidor. A solicitação é feita enviando-se uma mensagem ao servidor, que
responde com outra mensagem. A principal função do núcleo é realizar esta
comunicação entre cliente e servidor (Figura 4.8).
Microkernel
Hardware
Fig. 4.8 – Arquitetura Microkernel
Este conceito de Arquitetura Microkernel surgiu na década de 80, com o sistema
operacional Mach. O núcleo do Mach oferece basicamente quatro serviços: gerência de
processos, gerência de memória, comunicação por troca de mensagens e operações de
E/S, todos em modo usuário.
55
Apostila Fundamentos de Sistemas Operacionais
.
A utilização deste modelo permite que os servidores executem em modo usuário,
ou seja, não tenham acesso direto a certos componentes do sistema. Apenas o núcleo
do SO, responsável pela comunicação entre clientes e servidores, executa no modo
kernel. Assim, se um erro ocorrer em um servidor, este poderá parar, mas o sistema não
ficará inteiramente comprometido, aumentando sua disponibilidade (tempo em que está
acessível).
Como os servidores se comunicam através de troca de mensagens, não importa
se os clientes e servidores são processados em um sistema com um processador, com
múltiplos processadores (fortemente acoplados) ou ainda em um ambiente de sistema
distribuído (fracamente acoplados). A implementação de sistemas microkernel em
ambientes distribuídos permite que um cliente solicite um serviço e a resposta seja
processada remotamente. Isso permite acrescentar novos servidores à medida que
aumenta o numero de clientes, conferindo uma grande escalabilidade ao SO.
Outra vantagem é que a arquitetura microkernel permite isolar as funções do
sistema operacional por diversos processos servidores pequenos e dedicados a serviços
específicos, tornado o núcleo menor, mais fácil de depurar e, conseqüentemente,
aumentando sua confiabilidade. Na arquitetura microkernel, o sistema operacional passa
a ser de mais fácil manutenção, flexível e de maior portabilidade. Apesar de todas as
vantagens deste modelo, sua implementação, na prática, é muito difícil. Primeiro existe o
problema de desempenho, devido à necessidade de mudança de modo de acesso a cada
comunicação entre clientes e servidores. Outro problema é que certas funções do
sistema operacional exigem acesso direto ao hardware, como operações de E/S.
Na verdade, o que se implanta normalmente é a combinação do modelo de
camadas com a arquitetura de microkernel. O núcleo do sistema, além de ser
responsável pela comunicação entre cliente e servidor, passa a incorporar outras funções
críticas, como escalonamento, tratamento de interrupções e gerência de dispositivos.
56
Apostila Fundamentos de Sistemas Operacionais
.
4.9 Projeto do Sistema:
O projeto de um SO é bastante complexo e deve atender inúmeros requisitos,
algumas vezes conflitantes, como confiabilidade, portabilidade e facilidade de
manutenção. O projeto irá depender muito da arquitetura do hardware utilizado e do
tipo de sistema que se deseja construir: batch, tempo compartilhado, mono usuário ou
multiusuário, tempo real, etc.
Os primeiros SOs foram desenvolvidos em assembly e seus códigos possuíam
cerca de um milhão de instruções (ex.: IBM OS/360). Com a evolução dos SOs e
conseqüentemente o aumento do numero de linhas de código (cerca de 20 milhões no
sistema MULTICS), novas técnicas de programação modular foram incorporadas ao
projeto, além do uso de linguagens de alto nível, como PL/1 e Algol. Nos SOs atuais, o
número de linhas de código chega perto dos 40 milhões (Windows 2000), sendo escrito
grande parte em linguagem C/C++, utilizando em alguns casos, programação orientada
a objetos.
Existe uma série de vantagens na utilização de programação por objetos no
projeto e na implementação de sistemas operacionais. Os principais benefícios são:
-
melhoria na organização das funções e recursos do sistema;
redução no tempo de desenvolvimento;
maior facilidade na manutenção e extensão do sistema e
facilidade de implementação do modelo de computação distribuída.
Além disso, o uso de uma linguagem de alto nível permite maior portabilidade, ou
seja, o SO pode ser adaptado para outra arquitetura de hardware. Por outro lado, o uso
de linguagens de alto nível em relação à programação assembly, apresenta perda de
desempenho. Por isso, partes críticas do sistema, como device drivers, o escalonador e
as rotinas de tratamento de interrupções, são ainda desenvolvidas em assembly.
Um princípio fundamental no projeto de SOs é a separação no projeto do sistema
das políticas e dos mecanismos. A política define o que deve ser feito, e o
mecanismo define como implementar esta política.
57
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 5
PROCESSO
5.1 Introdução:
O processo é a base para implantação de um SO multiprogramável. O
processador executa instruções, sem distinguir qual programa se encontra em execução.
A gerência de um ambiente multiprogramável é uma função exclusiva do SO, que deve
controlar a execução dos diversos programas e o uso concorrente do processador.
Assim, um programa deve estar associado a um processo.
O termo processo surgiu após os SOs multiprogramáveis, sendo utilizado no lugar
de tarefa ou job, por grande parte da literatura técnica.
O SO deve controlar os processos. Através dos processos, um programa pode
alocar recursos, compartilhar dados, trocar informações e sincronizar sua execução. Nos
SOs
multiprogramáveis,
os
processos
são
executados
concorrentemente,
compartilhando, entre outros recursos, o uso do processador, da memória e dos
dispositivos de E/S. Em sistemas multiprocessados, além da concorrência de processos
pelo uso do processador, existe também a execução simultânea de processos nos
diferentes processadores.
Aqui abordaremos os principais conceitos relacionados aos processos.
5.2 Estrutura do Processo:
Inicialmente, pode-se entender um processo, como um programa em execução,
porém, com um conceito mais abrangente. Imaginemos como os SOs multiprogramáveis
atendem os diversos usuários e ainda mantém informações a respeito dos vários
programas executados ao mesmo tempo.
Em um sistema multiusuário, cada usuário é associado a um processo. Ao
executar um programa, o usuário tem a impressão de possuir o processador e demais
recursos exclusivamente para si. Na verdade, o processador executa o programa de um
usuário durante um intervalo de tempo, e no instante seguinte poderá estar executando
um outro programa de outro usuário.
Para que esta troca ocorra sem traumas, é necessário que as informações do
programa interrompido sejam guardadas, para que no seu retorno, nada seja perdido.
Todas informações importantes e necessárias à execução de um programa fazem parte
de um processo.
58
Apostila Fundamentos de Sistemas Operacionais
.
Um processo também pode ser definido como o ambiente em que o programa é
executado. Este ambiente possui informações sobre a execução, de quanto de recursos
do sistema cada programa pode utilizar, como espaço de memória, tempo do
processador e área em disco.
A execução de um mesmo programa pode variar dependendo do processo no qual
ele é executado, ou seja, em função dos recursos disponíveis. A falta de recursos pode
impedir um programa de ser executado com sucesso. Por exemplo, caso um programa
precise utilizar uma área em disco superior ao seu limite, o SO deve interromper sua
execução por falta de recursos.
Um processo é formado por três partes, denominadas contexto de hardware,
contexto de software e espaço de endereçamento, que juntas mantêm todas
informações necessárias à execução de um programa (Figura 5.1).
Contexto de
Software
Contexto de
Hardware
Programa
Espaço de
Endereçamento
Fig. 5.1 – Estrutura do processo
5.2.1 Contexto de hardware:
O contexto de hardware guarda o conteúdo dos registradores do processador.
Quando um processo está em execução, o seu contexto de hardware está armazenado
nos registradores do processador. Quando o processo perde a utilização da CPU, o
sistema salva as informações no contexto de hardware do processo.
O contexto de hardware é fundamental nos sistemas multiprogramáveis, onde o
revezamento da CPU permite que os processos sejam interrompidos e posteriormente
restaurados. A troca de um processo por outro no processador, executada pelo SO, é
59
Apostila Fundamentos de Sistemas Operacionais
.
chamada de mudança de contexto, e consiste em salvar o conteúdo dos registradores do
processo que esta saindo e carregá-los com os valores referentes ao do novo processo
que será executado (Figura 5.2).
5.2.2 Contexto de software:
No contexto de software são especificadas as características e limites dos recursos
que podem ser alocados pelo processo, como o numero Maximo de arquivos abertos
simultaneamente, prioridade de execução e tamanho do buffer dos dispositivos de E/S.
Muitas destas características são determinadas no momento da criação do processo,
enquanto outras podem ser alteradas posteriormente.
A maior parte das informações do contexto de software do
provenientes de um arquivo do SO, conhecido como arquivo de contas.
gerenciado pelo SO, são especificados os limites dos recursos que cada
alocar. Outras informações presentes no contexto de software
dinamicamente ao longo da execução dos processos.
processo são
Neste arquivo,
processo pode
são geradas
Sistema Operacional
Processo A
Processo B
executando
Salva registradores do
Processo A
Carrega registradores do
Processo B
executando
Salva registradores do
Processo B
Carrega registradores do
Processo A
executando
Fig. 5.2 – Mudança de contexto
60
Apostila Fundamentos de Sistemas Operacionais
.
O contexto de software é composto por três grupos de informações sobre o
respectivo processo: identificação, quotas e privilégios.

Identificação
Cada processo criado pelo sistema recebe uma identificação única
(chamada de PID – Process IDentification), representada por um número e
em alguns casos também através de um nome. É através do PID que o SO
e outros processos podem fazer referência a qualquer processo existente,
consultando e até alterando suas características.
O processo possui também a identificação do usuário ou do processo que o
criou (owner). Cada usuário possui uma identificação também única no
sistema (representada pelo UID – User Identification), que é atribuída ao
processo no momento de sua criação. A UID permite implementar modelos
de segurança, onde apenas os objetos (processos, arquivos, áreas de
memória, etc) que possuam um UID autorizado, podem ser acessados.

Quotas
As quotas são os limites de cada recurso do sistema que um processo pode
alocar. Caso uma quota seja insuficiente, o processo poderá ser executado
lentamente, interrompido ou mesmo não ser executado. Alguns exemplos
de quotas presentes nos SOs modernos:
- número máximo de arquivos abertos simultaneamente;
- tamanho máximo de memória principal e secundaria que o processo pode
alocar;
- número máximo de operações de E/S pendentes;
- tamanho máximo do buffer para operações de E/S;
- numero máximo de processos, subprocessos e threads que podem ser
criados.

Privilégios
Os privilégios ou direitos definem as ações que um processo pode fazer em
ralação a ele mesmo, aos demais processos e ao SO.
Privilégios que afetam o próprio processo permitem que suas
características possam ser alteradas, como prioridade de execução, limites
alocados na memória principal e secundaria, etc. Já os privilégios que
afetam os demais processos permitem, alem da alteração de suas próprias
características, alterar as de outros processos.
Privilégios que afetam o sistema são mais amplos e poderosos, pois estão
relacionados à gerência do ambiente, como a desativação do sistema,
alteração de regras de segurança, criação de outros processos
privilegiados, modificação de parâmetros de configuração do sistema, entre
outros. A maioria dos SOs possui uma conta de acesso com todos
privilégios disponíveis, afim de o administrador gerenciar o SO. Nos
61
Apostila Fundamentos de Sistemas Operacionais
.
sistemas Unix, existe a conta “root”, no Windows 2000 a conta
“administrador” e no Open VMS a conta “system”.
5.2.3 Espaço de endereçamento:
O espaço de endereçamento é a área de memória pertencente ao processo onde
as instruções e dados do programa são armazenados para execução. Cada processo
possui seu próprio espaço de endereçamento, que deve ser devidamente protegido do
acesso dos demais processos. A Figura 5.3 ilustra as características da estrutura de um
processo.
nome
PID
owner (UID)
registradores
gerais
prioridade de
execução
data/ hora
de criação
registrador PC
Contexto de
Software
Contexto de
Hardware
registrador SP
tempo de
processador
quotas
Programa
privilégios
registrador
de status
Espaço de
Endereçamento
endereços de memória
principal alocados
Fig. 5.3 – Características da estrutura de um processo
5.2.4 Bloco de controle do processo:
O processo é implementado pelo SO através de uma estrutura de dados chamada
Bloco de controle de processos (Process Control Block – PCB). A partir do PCB, o SO
mantém todas as informações sobre o contexto de hardware, contexto de software e
espaço de endereçamento de cada processo (Fig. 5.4).
62
Apostila Fundamentos de Sistemas Operacionais
.
ponteiros
Estado do processo
Nome do processo
Prioridade do processo
Registradores
Limites de memória
Lista de arquivos abertos
..
..
..
..
Fig. 5.4 – Bloco de controle do processo (PCB)
5.3 Estados do Processo:
Em um estado multiprogramável, um processo não deve alocar o processador
com exclusividade, de forma que possa ser compartilhado. Os processos passam por
diferentes estados ao longo de seu processamento, em função de eventos gerados pelo
SO ou pelo próprio processo. Um processo ativo pode encontra-se em três estados
diferentes:

Execução (running) – Um processo é dito no estado de execução
quando está sendo processado pela CPU. Em sistemas com apenas um
processador, somente um processo estará sendo executado em um dado
instante. Os processos se alternam na utilização do processador, seguindo
uma política estabelecida pelo SO. Em sistemas com multi-processadores,
existe a possibilidade de mais de um processo ser executado ao mesmo
tempo, como também é possível um mesmo processo ser executado
simultaneamente em mais de um processador (processamento paralelo).

Pronto (ready) – Um processo está no estado de pronto quando aguarda
apenas para ser executado. O SO que determina a ordem e o critério pelos
quais os processos neste estado devem utilizar o processador. Este
mecanismo é conhecido como escalonamento.
Em geral, existem vários processos no estado de pronto, organizados em
listas encadeadas. Os processos devem estar ordenados pela sua
importância (Figura 5.5).
63
Apostila Fundamentos de Sistemas Operacionais
.
Lista de
processos
em estado
de pronto
..
..
..
..
PCB# 5
..
..
..
..
PCB# 1
Lista de
processos
em estado
de espera
..
..
..
..
..
..
..
..
..
..
..
..
PCB# 9
PCB# 2
PCB# 4
Fig. 5.5 – Lista de PCBs nos estados de pronto e espera.

Espera (wait) – Um processo no estado de espera aguarda por algum
evento externo ou por algum recurso para prosseguir seu processamento.
Por exemplo, o término de uma operação de E/S ou a espera de uma data
ou hora para continuar sua execução. Em alguns SOs, este estado também
pode ser chamado de bloqueado (blocked).
O sistema organiza os vários processos no estado de espera também em
listas encadeadas. Em geral os processos são separados em listas de
espera associadas a cada tipo de evento (Figura 5.5). Neste caso, quando
um evento acontece, todos processos da lista associada ao evento são
transferidos para o estado de pronto.
5.4 Mudanças de Estado de Processo:
Um processo muda de estado durante seu processamento em função de eventos
originados por ele próprio (eventos voluntários) ou pelo SO (eventos involuntários).
Basicamente apenas quatro mudanças de estados podem ocorrer:

Pronto → Execução – Após a criação de um processo, o sistema o coloca
em uma lista de processos no estado de pronto, aguardando para ser
executado (Figura 5.6 a). Cada SO tem sua política de escalonamento.

Execução → Espera – Um processo passa a estado de espera por
eventos gerados pelo próprio processo, como uma operação de E/S, ou por
eventos externos (Figura 5.6 b). Um evento externo é gerado, por
exemplo, quando o SO suspende por um período de tempo a execução de
um processo
64
Apostila Fundamentos de Sistemas Operacionais
.

Espera → Pronto – Ocorre quando uma operação solicitada é atendida ou
o recurso esperado é concedido. Não existe a mudança de espera para
execução diretamente (Figura 5.6 c).

Execução → Pronto – Ocorre através de eventos gerados pelo sistema,
como o termino da fatia de tempo que o processo possui para sua
execução (Figura 5.6 d). Então, aguarda nova oportunidade para continuar
seu processamento.
Quando não houver espaço suficiente para todos os processos na memória
principal, um processo em estado de pronto ou espera pode ser encontrado na memória
secundária. Uma técnica conhecida como swapping retira processos da memória
principal e os traz de volta segundo seus próprios critérios. Portanto, os processos em
estado de espera e pronto, podem estar ou não residentes em memória principal (Figura
5.7).
Estado de Execução
d
b
a
c
Estado de Espera
Estado de Pronto
Fig. 5.6 – Mudanças de estados do processo
65
Apostila Fundamentos de Sistemas Operacionais
.
Estado de Execução
Estado de Espera
Estado de Pronto
Estado de Espera
Estado de Pronto
residente
não residente
Fig. 5.7 – Mudanças de estado do processo (2).
5.5 Criação e Eliminação de Processos:
Processos são criados e eliminados por diversas razões. A criação de um processo
ocorre quando o SO adiciona um novo PCB à sua estrutura e reserva espaço na memória
para uso. A partir da criação do PCB, o SO já reconhece a existência do processo,
passando a gerenciá-lo e associar programas ao seu contexto para serem executados.
No caso da eliminação de um processo, todos recursos associados a ele são desalocados
e o PCB eliminado pelo SO.
Além destes três processos, a maioria dos SOs estabelece mais dois estados para
os momentos de criação e eliminação de um processo (Figura 5.8).
66
Apostila Fundamentos de Sistemas Operacionais
Estado de Execução
Estado de Espera
.
Estado de Término
Estado de Pronto
Estado de Criação
Fig. 5.8 – Mudanças de estado do processo (3)


Criação (new) – Um processo é considerado em estado de criação, quando o
SO já criou um novo PCB, porém ainda não pode colocá-lo na lista de processos
do estado de pronto. Alguns SOs limitam o número de processos ativos em
função dos recursos disponíveis ou de desempenho. Esta limitação pode ocasionar
que os processos criados permaneçam no estado de criação até que possam
passar a ativos.
A criação de processos pode ocorrer por razões como:
- logon interativo: um processo é criado através do estabelecimento de uma
sessão interativa por um usuário a partir de um terminal.
- criação por um outro processo: um processo já existente pode criar outros
processos, sendo estes novos independentes ou subprocessos.
- criação pelo SO: o SO pode criar novos processos para oferecer algum serviço.

Terminado (exit) – Um processo no estado terminado não poderá ter mais
nenhum programa executado em seu contexto, porém, o SO ainda mantém suas
informações de controle na memória. Neste estado, o processo não é mais
considerado ativo, mas como o PCB ainda existe, o SO pode recuperar
informações sobre a contabilização de uso de recursos do processo, como o
tempo total do processador. Após a extração das informações, o processo pode
deixar de existir.
O término de um processo pode ocorrer devido a:
- término normal da execução;
- eliminação por um outro processo;
- eliminação forcada por ausência de recursos disponíveis no sistema.
67
Apostila Fundamentos de Sistemas Operacionais
.
5.6 Processos Independentes, Subprocessos e Threads:
Processos, subprocessos e threads são maneiras diferentes de implementar a
concorrência dentro de uma aplicação. Neste caso, busca-se dividir o código em partes
para trabalharem de forma cooperativa. Por exemplo, um banco de dados que recebe
consultas constantes e freqüentes. Aqui, a concorrência na aplicação proporciona um
tempo de espera menor entre consultas, melhorando o desempenho da aplicação e
beneficiando os usuários.
O uso de processos independentes é a maneira mais simples de se implementar a
concorrência em sistemas multiprogramáveis. Neste caso, não existe vínculo entre o
processo criado e seu criador. A criação de um processo independente exige a locação
de um PCB, possuindo contextos de hardware, software e espaço de endereçamento
próprios.
Subprocessos são criados dentro de uma estrutura hierárquica. E neste caso, o
processo criador é denominado processo pai e o novo processo é chamado de
subprocesso ou processo filho. O subprocesso pode criar outros subprocessos. Uma
característica desta implementação é a de criar dependência entre processo criador e
subprocesso. Se o processo deixar de existir, também os subprocessos o farão. Assim
como os processos independentes, os subprocessos também exigem seu próprio PCB. A
Figura 5.9 ilustra cinco processos numa estrutura hierárquica, cada qual com seus
contextos e espaços de endereçamento. Além disso, os subprocessos também podem
compartilhar quotas com o processo pai. Ou seja, quando o subprocesso é criado, o
processo pai cede parte de suas quotas a ele.
O uso de processos independentes e subprocessos demanda consumo de
recursos, uma vez que recursos são alocados toda vez que um processo é criado, e
também tempo do processador é utilizado para este trabalho. Assim também ocorre no
seu término (desalocação de recursos). Mais ainda, a comunicação e sincronização entre
processos é considerada pouco eficiente, visto que cada processo possui seu próprio
espaço de endereçamento.
O conceito de thread foi estabelecido com a intenção de reduzir o tempo gasto na
criação, eliminação e troca de contexto de processos nas aplicações concorrentes, bem
como economizar recursos do sistema como um todo. Num ambiente multithread, um
único processo pode suportar múltiplos threads, cada qual associado a uma parte do
código da aplicação (Figura 5.10). Neste caso não é necessário haver diversos processos
para implementação da concorrência. Threads compartilham o processador da mesma
maneira que um processo, ou seja, enquanto espera por uma operação de E/S, outro
thread pode ser executado.
68
Apostila Fundamentos de Sistemas Operacionais
.
Processo A
Processo C
Processo B
Processo E
Processo D
Figura 5.9 – Estrutura de Processos e Subprocessos
Cada thread possui seu próprio contexto de hardware, porém compartilha o
mesmo contexto de software e espaço de endereçamento. O compartilhamento deste
último permite que a comunicação de threads dentro de um mesmo processo seja feita
de forma simples e rápida. Este assunto será melhor detalhado no capítulo seguinte.
Contexto
de hardware
Contexto
de hardware
Thread 1
Thread 2
Thread 3
Contexto de
software
Contexto
de hardware
Espaço de
endereçamento
Fig. 5.10 – Processo Multithread
69
Apostila Fundamentos de Sistemas Operacionais
.
5.7 Processos Foreground e Background:
Um processo possui sempre associado à sua estrutura, pelo menos dois canais de
comunicação por onde são realizadas todas as entradas e saídas de dados ao longo do
seu processamento. Os canais de entrada (input) e de saída (output) de dados podem
estar associados a terminais, arquivos, impressoras e ate mesmo outros processos.
Um processo foreground é aquele que permite a comunicação direta do usuário
com o processo durante sua execução. Assim, ambos os canais estão associados a um
terminal com teclado, mouse e monitor, permitindo portanto, a interação com o usuário
(Figura 5.11a). O processamento interativo tem com base processos foreground.
Um processo background é aquele onde não existe a comunicação com o usuário
durante seu processamento (Figura 5.11b). Aqui, os canais de E/S não estão associados
a nenhum dispositivo de E/S interativo, mas em geral a arquivos de E/S. O
processamento batch, por exemplo, é realizado através de processos background.
Quando o canal de saída de um processo estiver associado ao canal de entrada
de outro processo, dizemos que existe um pipe ligando ambos os processos. Por
exemplo, se um processo A gera uma listagem e o processo B tem como função ordenála, basta associar o canal de saída do processo A ao canal de entrada do processo B
(Figura 5.12).
(a) Processo Foreground
entrada
saída
terminal
terminal
(b) Processo Background
entrada
saída
arquivo
de entrada
arquivo
de saída
Fig. 5.11 – Processos foreground e background
70
Apostila Fundamentos de Sistemas Operacionais
.
saída do
Processo A
entrada do
Processo A
saída do
Processo B
entrada do
Processo B
Processo A
Processo B
Figura 5.12 – Pipe
5.8 Processos do Sistema Operacional:
O conceito de processo, além de estar associado a aplicações de usuários, podem
também ser implementados na própria arquitetura do SO. Como visto em capítulo
anterior, a arquitetura microkernel implementa uso intensivo de processos que
disponibilizam serviços para processos das aplicações e do próprio SO.
Quando processos são utilizados para a implementação de serviços do sistema,
estamos retirando códigos de seu núcleo, tornando-o menor e mais estável. No caso de
um ou mais serviços não serem desejados, basta não ativar os processos responsáveis,
o que permitirá liberar memória para os processos dos usuários.
Alguns serviços que o SO pode implementar através de processos são:









auditoria e segurança;
serviços de rede;
contabilização do uso de recursos;
contabilização de erros;
gerência de impressão;
gerência de jobs match;
temporização;
comunicação de eventos;
interface de comandos.
71
Apostila Fundamentos de Sistemas Operacionais
.
5.9 Processos CPU-Bound e I/O-Bound:
Os processos podem ser classificados como CPU-Bond ou I/O-Bond, de acordo
com a utilização do processador e dos dispositivos de E/S.
Um processo é definido como CPU-Bound (ligado à CPU), quando passa a maior
parte do tempo no estado de execução, ou seja, utilizando o processador (Figura 5.13a).
Este tipo de processo realiza poucas operações de leitura e gravação e é encontrado em
aplicações científicas que efetuam muitos cálculos.
Por outro lado, um processo I/O-Bound (ligado à E/S) passa a maior parte do
tempo no estado de espera, pois realiza grande número de operações de E/S (Figura
5.13b). Aplicações comerciais, que se baseiam em leitura, processamento e gravação
são exemplos de processos deste tipo, assim como também os processos interativos,
pela forma de comunicação entre o usuário e o sistema, normalmente lenta, devido ao
uso de terminais.
E/ S
E/ S
UCP
UCP
tempo
(a) CPU-bound
tempo
(b) I/ O-bound
Fig. 5.13 – Processos CPU-bound x I/O-bound
72
Apostila Fundamentos de Sistemas Operacionais
.
5.10 Sinais:
Sinais são um mecanismo que permite notificar processos de eventos gerados
pelo sistema operacional ou por outros processos. O uso de sinais é fundamental para a
gerência de processos, além de possibilitar a comunicação e sincronização entre
processos.
Por exemplo, ao se teclar simultaneamente as teclas Ctrl e C, para interromper
um programa, o SO gera um sinal ao processo, sinalizando a ocorrência do evento. O
processo identificando o sinal, uma rotina especial de tratamento é executada (Figura
5.14).
interrupção
sinal
Sistema Operacional
[ctrl-C]
Fig. 5.14 – Uso de Sinais
Processo
Os sinais podem ser usados em conjunto com temporizadores com a intenção de
sinalizar ao processo algum evento associado ao tempo. Por exemplo, um processo que
deve ser avisado periodicamente sobre uma tarefa a realizar, como monitorar uma fila
de pedidos. Após a realização da tarefa, o processo retorna à espera do próximo sinal.
A maior parte dos eventos associados a sinais são gerados pelo SO ou pelo
hardware, como as exceções, interrupções, limites de quotas excedidos e alarmes de
tempo. Em outros casos, os eventos são gerados a partir de outros processos com o
propósito de sincronizar suas execuções.
A geração de um sinal ocorre quando o SO, a partir da ocorrência de eventos
síncronos ou assíncronos, notifica o processo através de bits de sinalização localizados
no seu PCB. Um processo não responde instantaneamente a um sinal. Os sinais ficam
pendentes até que o processo seja escalonado, quando então serão tratados. Por
exemplo, na eliminação de um processo, o sistema ativa o bit associado a este evento. O
processo só será excluído do sistema quando for selecionado para execução. Assim, é
possível que o processo demore algum tempo até ser eliminado de fato.
O tratamento de um sinal é bem semelhante ao de uma interrupção. Quando um
sinal é tratado, o contexto do processo é salvo e a execução desviada para um código de
tratamento de sinal (signal handler), geralmente no núcleo do SO. Após a execução do
73
Apostila Fundamentos de Sistemas Operacionais
.
tratador de sinais, o programa pode voltar a ser processado do ponto onde foi
interrompido. Às vezes, o próprio processo pode tratar o sinal através de um tradutor de
sinais definido no código do programa. É possível também que um processo bloqueie
temporariamente ou ignore por completo alguns sinais.
Apesar do mecanismo ser parecido com o do tratamento de interrupções e
exceções, os propósitos são diferentes. O sinal está para o processo assim como as
interrupções e exceções estão para o sistema operacional (Figura 5.15)
Processo
Processo
Sinais
Sistema Operacional
Interrupções
Exceções
Hardware
Fig. 5.15 – Sinais, interrupções e exceções.
74
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 6
THREAD
6.1 Introdução:
Até o final dos anos 70, os SOs suportavam processos com apenas um thread
(monothread), ou seja, um processo com apenas um programa fazendo parte de seu
contexto. Em 1979, introduziu-se o conceito de processos “ligthweight” (peso leve),
onde o espaço de endereçamento de um processo era compartilhado por vários
programas. Porém, esta idéia não foi utilizada comercialmente, e apenas na metade da
década de 80, com o SO Mach, ficou clara a separação entre os conceitos de processo e
thread.
Com o conceito de múltiplos threads (multithread), pode-se projetar aplicações
concorrentes de forma eficiente, pois um processo pode ter diferentes partes de seu
código sendo executadas em paralelo. Como os threads de um mesmo processo
compartilham o mesmo espaço de endereçamento, a comunicação entre threads não
envolve mecanismos lentos de intercomunicação entre processos, aumentando assim o
desempenho da comunicação.
O desenvolvimento de programas que exploram os benefícios da programação
multithread não é simples. A presença do paralelismo introduz um novo conjunto de
problemas, como a comunicação e sincronização de threads. Existem diferentes modelos
para a implementação de threads em um SO, onde desempenho, flexibilidade e custos
devem ser avaliados.
Atualmente, o conceito de multithread pode ser encontrado em sistemas como
Sun Solaris e Windows 2000. A utilização comercial de sistemas multithreads tem
crescido devido ao aumento de popularidade de sistemas com multiprocessadores, do
modelo cliente-servidor w dos sistemas distribuídos.
6.2 Ambiente Monothread:
Um programa é uma seqüência de instruções, compostas de desvios, repetições e
chamadas a procedimentos e funções. Em um ambiente monothread, um processo
suporta apenas um programa em seu espaço de endereçamento. Neste ambiente,
aplicações concorrentes são implementadas apenas com o uso de múltiplos processos
independentes ou subprocessos.
O uso de processos independentes e subprocessos permite dividir uma aplicação
em partes que podem trabalhar de forma concorrente. Por exemplo, um usuário pode
estar lendo seus e-mails antigos, ao mesmo tempo em que estaria enviando e
recebendo e-mails atuais. Co o uso de múltiplos processos, cada funcionalidade do
software implicaria na criação de um novo processo para atendê-lo, aumentando o
desempenho da aplicação (Figura 6.1).
75
Apostila Fundamentos de Sistemas Operacionais
.
Um problema é que o uso de processos no desenvolvimento de aplicações
concorrentes demanda consumo de diversos recursos do sistema. Sempre que um novo
processo é criado, o sistema deve alocar recursos para cada processo, consumindo
tempo de processador neste trabalho. No caso do término do processo, o sistema
dispensa tempo para desalocar recursos previamente alocados.
Outro problema a ser considerado é quanto ao compartilhamento do espaço de
endereçamento. Como cada processo possui seu próprio espaço de endereçamento, a
comunicação entre processos torna-se difícil e lenta, pois utiliza mecanismos como pipes,
sinais, semáforos, memória compartilhada ou troca de mensagem. Além disso, o
compartilhamento de recursos comuns aos processos concorrentes, como memória e
arquivos abertos, não é simples. Na Figura 6.2 existem três processos monothread, cada
um com seu próprio contexto de hardware, de software e espaço de endereçamento.
Subprocessos
Processos Independentes
Fig. 6.1 – Concorrência com subprocessos e processos independentes
São exemplos de sistemas monothread o MS-DOS e as primeiras versões do
Windows. Mesmo em ambientes multiprogramáveis e multiusuários, encontra-se
exemplos de implementações monothread, como nas versões mais antigas dos sistemas
VAX/VMS e Unix.
Thread
Thread
Thread
Fig. 6.2 – Ambiente monothread
76
Apostila Fundamentos de Sistemas Operacionais
.
6.3 Ambiente Multithread:
Em um ambiente multithread, ou seja, com múltiplos threads, não existe a idéia
de programas associados a processos, mas sim a threads. O processo, neste ambiente,
tem pelo menos um thread em execução, mas pode compartilhar o seu espaço de
endereçamento com inúmeros outros threads. Na Figura 6.3 existe apenas um processo
com três threads de execução compartilhando o mesmo espaço de endereçamento.
Contexto
de hardware
Contexto
de hardware
Thread 1
Thread 2
Thread 3
Contexto de
software
Contexto
de hardware
Espaço de
endereçamento
Fig. 6.3 – Ambiente Multithread
De forma simplificada, um thread pode ser definido como uma sub-rotina de um
programa que pode ser executada de forma assíncrona, ou seja, executada
paralelamente ao programa chamador. O programador deve especificar os threads,
associando-os às sub-rotinas assíncronas. Assim, um ambiente multithread possibilita a
execução concorrente de sub-rotinas dentro de um mesmo processo.
Na Figura 6.4 existe um programa principal que realiza a chamada de suas subrotinas assíncronas (Sub_1 e Sub_2). Inicialmente, o processo é criado apenas com o
Thread_0 para a execução do programa principal. Quando o programa principal chama
as duas sub-rotinas, são criados os Thread_1 e Thread_2, e executados
independentemente do programa principal. Neste processo, os três threads são
executados concorrentemente.
77
Apostila Fundamentos de Sistemas Operacionais
.
No ambiente multithread, cada processo pode responder a varias solicitações
concorrentemente ou mesmo simultaneamente, caso haja mais de um processador. A
grande vantagem no uso de threads é a possibilidade de minimizar a alocação de
recursos do sistema, alem de diminuir o overhead na criação, troca e eliminação de
processos.
Threads compartilham o processador da mesma maneira que processos e passam
pelas mesmas mudanças de estado (execução, espera e pronto). Por exemplo, enquanto
um thread espera por uma operação de E/S, outro thread pode ser executado. Para
permitir a troca de contexto entre os diversos threads, cada um possui seu próprio
contexto de hardware, com o conteúdo dos registradores gerais, PC e SP. Quando um
thread está sendo executado, seu contexto hardware está armazenado nos registradores
do processador. No momento em que o thread perde a utilização do processador, as
informações são atualizadas no seu contexto de hardware.
Processo
Variáveis
Programa Principal
Thread_1
PC
SP
Contexto de
Hardware
...
Espaço de
endereçamento
Call Sub_1
Thread_2
Sub_1
Ret
PC
SP
Thread_3
Sub_2
PC
SP
Contexto de
Hardware
Fim
Contexto de
Hardware
Call Sub_2
...
Ret
Fig. 6.4 – Aplicação Multithread (a)
78
Apostila Fundamentos de Sistemas Operacionais
.
Dentro de um mesmo processo, threads compartilham o mesmo contexto de
software e espaço de endereçamento com os demais threads, porém cada thread possui
seu contexto de hardware individual. Threads são implementados internamente através
de uma estrutura de dados denominada bloco de controle do thread (Thread Control
Block – TCB). O TCB armazena, além do contexto de hardware, mais algumas
informações relacionadas exclusivamente ao thread, como prioridade, estado de
execução e bits de estado.
Em ambientes monothread, o processo é ao mesmo tempo a unidade de alocação
de recursos e a unidade de escalonamento. A independência entre os conceitos de
processo e thread permite separar a unidade de alocação de recursos da unidade de
escalonamento, que em ambientes monothread estão fortemente relacionadas. Em um
ambiente multithread, a unidade de alocação de recursos é o processo, onde todos os
seus threads compartilham o espaço de endereçamento, descritores de arquivos de
dispositivos de E/S. Por outro lado, cada thread representa uma unidade de
escalonamento independente. Neste caso, o sistema não seleciona um processo para a
execução, mas sim um de seus threads.
A grande diferença entre aplicações mono e multithread está no uso do espaço de
endereçamento. Processos independentes e subprocessos possuem espaços de
endereçamento individuais e protegidos, enquanto threads compartilham o espaço
dentro de um mesmo processo. Isso permite que o compartilhamento de dados entre
threads de um mesmo processo seja mais simples e rápido, se comparado a ambientes
monothreads.
Como threads de um mesmo processo compartilham o mesmo espaço de
endereçamento, não existe qualquer proteção no acesso à memória, permitindo que um
thread possa alterar facilmente dados de outros. Para que os threads trabalhem de
forma cooperativa, é fundamental que a aplicação implemente mecanismos de
comunicação e sincronização entre threads, a fim de garantir o acesso seguro aos dados
compartilhados na memória.
O uso de multithreads proporciona uma serie de benefícios. Programas
concorrentes com múltiplos threads são mais rápidos do que programas concorrentes
implementados com múltiplos processos, pois operações de criação, troca de contexto e
eliminação dos threads geram menor overhead (Tabela 6.1). Como os threads dentro de
um processo dividem o mesmo espaço de endereçamento, a comunicação entre eles
pode ser realizada de forma rápida e eficiente. Além disso, threads em um mesmo
processo podem compartilhar facilmente outros recursos, como descritores de arquivos,
temporizadores, sinais, atributos de segurança, etc.
79
Apostila Fundamentos de Sistemas Operacionais
.
Implementação
Tempo de criação (μs)
Processo
Processo Lightweight
Thread
1700
350
52
Tempo de sincronização
(μs)
200
390
66
Tabela 6.1 – Latência de Processos e Threads
A utilização do processador, dos discos e outros periféricos pode ser feita de
forma concorrente pelos diversos threads, significando melhor utilização dos recursos
computacionais disponíveis. Em algumas aplicações, a utilização de threads pode
melhorar o desempenho da aplicação apenas executando tarefas em background
enquanto operações E/S estão sendo processadas (Figura 6.5). Aplicações como editores
de texto, planilhas, aplicativos gráficos e processadores de imagem são especialmente
beneficiados quando desenvolvidos com base em threads.
Em ambientes cliente-servidor, threads são essenciais para solicitação de serviços
remotos. Em um ambiente monothread, se uma aplicação solicita um serviço remoto, ela
pode ficar esperando indefinidamente, enquanto aguarda pelo resultado. Em um
ambiente multithread, um thread pode solicitar o serviço remoto, enquanto a aplicação
pode continuar realizando outras atividades. Já para o processo que atende a solicitação,
múltiplos threads permitem que diversos pedidos sejam atendidos simultaneamente
(Figura 6.6).
Thread de
entrada
Buffer
Thread de
exibição
Thread de
gravação
Fig. 6.5 – Aplicação Multithread (b)
80
Apostila Fundamentos de Sistemas Operacionais
.
Processo servidor
Solicitações
Thread
Thread
Thread
Processo cliente
Processo cliente
Processo cliente
Fig. 6.6 – Aplicação multithread (c)
Não apenas aplicações tradicionais podem fazer uso dos benefícios do
multithreading. O núcleo do SO também pode ser implementado com o uso desta
técnica de forma vantajosa, como na arquitetura microkernel, apresentada em capítulo
anterior.
81
Apostila Fundamentos de Sistemas Operacionais
.
6.4 Arquitetura e Implementação:
O conjunto de rotinas disponíveis para que uma aplicação utilize as facilidades dos
threads é chamado de pacote de threads. Existem diferentes abordagens na
implementação deste pacote em um SO, o que influenciará no desempenho, na
concorrência e na modularidade das aplicações multithread.
Threads podem ser oferecidos por uma biblioteca de rotinas fora do núcleo do SO
(modo usuário), pelo próprio núcleo do sistema (modo kernel), por uma combinação de
ambos (modo híbrido) ou por um modelo conhecido como “scheduler activations”. A
Tabela 6.2 resume as diversas arquiteturas para diferentes ambientes operacionais.
Ambientes
Distributed Computing Environment (DCE)
Compaq Open VMS versão 6
MS Windows 2000
Compaq Unix
Compaq Open VMS versão 7
Sun Solaris versão 2
University of Washington FastThreads
Arquitetura
Modo Usuário
Modo Usuário
Modo Kernel
Modo Kernel
Modo Kernel
Modo Híbrido
Scheduler Activations
Tabela 6.2 – Arquitetura de threads para diversos ambientes operacionais
Uma das grandes dificuldades para a utilização de threads foi a ausência de um
padrão. Em 1995, o padrão POSIX P1003.1c foi aprovado e posteriormente atualizado
para a versão POSIX 1003.4 a. Com este padrão, também conhecido como Pthreads,
aplicações comerciais multithreading tornaram-se mais simples e de fácil implementação.
O padrão Pthreads é largamente utilizado em ambientes Unix, como o Sun Solaris
Pthreads e o DECthreads para Digital OSF/1.
6.4.1 Threads em Modo Usuário:
Threads em modo usuário (TMU) são implementados pela aplicação e não pelo
SO. Para isso, deve existir uma biblioteca de rotinas que possibilite a aplicação realizar
tarefas como criação/eliminação de threads, troca de mensagens entre threads e uma
política de escalonamento. Neste modo, o SO não sabe da existência de múltiplos
threads, sendo responsabilidade exclusiva da aplicação gerenciar e sincronizar os
diversos threads existentes.
A vantagem deste modelo é a possibilidade de implementar aplicações
multithreads mesmo em SOs que não suportem threads. Utilizando biblioteca, múltiplos
threads podem ser criados, compartilhando o mesmo espaço de endereçamento do
processo, além de outros recursos (Figura 6.7). TMU são rápidos e eficientes por
dispensarem acessos ao kernel do SO, evitando assim a mudança de modo de acesso
(usuário-kernel-usuário).
82
Apostila Fundamentos de Sistemas Operacionais
.
Thread 4
Thread 3
Thread 2
Thread 1
Thread 0
Os TMU possuem uma grande limitação, pois o SO gerencia cada processo como
se existisse apenas um thread. Quando o thread chama uma rotina do sistema que o
coloca em estado de espera (rotina bloqueante), todo o processo é colocado no estado
de espera, mesmo havendo outros threads prontos para execução. Para contornar esta
limitação, a biblioteca tem que possuir rotinas que substituam as rotinas bloqueantes por
outras que não possam causar o bloqueio de um thread (rotinas não-bloqueantes). Todo
este controle é transparente para o usuário e para o SO.
Modo
usuário
Biblioteca
Kernel
Modo
kernel
Figura 6.7 – Threads em modo usuário
Talvez um dos maiores problemas na implementação de TMU seja o tratamento
individual de sinais. Como o sistema reconhece apenas processos e não threads, os
sinais enviados para um processo devem ser reconhecidos e encaminhados a cada
thread para tratamento. No caso do recebimento de interrupções de clock, fundamental
para implementação do tempo compartilhado, esta limitação é crítica. Neste caso, os
sinais de temporização devem ser interceptados, para que se possa interromper o thread
em execução e realizar a troca de contexto.
Em relação ao escalonamento em ambientes com múltiplos processadores, não é
possível que múltiplos threads de um processo possam ser executados em diferentes
processadores simultaneamente, pois o sistema seleciona apenas processos para
execução e não threads. Esta restrição limita drasticamente o grau de paralelismo da
aplicação, já que os threads de um mesmo processo podem ser executados em somente
um processador de cada vez.
83
Apostila Fundamentos de Sistemas Operacionais
.
6.4.2 Threads em Modo Kernel:
Threads em Modo Kernel (TMK) são implementados diretamente pelo núcleo do
SO, através de chamadas a rotinas do sistema que oferecem todas as funções de
gerenciamento e sincronização (Fig. 6.8). O S.O. sabe da existência de cada thread e
pode escaloná-los individualmente. No caso de múltiplos processadores, os threads de
um mesmo processo podem ser executados simultaneamente.
Thread 4
Thread 3
Thread 2
Thread 0
Thread 1
O grande problema para pacotes em modo kernel é o seu baixo desempenho.
Enquanto nos pacotes em modo usuário todo tratamento é feito sem ajuda do SO, ou
seja, sem a mudança do modo de acesso (usuário-kernel-usuário), pacotes em modo
kernel utilizam chamadas a rotinas do sistema e, conseqüentemente, várias mudanças
no modo de acesso. A Tabela 6.3 compara o desempenho de duas operações distintas
envolvendo a criação, escalonamento, execução e eliminação de um processo/thread.
Modo
usuário
Biblioteca
Modo
kernel
Kernel
Figura 6.8 – Threads em Modo Kernel
Implementação
Subprocessos
Threads em Modo Kernel
Threads em Modo Usuário
Operação 1 (μs)
11.300
948
34
Operação 2 (μs)
1.840
441
37
Tabela 6.3 – Comparação entre tempos de latência
84
Apostila Fundamentos de Sistemas Operacionais
.
6.4.3 Threads em Modo Híbrido:
A arquitetura de threads em modo híbrido combina as vantagens de threads
implementados em modo usuário (TMU) e threads em modo kernel (TMK). Um processo
pode ter vários TMKs, e por sua vez, um TMK pode ter vários TMUs. O núcleo do SO
reconhece os TMKs e pode escaloná-los individualmente. Um TMU pode ser executado
em um TMK, em um determinado momento, e no instante seguinte ser executado em
outro.
O programador desenvolve a aplicação em termos de TMU e especifica quantos
TMK estão associados ao processo. Os TMUs são mapeados em TMK enquanto o
processo está sendo executado. O programador pode utilizar apenas TMK, TMU ou uma
combinação de ambos (Figura 6.9).
TMU 5
TMU 4
TMU 3
TMU 2
TMU 1
TMU 0
O modo híbrido, apesar de maior flexibilidade, apresenta problemas herdados de
ambas as implementações. Por exemplo, quando um TMK realiza uma chamada
bloqueante, todos os TMUs são colocados no estado de espera. TMUs que desejam
utilizar vários processos deve utilizar diferentes TMKs, o que influenciará no
desempenho.
Modo
usuário
Biblioteca
TMK 0
TMK 1
TMK 2
TMK 3
Modo
kernel
Kernel
Figura 6.9 – Threads em modo híbrido
85
Apostila Fundamentos de Sistemas Operacionais
.
6.4.4 Scheduler Activations:
Os problemas apresentados no pacote de threads em modo híbrido existem
devido à falta de comunicação entre threads em modo usuário e em modo kernel. O
modelo ideal deveria utilizar as facilidades do pacote em modo kernel com o
desempenho e flexibilidade do modo usuário.
Introduzido no início dos anos 90, este pacote combina o melhor das duas
arquiteturas, mas em vez de dividir os threads em modo usuário entre os de modo
kernel, o núcleo do sistema troca informações com a biblioteca de threads utilizando
uma estrutura de dados chamada scheduler activations (Figura 6.10).
Thread 4
Thread 3
Thread 2
Thread 1
Thread 0
A maneira de alcançar um melhor desempenho é evitar as mudanças de modos
de acesso desnecessárias (usuário-kernel-usuário). Caso um thread utilize uma chamada
ao sistema que o coloque no estado de espera, não é necessário que o kernel seja
ativado, bastando que a própria biblioteca em modo usuário escalone outro thread. Isto
é possível porque a biblioteca em modo usuário e o kernel se comunicam e trabalham de
forma cooperativa. Cada camada implementa seu escalonamento de forma
independente, porem trocando informações quando necessário.
Modo
usuário
Biblioteca
Kernel
Modo
kernel
Figura 6.10 – Scheduler activations
86
Apostila Fundamentos de Sistemas Operacionais
.
6.5 Modelos de Programação:
O desenvolvimento de aplicações multithread não é simples, pois exige que a
comunicação e o compartilhamento de recursos entre os diversos threads seja feito de
forma sincronizada para evitar problemas de inconsistências e deadlock. Além das
dificuldades naturais no desenvolvimento de aplicações concorrentes, o procedimento de
depuração é bastante complexo.
Um fator importante em aplicações multithread é o numero total de threads e a
forma como são criados e eliminados. Se uma aplicação cria um numero excessivo de
threads, poderá ocorrer um overhead no sistema, ocasionando uma queda de
desempenho.
Dependendo da implementação, a definição do numero de threads pode ser
dinâmica ou estática. Quando a criação/eliminação é dinâmica, os threads são
criados/eliminados conforme a demanda da aplicação, oferecendo grande flexibilidade.
Já em ambientes estáticos, o número de threads é definido na criação do processo onde
a aplicação será executada.
Para obter os benefícios do uso de threads, uma aplicação deve permitir que
partes diferentes de seu código sejam executadas em paralelo de forma independente.
Se um aplicativo realiza várias operações de E/S e trata eventos assíncronos, a
programação multithread aumenta seu desempenho até mesmo em ambientes com um
fraco processador. Sistemas gerenciadores de banco de dados (SGBDs), servidores de
arquivo ou impressão são exemplos onde o uso de múltiplos threads proporciona
grandes vantagens e benefícios.
87
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 7
Sincronização e Comunicação entre processos
7.1 Introdução:
Com o surgimento dos SOs multiprogramáveis, tornou-se possível estruturar
aplicações de maneira que partes diferentes do código do programa pudessem ser
executadas concorrentemente. Este tipo de aplicação foi denominada de aplicação
concorrente.
Em sistemas com um único processador, os processos alternam sua execução
segundo escalonamento estabelecido pelo SO e mesmo assim aplicações concorrentes
obtêm melhoras em seu desempenho. Em sistemas com múltiplos processadores,
estendem-se estas vantagens com a possibilidade do paralelismo na execução de
instruções.
Os processos de uma aplicação concorrente podem compartilhar recursos, como
arquivos registros, dispositivos de E/S e áreas de memória. Este compartilhamento pode
gerar situações indesejáveis, capazes de comprometer a execução das aplicações. Para
evitar este tipo de problema, os processos devem ter suas ações sincronizadas, através
de mecanismos oferecidos pelo SO.
7.2 Aplicações Concorrentes:
Em aplicações concorrentes, pode ser necessário que os processos comuniquemse entre si. Esta comunicação pode ser implementada através de variáveis
compartilhadas na memória principal ou trocas de mensagens. Mais uma vez, é
necessário que haja sincronização entre a execução dos processos concorrentes.
A figura 7.1 apresenta um exemplo onde dois processos concorrentes
compartilham um buffer para troca de informações. Aqui, um processo só poderá gravar
dados no buffer se ele estiver vazio, e só poderá ler um dado do buffer caso haja um
dado a ser lido. Em ambos os casos, os processos deverão esperar até que o buffer
esteja pronto para as operações de gravação e leitura.
Sincronização
gr
Processo
gravador
av
aç
ão
i tu
le
ra
Processo
leitor
dado
Buffer
Figura 7.1 – Sincronização e Comunicação entre processos
88
Apostila Fundamentos de Sistemas Operacionais
.
Os mecanismos que realizam a comunicação entre processos concorrentes e o
acesso a recursos compartilhados são chamados de mecanismos de sincronização. Em
SOs multiprogramáveis estes mecanismos são fundamentais para garantir a integridade
e confiabilidade na execução de aplicações concorrentes.
7.3 Especificação de Concorrência em Programas:
Existem varias notações para especificar quais partes de um programa que devem
ser executadas concorrentemente. Técnicas mais recentes tentam expressar a
concorrência no código dos programas de uma forma mais clara e estruturada.
As primeiras notações para especificar uma concorrência em um programa foram
os comandos FORK e JOIN. O exemplo abaixo exemplifica de forma simplificada este
uso.
PROGRAMA A;
.
.
FORK B;
.
.
JOIN B;
.
.
END.
END.
PROGRAMA B;
.
.
.
.
.
O Programa A começa a ser executado e, ao encontrar o comando FORK, faz com
que seja criado um outro processo para execução do Programa B, concorrentemente ao
Programa A. O comando JOIN faz com que o Programa A sincronize-se com o B, ou seja,
o Programa A só continuará a ser executado após o término da execução de B. Os
comandos FORK e JOIN são poderosos e práticos, sendo utilizados de forma semelhante
no Sistema Unix.
Outra forma mais clara e simples de expressar concorrência em um programa é
com o uso dos comandos PARBEGIN e PAREND (1965), que posteriormente foram
chamados de COBEGIN e COEND. Aqui continuaremos a utilizar os comandos PARBEGIN
e PAREND.
A figura 7.2 demonstra o uso dos comandos PARBEGIN e PAREND.
89
Apostila Fundamentos de Sistemas Operacionais
.
Processo
principal
PARBEGIN
Comando_1;
Comando_2;
.
.
Comando_n;
PAREND
Processo 1
Processo 2
Processo n
Processo
principal
Figura 7.2 – Concorrência em programas
Para exemplificar o uso destes comandos, o programa chamado EXPRESSAO
realiza um cálculo do valor da expressão descrita a seguir:
X := SQRT (1024) + (35.4 * 0.23) – (302 / 7)
Os comandos situados entre PARBEGIN e PAREND são executados
concorrentemente. O cálculo final de X só poderá ser realizado quando todas as
variáveis dentro da estrutura estiverem sido calculadas.
PROGRAM Expressao;
VAR X, Temp1, Temp2, Temp3 : REAL;
BEGIN
PARBEGIN
Temp1 := SQRT (1024);
Temp2 := 35.4 * 0.23;
Temp3 := 302 / 7;
PAREND;
X := Temp1 + Temp2 - Temp3;
WRITELN ('x = ', X);
END.
90
Apostila Fundamentos de Sistemas Operacionais
.
7.4 Problemas de Compartilhamento de Recursos:
Para melhor compreensão da importância da sincronização entre processos
concorrentes, são apresentados alguns exemplos-problema de compartilhamento de
recursos.
O primeiro problema é analisado a partir do programa Conta_Corrente, que
atualiza o saldo bancário de um cliente após o lançamento de débito ou crédito no
arquivo de contas-correntes Arq_Contas. Neste arquivo são armazenados os saldos de
todos os correntistas do banco. O programa lê o registro do cliente no arquivo
(Reg_Cliente), lê o valor a ser depositado ou retirado (Valor_Dep_Ret) e, em seguida
atualiza o saldo no arquivo de contas.
PROGRAM Conta_Corrente;
.
.
READ (Arq_Contas, Reg_Cliente);
READLN (Valor_Dep_Ret);
Reg_Cliente.Saldo :=
Reg_Cliente.Saldo + Valor_Dep_Ret;
WRITE (Arq_Contas, Reg_Cliente);
.
.
END.
Considerando processos concorrentes pertencentes a dois funcionários do banco
que atualizam o saldo de um mesmo cliente simultaneamente, a situação de
compartilhamento do recurso pode ser analisada. O processo do primeiro funcionário
(Caixa 1) lê o registro do cliente e soma ao campo Saldo o valor do lançamento de
débito. Antes de gravar o novo saldo no arquivo, o processo do segundo funcionário
(Caixa 2) lê o registro do mesmo cliente, que está sendo atualizado, para realizar outro
lançamento, desta vez de crédito. Independente de qual processo atualize primeiro o
saldo no arquivo, o dado gravado estará inconsistente. Acompanhe:
Caixa
1
1
1
2
2
2
1
2
Comando
READ
READLN
:=
READ
READLN
:=
WRITE
WRITE
Saldo Arquivo
1.000
1.000
1.000
1.000
1.000
1.000
800
1.300
Valor Dep/Ret
*
-200
-200
*
+300
+300
-200
+300
Saldo Memória
1.000
1.000
800
1.000
1.000
1.300
800
1.300
91
Apostila Fundamentos de Sistemas Operacionais
.
Outro exemplo simples é a situação onde dois processos (A e B) executam um
comando de atribuição. O processo A soma 1 à variável X e o processo B subtrai 1 da
mesma variável. Suponha que inicialmente a variável X possua o valor 2.
Processo A
X: = X + 1 ;
Processo B
X: = X – 1;
Seria razoável pensar que no final das operações a variável continuasse valendo
2, porem nem sempre isso será verdade. Decompondo em operações mais elementares,
usando uma linguagem de alto nível, temos:
Processo A
Load x, Ra
Add 1,Ra
Store Ra,x
Processo B
Load x, Rb
Sub 1,Rb
Store Rb,x
Considere que o Processo A carregue o valor de X no Registrador Ra, some 1, e
no momento em que vai armazenar o novo valor de X, seja interrompido. Neste instante,
inicia-se o Processo B, que carrega o valor de X em Rb e subtrai o valor 1. Agora o
Processo B é interrompido e o A volta a ser executado, atribuindo o valor 3 à variável X
e finalizando sua execução. O Processo B retorna sua execução, atribui o valor 1 a X e
sobrepõe o valor anteriormente gravado pelo Processo ª O resultado final será
inconsistente. Resumindo:
Processo
A
A
B
B
A
B
Comando
Load X,Ra
Add 1,Ra
Load X,Rb
Sub 1,Rb
Store Ra,X
Store Rb,X
X
2
2
2
2
3
1
Ra
2
3
*
*
3
*
Rb
*
*
2
1
*
1
Através destes exemplos, conclui-se que quando dois ou mais processos
compartilham um mesmo recurso, alguns mecanismos devem evitar que este tipo de
problema ocorra (conhecidos como race conditions – condições de corrida).
92
Apostila Fundamentos de Sistemas Operacionais
.
7.5 Exclusão Mútua:
Para que sejam evitados problemas desta natureza, onde dois processos
manipulem o mesmo arquivo ou a mesma variável de memória simultaneamente,
enquanto um processo estiver acessando determinado recurso, todos os outros que
queiram acessar esse mesmo recurso deverão esperar. Isso se chama EXCLUSÃO
MUTUA (Mutual Exclusion).
A exclusão mútua deverá agir apenas sobre os processos que estão concorrendo
em um determinado recurso. Quando desenvolvemos um programa, que faça
tratamento de exclusão mútua, este deverá terá uma seção chamada REGIÃO CRÍTICA
(Critical Region). Nesta região existe uma série de procedimentos e protocolos que o
programa deverá fazer para que o sistema operacional libere o recurso para o mesmo.
Toda vez que um processo desejar executar instruções de sua região crítica,
obrigatoriamente devera executar antes um protocolo de entrada nessa região. Da
mesma forma, ao sair da região crítica um protocolo de saída deverá ser executado. A
região critica deve ser sempre usada quando seu programa for fazer uso de recursos
que são passiveis de compartilhamento com algum outro suposto programa na memória.
É nela também que os processos encontram-se em um momento mais critico, pois
qualquer erro ocorrido ali dentro pode fazer com que dois ou mais processos colidam
gerando falhas e derrubando o sistema.
Assim, para garantir a implementação da exclusão mútua, os processos
envolvidos devem fazer acesso aos recursos de forma sincronizada. Diversas soluções
foram criadas com este propósito; porém, ainda existem duas situações que devem ser
evitadas.
7.5.A Starvation:
A primeira situação indesejada é conhecida como starvation (ou espera
indefinida).
Quem determina as prioridades dos processos é o sistema operacional. Neste
caso existem duas formas do sistema operacional determinar qual será a vez de quem.
Ou por escolha aleatória ou por prioridades. Quando a escolha é aleatória, existirá a
probabilidade de um processo nunca ser escolhido. Quando for uma escolha por
prioridades, um processo de menor prioridade nunca receberá o acesso ao recurso, e ai
este processo nunca executará sua rotina.
Uma solução bastante simples é a criação de filas de pedidos de alocação para
cada recurso, utilizando o esquema FIFO (First In First Out). Sempre que um processo
solicita um recurso, o pedido é colocado no final da fila associada ao recurso. Quando o
recurso é liberado, o sistema seleciona o primeiro processo da fila.
93
Apostila Fundamentos de Sistemas Operacionais
7.5.B
.
Sincronização condicional:
Sincronização Condicional é uma situação onde o acesso a um recurso
compartilhado exige a sincronização de processos vinculada a uma condição de acesso.
Quando um recurso não está pronto para ser utilizado, o processo que vai acessar
o recurso ficará em estado de espera até que o mesmo esteja pronto. Existe o risco
deste recurso nunca ficar pronto por já estar com problemas. Ai todo o sistema fica
esperando o recurso resolver sua vida. Um exemplo disto é o caso do uso de Buffers
para leitura e gravação de dados feita pelos processos. Uma possível falha na memória
que impeça o acesso aos buffers e todo o sistema estará parado...
Diversas soluções foram propostas para garantir a exclusão mútua de processos
concorrentes. A seguir, algumas soluções de hardware e software serão apresentadas,
com comentários sobre suas vantagens e desvantagens.
7.5.1 Soluções de Hardware:

Desabilitação de interrupções
Faz com que o processo, antes de entrar em sua região crítica desabilite todas as
interrupções externas e a reabilite após deixar a região critica. Como a mudança de
contexto de processos só pode ser realizada através de interrupções, o processo que as
desabilitou terá acesso exclusivo garantido.
Apesar de simples, esta solução apresenta limitações. Primeiramente, a
multiprogramação fica comprometida, uma vez a concorrência entre processos entre
processos tem como base o uso da interrupção. Um caso mais grave poderia ocorrer
caso um processo desabilitasse as interrupções e não tornasse a habilitá-las. Neste caso,
o sistema provavelmente teria seu funcionamento comprometido.
Em sistemas com múltiplos processadores esta solução torna-se ineficiente devido
ao tempo de propagação quando um processador sinaliza aos demais que as
interrupções devem ser habilitadas ou desabilitadas. Ainda, o mecanismo de clock do
sistema é implementado através de interrupções, portanto esta solução deve ser
implementada com muito critério.
Apesar destas limitações, esta solução pode ser útil quando se deseja que a
execução de parte do núcleo do SO ocorra sem que haja interrupção. Desta forma, o
sistema pode garantir que não ocorrerão problemas de inconsistência em suas
estruturas de dados durante a execução de algumas rotinas.

Instrução test-and-set
Muitos processadores possuem uma instrução especial onde um processo apenas
lê o conteúdo de uma variável, e armazena seu valor em outra área podendo neste caso
fazer todas as manipulações necessárias e devidas sem precisar de prioridades ou
esperar que a variável original seja liberada. Esta instrução é chamada de test-and-set e
94
Apostila Fundamentos de Sistemas Operacionais
.
tem como característica ser executada sem interrupção, ou seja, trata-se de uma
instrução invisível. Assim garante-se que dois processos não manipulem uma variável
compartilhada ao mesmo tempo, possibilitando a implementação da exclusão mútua.
O uso desta instrução especial oferece vantagens, como a simplicidade de
implementação da exclusão mútua em múltiplas regiões críticas e o uso da solução em
arquiteturas com múltiplos processadores. A principal desvantagem é a possibilidade do
starvation, pois a seleção do processo para o acesso ao recurso é arbitrária.
7.5.2 Soluções de software:
Diversos algoritmos foram propostos na tentativa de implementar a exclusão
mútua através de soluções de software. As primeiras soluções tratavam apenas da
exclusão mútua para dois processos e, inicialmente, apresentavam alguns problemas. A
evolução ocorreu até uma solução definitiva para a exclusão mútua para N processos.
Além da exclusão mútua, que soluciona os problemas de compartilhamento de
recursos, existem outros fatores fundamentais para a solução de problemas de
sincronização:
- O número de processadores e o tempo de execução dos processos.
- Um processo fora de sua região crítica não pode impedir que outros processos entrem
em suas próprias regiões críticas.
- Um processo não pode permanecer indefinidamente esperando para entrar em sua
região crítica.
Todas as soluções que foram apresentadas para contornar estes inconvenientes
apresentavam problemas da ESPERA OCUPADA, Na espera ocupada, todas vezes que
um processo tenta entrar em sua região crítica ele são impedidas por já existir um outro
processo usando o recurso, fazendo o sistema ficar parado esperando que o mesmo
tenha acesso a este respectivo recurso.
7.6 Semáforos:
O conceito de semáforos foi proposto em 1965, sendo apresentado como um
mecanismo de sincronização que permitia implementar, de forma simples, a exclusão
mútua sincronização condicional entre processos.
O semáforo é uma variável que fica associada a um recurso compartilhado,
indicando quando este está sendo acessado por um outro processo. Ela terá seu valor
alterado quando o processo entra e quando sai da região crítica de forma que se um
outro processo entrar em sua região critica ele possa checar antes este valor para saber
se o recurso esta ou não disponível. Quando o processo tiver seu acesso impedido, ele
será colocado em uma fila de espera associada ao semáforo aguardando sua vez de
utilizar o recurso. Todos os processos da fila terão acesso ao recurso na ordem de
chegada. O semáforo pode ser usado também para implementar sincronizações
condicionais. Isto consiste em um processo que necessita ser notificado sobre a
95
Apostila Fundamentos de Sistemas Operacionais
.
ocorrência de um evento. Pode-se usar o semáforo para notificar este processo sobre a
ocorrência deste evento.
Outro tipo de semáforo usado é SEMÁFORO CONSUMIDOR onde ele pode
informar ao processo se o buffer está cheio ou está vazio.
SEMÁFORO CONTADOR é aquele que notifica os processos sobre o uso dos
recursos. Sempre que um processo usa um recurso qualquer, este semáforo é
incrementado sempre que um processo liberar um recurso ele será decrementado. Este
semáforo é útil para evitar que um processo na região crítica sem que haja recursos
disponíveis no sistema.
O uso de semáforos exige do programador muito cuidado, pois qualquer engano
pode gerar bugs em seu programa que o levem a falhas de sincronização ocasionando
quedas e travamento geral do sistema.
DO
0)
D
O
=
(S
W
N
(S
>
N
W
0)
Processo deseja entrar
na região crítica
UP (S) - processo sai
da região crítica
Libera processo
da fila de espera
Processo acessa
a região crítica
Fila de espera
de processos
Fig. 7.3 – Utilização do semáforo binário na exclusão mútua
96
Apostila Fundamentos de Sistemas Operacionais
.
7.7 Monitores:
Monitores são mecanismos de sincronização de alto nível que tornam mais
simples o desenvolvimento de aplicações concorrentes. Este conceito foi proposto em
1972.
Basicamente, são mecanismos de sincronização compostos de um conjunto de
procedimentos, variáveis e estrutura de dados definidos dentro de um módulo cuja
finalidade é a implementação automática da exclusão mútua entre seus procedimentos.
Somente um processo pode estar executando um dos procedimentos do monitor em um
determinado instante. Toda vez que um processo chamar um destes procedimentos, o
monitor verifica se já existe outro processo executando algum procedimento do monitor.
Caso exista, o processo fica aguardando a sua vez ate que tenha permissão para
executá-lo.
A implementação da exclusão mútua nos monitores é realizada pelo compilador
do programa e não mais pelo programador. Para isto ele irá colocar todas as regiões
críticas do programa em forma de procedimentos no monitor e o compilador se
encarregará de garantir a exclusão mútua destes procedimentos. A comunicação do
processo com o monitor passa a ser feita através de chamadas a seus procedimentos e
dos parâmetros passados para eles.
Outra característica do monitor é que os processos, quando não puderem acessar
estes procedimentos, ficarão aguardando em uma fila de espera e enquanto isto, eles
poderão executar outros procedimentos.
Como ele é escrito em uma linguagem de programação, o compilador das outras
demais linguagens deverão ser capazes de reconhecê-la e implementá-la. São raras as
linguagens que permitem tal implementação criando uma limitação para o uso deste
recurso.
Declaração de
variáveis globais
Procedimentos
Monitor
Proc. 1
Proc. 2
Fila de entrada
Proc. n
Inicialização
de variáveis
Fig. 7.4 – Estrutura do monitor
97
Apostila Fundamentos de Sistemas Operacionais
.
7.8 Troca de mensagens:
A troca de mensagens é um mecanismo de comunicação e sincronização entre os
processos, implementado pelo sistema operacional através de duas rotinas do sistema
SEND e RECEIVE. A rotina SEND é a responsável pelo envio de uma mensagem para o
processo receptor enquanto a rotina RECEIVE por receber a mensagem do processo
transmissor. Tais procedimentos mesmo não sendo mutuamente exclusivos permitem a
comunicação entre os processos e a sincronização entre eles, pois uma mensagem
somente poderá ser lida depois de ter sido enviada e ela somente será envidada após a
ocorrência de um evento.
No sistema de troca de mensagens, existe a possibilidade da mensagem se
perder. Para isto foi implementado o recurso de que o processo receptor ao recebê-la
deverá enviar ao processo transmissor uma mensagem de recebimento. Caso o
transmissor não receber esta mensagem em um certo espaço de tempo ele irá
retransmitir esta mensagem.
A comunicação entre processos pode ser feita diretamente. Bastando que o
processo que deseja enviar uma mensagem enderece explicitamente o nome do
receptor. Esta característica chama-se ENDEREÇAMENTO DIRETO e só é permitida à
comunicação entre dois processos.
Existe também o ENDEREÇAMENTO INDIRETO que é um mecanismo que consiste
no uso de uma área compartilhada, onde as mensagens podem ser colocadas pelo
processo transmissor e retiradas por qualquer processo.
Existem duas formas de comunicação entre os processos: COMUNICAÇÃO
SINCRONA e COMUNICAÇÃO ASSINCRONA. Uma comunicação é dita Síncrona, quando
um processo envia uma mensagem e fica esperando até que o processo receptor leia a
mensagem e mande a notificação de recebimento. Uma comunicação assíncrona é
aquela em que o processo que envia a mensagem não espera notificação de
recebimento.
Processo A
Processo B
Fig. 7.5 – Comunicação direta
98
Apostila Fundamentos de Sistemas Operacionais
Processo A
.
Processo B
Mailbox
ou Port
Fig. 7.6 – Comunicação indireta
7.9 Deadlock:
O Deadlock existe em qualquer sistema multiprogramável. Dizemos que um
processo está em Deadlock quando este para de responder porque está esperando por
um evento que nunca ocorrerá. Esta situação é conseqüência do problema da exclusão
mútua. Existem as condições onde o Deadlock irá ocorrer:
- Cada recurso só pode estar alocado a um único processo em um determinado instante.
(Exclusão mútua)
- Um processo além dos recursos já alocados, pode estar esperando por outros recursos.
- Um recurso não pode ser liberado de um processo porque outros processos desejam o
mesmo recurso (Não-preempção)
- Um processo pode ter de esperar por um recurso alocado a outro processo e vice-versa
(Espera circular).
Processo A
Processo A
solicita o
Recurso 2
Recurso 1
alocado ao
Processo A
Recurso 2
Recurso 1
Processo B
Recurso 2
alocado ao
Processo B
Processo B
solicita o
Recurso 1
Fig. 7.7 – Espera circular
99
Apostila Fundamentos de Sistemas Operacionais
.
7.9.1 Prevenção do Deadlock:
Para prevenir o Deadlock é preciso garantir que uma das quatro condições acima
citada nunca ocorra, dentre as diversas situações já citadas pode ser feito um minucioso
trabalho de determinar muito bem que recursos, quais recursos e quando estes recursos
deverão ser disponibilizados aos processos.
7.9.2 Detecção de Deadlock:
Em sistemas que não possuam mecanismos que previnam a ocorrência de
deadlocks, é necessário um esquema de detecção e correção do problema. A Detecção
do Deadlock é um mecanismo que determina a existência deste e identifica os recursos
envolvidos no problema. Um exemplo deste tipo de detector é o próprio Gerenciador de
tarefas do Windows que detecta o aplicativo que parou de responder ao sistema
causado, possivelmente, por um deadlock, como podemos ver logo abaixo:
Fig. 7.8 – Exemplo de Deadlock
7.9.3 Correção do Deadlock:
Geralmente o problema é resolvido eliminando os processos envolvidos e
desalojando os recursos para ele já garantidos. É aquele processo em que você dá um
Alt+Ctrl+Del no Windows e aparece uma janela informando o aplicativo que não
responde. Este aplicativo pode estar em um processo de Deadlock, neste caso você
manda finalizar o aplicativo e tudo voltará ao normal. Muitas vezes este mecanismo não
resolve e pelo contrário gera novos problemas. Se você finalizar um processo que esteja
100
Apostila Fundamentos de Sistemas Operacionais
.
intimamente envolvido com o sistema operacional ou que esteja usando recursos de
baixo nível do mesmo, você poderá vir a deixá-lo instável ou travado.
Abaixo vemos a caixa de dialogo do Windows que tentará fechar o processo que
pode estar parado por falta de comunicação com o sistema.
Fig. 7.9 – Correção do Deadlock
O problema do Deadlock é um problema que tende a tornar-se mais critico à
medida que os sistemas operacionais evoluem no sentido de implementar o paralelismo
e permitir a alocação dinâmica de um numero maior de recursos e a execução de um
numero maior de processos simultaneamente. Os usuários sentem muita saudade dos
computadores que rodavam o DOS nos bons tempos quando quase não davam
problemas. Mas é bom lembrar que o DOS era um sistema operacional monotarefa e
monousuário onde praticamente tínhamos apenas um único processo rodando de cada
vez. Neste caso não existiam os problemas que um ambiente multitarefa e multiusuário
tem hoje. Todos os recursos do sistema estavam exclusivamente disponíveis para aquele
processo e, portanto ele tinha total e plena liberdade de fazer com estes o que bem
entendia.
Hoje os sistemas operacionais são mais complexos rodando em maquinas mais
críticas devido à velocidade de processamento tendo um maior numero de aplicações
que rodam simultaneamente e demandando praticamente todos os recursos do sistema
ao mesmo tempo. Muitos destes programas trabalham não só com um, mas com vários
processos simultaneamente o que aumentam as chances de colisões entre eles ou com
os recursos do sistema.
101
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 8
Gerência do Processador
8.1 Funções:
Com o surgimento dos sistemas multiprogramáveis, onde múltiplos processos
poderiam permanecer na memória e disputar o uso de um único processador, a gerência
do processador tornou-se uma das atividades mais importantes em um sistema
operacional.
A partir do momento em que vários processos podem estar no estado de pronto,
devem ser estabelecidos critérios para definir qual processo será escolhido para fazer
uso do processador. Tais critérios compõem a política de escalonamento, que é a base
da gerência do processador e da multiprogramação em um sistema operacional.
Dentre as funções da gerência do processador, podemos citar: manter o
processador ocupado a maior parte do tempo. balancear o uso da CPU entre processos,
privilegiar a execução de aplicações críticas, maximizar o throughput e oferecer tempos
de resposta razoáveis aos usuários interativos.
Cada sistema operacional possui sua política de escalonamento adequada ao seu
propósito e às suas características. Sistemas de tempo compartilhado, por exemplo,
possuem requisitos de escalonamento distintos dos sistemas de tempo real.
8.2
Critérios de escalonamento:
-
Utilização do processador: corresponde a uma taxa de utilização, que na
maioria dos sistemas varia entre 30 e 90%. Uma utilização abaixo dos 30%
indicaria um sistema ocioso, com carga de processamento baixa, enquanto uma
taxa de utilização acima dos 90% pode indicar um sistema bastante carregado,
próximo da sua capacidade máxima (em alguns casos tal situação pode levar a
um crash – travamento do sistema).
-
Throughput: é o número de processos executados em um determinado intervalo
de tempo. Quanto maior o throughput, maior o número de tarefas executadas em
função do tempo. A maximização do throughput é desejada na maioria dos
sistemas.
-
Tempo de Processador: é o tempo que um processo leva no estado de
execução, durante seu processamento. As políticas de escalonamento não
interferem neste parâmetro, sendo este tempo função apenas do código
executável e da entrada/saída de dados.
102
Apostila Fundamentos de Sistemas Operacionais
.
-
Tempo de Espera (pela CPU): é todo o tempo que o processo permanece na
fila de pronto, aguardando a liberação da CPU para ser executado. A redução
deste tempo de espera é desejada pela maioria das políticas de escalonamento.
-
Tempo de Turnaround: é o tempo total que o processo permaneceu no
sistema, desde sua criação até o momento em que é encerrado. São contados os
tempos de alocação de memória, espera na fila de pronto e interrupção (E/S).
-
Tempo de Resposta: é o tempo decorrido entre uma requisição ao sistema e o
instante em que a resposta começa a ser exibida. Em sistemas interativos, como
aplicações on-line ou acesso à Web, os tempos de resposta devem ser da ordem
de apenas poucos segundos.
8.3
Escalonamentos Não-Preemptivos e Preemptivos:
Escalonamentos do tipo não-preemptivos são aqueles onde o sistema operacional
não pode interromper o processo em execução para retirá-lo da CPU. Assim sendo, se
nenhum evento externo ocorresse durante a execução do processo, este permanecia na
CPU até terminar ou então alguma instrução do próprio programa o desviasse para o
estado de espera (operação de E/S).
Já os escalonamentos preemptivos são caracterizados pela possibilidade de o
sistema operacional interromper o processo em execução para retirá-lo da CPU e dar
lugar a outro. Neste caso o processo retirado da CPU volta ao estado de pronto, onde
permanece aguardando nova oportunidade de ocupar a CPU. Com o uso da preempção,
é possível ao sistema priorizar a execução de processos, como no caso de aplicações
em tempo real. Outro benefício é a possibilidade de implementar políticas de
escalonamento que compartilhem o processador de uma maneira mais uniforme,
balanceando o uso da CPU entre os processos.
São escalonamentos não-preemptivos:
-
FIFO: o processo que chegar primeiro à fila de pronto é selecionado para
execução, e permanece utilizando o processador até terminar sua execução ou
ser interrompido por E/S. Neste caso, o próximo processo da fila de pronto é
selecionado para execução. Todo processo que chega à fila de pronto entra no
final desta fila, conservando a ordem de chegada na fila, até ser escalonado
novamente. Apesar de simples, este escalonamento apresenta algumas
deficiências, principalmente no que diz respeito à dificuldade de se prever o início
da execução de um processo, já que a ordem de chegada á fila de pronto deve
ser observada à risca. Outro problema é quanto aos tipos de processo, onde os
CPU-bound levam vantagem no uso do processador em relação aos do tipo I/Obound, pois o sistema não trata este tipo de diferença. O escalonamento FIFO foi
inicialmente implementado em sistemas monoprogramáveis, sendo ineficiente se
aplicado em sistemas interativos de tempo compartilhado.
103
Apostila Fundamentos de Sistemas Operacionais
.
Abaixo, um exemplo de escalonamento utilizando o método FIFO: a ordem de
chegada dos processos (A, B, C) na fila de pronto foi obedecida, e, não tendo sido
interrompidos por E/S, os processos executaram inteiramente até terminar, de
acordo com seus tempos necessários para execução.
0
10
Processo A
10 u.t.
-
18
Processo B
8 u.t.
27
Processo C
9 u.t.
SJF (Shortest Job First): este escalonamento seleciona o processo que tiver o
menor tempo de processador ainda por executar. Desta forma, o processo que
estiver na fila de pronto com menor necessidade de tempo de CPU para terminar
o seu processamento será o escolhido para ocupar a CPU. Funciona com um
parâmetro passado ao sistema via contexto de software, onde o tempo estimado
para o processo é informado baseando-se em estatísticas de execuções
anteriores.
Como exemplo, vamos utilizar os mesmos processos executados no
escalonamento FIFO acima, com seus respectivos tempos de execução em u.t.
(unidades de tempo): processo A com 10 u.t., processo B com 8 u.t, e o processo
C com 9 u.t. Como neste escalonamento o que importa é o tempo de execução, a
nova ordem de escalonamento para utilização da CPU será B, C e A, como segue:
0
8
Processo B Processo C
-
17
27
Processo A
Cooperativo: este escalonamento busca aumentar o grau de concorrência no
processador. Neste caso, um processo em execução pode voluntariamente liberar
o processador retornando à fila de pronto, possibilitando que um novo processo
seja escalonado, permitindo melhor distribuição do tempo do processador. A
liberação da CPU é uma tarefa exclusiva do programa em execução, que de
maneira cooperativa libera o processador para um outro processo. Neste
mecanismo, o processo em execução verifica periodicamente uma fila de
mensagens para saber se existem outros processos na fila de pronto. Porém,
como a interrupção do processo não depende do sistema operacional, situações
indesejáveis podem ocorrer, como por exemplo, se um programa em execução
não verificar a fila de mensagens, os demais programas não terão chance de
executar enquanto a CPU não for liberada. As primeiras versões do Windows
chegaram a utilizar este tipo de escalonamento.
104
Apostila Fundamentos de Sistemas Operacionais
.
São escalonamentos preemptivos:
Circular: é um tipo de escalonamento projetado especialmente para sistemas em
tempo compartilhado. É muito semelhante ao FIFO (obedece a ordem de chegada
á fila de PRONTO), mas quando um processo passa para o estado de execução há
um limite de tempo para o uso contínuo do processador, chamado fatia de tempo
(time-slice) ou quantum. Assim, toda vez que um processo é selecionado para
execução uma nova fatia de tempo lhe é concedida. Caso esta fatia de tempo
expire, o sistema operacional interrompe o processo, salva seu contexto e o
direciona para a fila de PRONTO. Este mecanismo é conhecido como preempção
por tempo. A principal vantagem deste escalonamento é não permitir que um
processo monopolize a CPU. Outrossim, uma desvantagem é que os processos
CPU-bound são beneficiados no uso do processador em relação aos processos
I/O-bound, pois tendem a utilizar totalmente a fatia de tempo recebida. A figura a
seguir mostra o escalonamento circular com 3 processos, onde a fatia de tempo é
igual a 2 u.t. No exemplo não estão sendo levados em consideração tempos de
troca de contexto entre os processos, nem o tempo perdido em operações de E/S.
Os processos A, B e C, gastam 10 u.t, 6 u.t e 3 u.t., respectivamente.
-
A
B
C
2
-
4
6
8
10 11
17
u.t.
Por Prioridades: funciona com base num valor associado a cada processo,
denominado prioridade de execução. O processo com maior prioridade na fila de
PRONTO é sempre o escolhido para ocupar o processador, sendo os processos
com prioridades iguais escalonados pelo critério FIFO. Neste escalonamento o
conceito da fatia de tempo não existe. Como conseqüência disto, um processo em
execução não pode sofrer preempção por tempo. Neste escalonamento a perda
do uso do processador somente ocorrerá no caso de uma mudança voluntária
para o estado de espera (interrupção por E/S), ou quando um outro processo de
prioridade maior passa (ou chega) para o estado de pronto. Neste caso o sistema
operacional interrompe o processo em execução, salva seu contexto e o coloca na
fila de pronto, dando lugar na CPU ao processo prioritário. Este mecanismo é
chamado de preempção por prioridade. A figura a seguir mostra a execução dos
processos A, B e C, com tempos de execução de 10, 4 e 3 u.t. respectivamente, e
105
Apostila Fundamentos de Sistemas Operacionais
.
valores de prioridades de 2, 1 e 3, também respectivamente. Na maioria dos
sistemas, valores menores correspondem à MAIOR prioridade. Assim, a ordem de
execução será invertida para B, A e C.
A
B
C
4
14
17 u.t.
A prioridade de execução faz parte do contexto de software do processo, e pode
ser estática (quando não pode ser alterada durante a existência do processo) ou
dinâmica (quando pode ser alterada durante a existência do processo). Este
escalonamento é muito usado em sistemas de tempo real, com aplicações de
controle de processos, controle de tráfego (sinais de trânsito, de trens/metrô,
aéreo), robótica, entre outros.
-
Escalonamento Circular com Prioridades: implementa o conceito de fatia de
tempo e de prioridade de execução
associada a cada processo. Neste
escalonamento, um processo permanece no estado de execução até que termine
seu processamento, ou voluntariamente passe para o estado de espera
(interrupção por E/S), ou sofra uma preempção por tempo ou prioridade. A
principal vantagem deste escalonamento é permitir um melhor balanceamento no
uso do processador, com a possibilidade de diferenciar o grau de importância dos
processos através da prioridade (o Windows utiliza este escalonamento).
-
Por Múltiplas Filas: Este escalonamento implementa várias filas de pronto, cada
uma com prioridade específica. Os processos são associados às filas de acordo
com características próprias, como importância da aplicação, tipo de
processamento ou área de memória necessária. Assim, não é o processo que
detém a prioridade, mas sim a fila. O processo em execução sofre preempção
caso um outro processo entre em uma fila de maior prioridade. O sistema
operacional só pode escalonar processos de uma fila quando todas as outras filas
de maior prioridade estejam vazias. Os processos sempre voltam para a mesma
fila de onde saíram.
-
Por Múltiplas Filas com Realimentação: semelhante ao anterior, porém permitindo
ao processo voltar para uma outra fila de maior ou menor prioridade, de acordo com seu
comportamento durante o processamento. O sistema operacional identifica
dinamicamente o comportamento de cada processo e o redireciona para a fila mais
conveniente ao longo de seu processamento. É um algoritmo generalista, podendo ser
implementado na maioria dos sistemas operacionais.
106
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 9
Gerência de Memória / Memória Virtual
9.1
Introdução:
Historicamente, a memória principal sempre foi vista como um recurso escasso e
caro. Uma das maiores preocupações dos projetistas foi desenvolver sistemas
operacionais que não ocupassem muito espaço de memória e, ao mesmo tempo,
otimizassem a utilização dos recursos computacionais. Mesmo atualmente, com a
redução do custo e o aumento considerável da capacidade da memória principal, seu
gerenciamento é dos fatores mais importantes no projeto e implementação dos sistemas
operacionais.
Enquanto nos sistemas monoprogramáveis a gerência de memória não é muito
complexa, nos sistemas multiprogramáveis essa gerência se torna crítica, devido à
necessidade de se maximizar o número de usuários e aplicações utilizando
eficientemente o espaço da memória principal.
9.2
Funções:
Geralmente, os programas são armazenados em memórias secundárias, de uso
permanente e não voláteis, como discos ou fitas. Como o processador somente executa
o que está na memória principal, o sistema operacional deve sempre transferir
programas da memória secundária para a principal antes de serem executados.Como o
tempo de acesso às memórias secundárias é muito superior ao tempo de acesso à
memória principal, o sistema operacional deve buscar reduzir o número de operações de
E/S (acessos à memória secundária) a fim de não comprometer o desempenho do
sistema.
A gerência de memória deve tentar manter na memória principal o maior número
de processos residentes, permitindo maximizar o compartilhamento do processador e
demais recursos computacionais. Mesmo não havendo espaço livre, o sistema deve
permitir que novos processos sejam aceitos e executados. Outra preocupação na
gerência de memória é permitir a execução de programas maiores do que a memória
física disponível.
Em um ambiente de multiprogramação o sistema operacional deve proteger as
áreas de memória ocupadas por cada processo, além da área onde reside o próprio
sistema. Caso um programa tente realizar algum acesso indevido à memória, o sistema
deve, de alguma forma, impedir o acesso.
107
Apostila Fundamentos de Sistemas Operacionais
9.3
.
Alocação Contígua Simples:
Este tipo de alocação foi implementado nos primeiros sistemas operacionais,
embora ainda nos dias de hoje esteja presente em alguns sistemas monoprogramáveis.
Nesse modelo, a memória principal é dividida em duas partes, uma para o sistema
operacional e a outra para o programa do usuário. Dessa forma, o programador deve
desenvolver suas aplicações preocupado apenas em não ultrapassar o espaço de
memória disponível.
Neste esquema o usuário tem total controle sobre toda a memória, exceto
naquela área onde reside o sistema operacional, cujo endereçamento é protegido por
um registrador, impedindo acesso indevido pelo usuário.
Sistema
Operacional
X
registrador
Área para
programas
Proteção na alocação contígua simples
Apesar de simples implementação e código reduzido, a alocação contígua simples
não permite a utilização eficiente dos recursos do sistema, pois apenas um usuário pode
dispor destes recursos. Há inclusive um desperdício de espaço de memória, caso o
programa não venha a ocupar toda a área reservada para ele.
Sistema
Operacional
Programa do
Usuário
Sub-utilização
Área livre da memória principal
108
Apostila Fundamentos de Sistemas Operacionais
9.4
.
Segmentação de Programas:
Na alocação contígua simples todos os programas estão limitados ao tamanho da
memória principal disponível para o usuário. Uma solução encontrada para o problema é
dividir o programa em módulos, de modo que seja possível a execução independente de
cada módulo, utilizando a mesma área de memória. A esta técnica dá-se o nome de
segmentação ou overlay.
Consideremos um programa que tenha três módulos: um principal, um de
cadastramento e outro de impressão, sendo os módulos de cadastramento e impressão
independentes. A independência significa que quando um módulo estiver na memória
para execução, o outro não necessariamente precisa estar presente.O módulo principal é
comum aos outros dois, logo, precisa estar na memória durante todo o tempo da
execução do programa.
Na figura a seguir, a memória é insuficiente para armazenar todo o programa,
que totaliza 9 KB. A técnica de overlay utiliza uma área de memória comum para
armazenar o módulo principal do programa e uma outra área na mesma memória,
chamada área de overlay, que será compartilhada entre os módulos de cadastramento e
impressão. Assim, sempre que um dos módulos for referenciado no módulo principal, o
sistema o carregará da memória secundária para a área de overlay, sobrepondo o
módulo antigo na memória.
Memória Principal
Sistema
2 KB
Operacional
3 KB
4 KB
Cadastramento
Módulo Principal
4 KB
Área de
Overlay
Impressão
2 KB
1 KB
Área livre
2 KB
Técnica de Overlay
A definição das áreas de overlay é função do programador, através de comandos
específicos da linguagem de programação utilizada.
A grande vantagem da utilização desta técnica consiste em se poder executar
programas maiores do que a memória física disponível.
109
Apostila Fundamentos de Sistemas Operacionais
9.5
.
Alocação Particionada Estática:
Os sistemas operacionais evoluíram no sentido de proporcionar melhor
aproveitamento dos recursos disponíveis. Nos sistemas monoprogramáveis o
processador permanece grande parte do tempo ocioso e a memória principal é subutilizada. Os sistemas multiprogramáveis já são muito mais eficientes no uso do
processador, necessitando que vários processos estejam na memória principal ao mesmo
tempo e que novas formas de gerência de memória sejam implementadas.
Nos primeiros sistemas multiprogramáveis a memória era dividida em blocos de
tamanho fixo, chamados partições.O tamanho dessas partições, estabelecido em tempo
de inicialização do sistema, era definido em função do tamanho dos programas que
executariam no ambiente.Sempre que fosse necessária a alteração do tamanho de uma
partição, o sistema deveria ser inicializado novamente com uma nova configuração.
Sistema
Operacional
Partição 1
2 KB
Partição 2
5 KB
Partição 3
8 KB
Inicialmente, os programas só podiam ser carregados e executados em apenas
uma partição específica, mesmo que as outras estivessem disponíveis. Esta limitação se
devia aos compiladores e linkeditores, que geravam apenas código absoluto. No código
absoluto, todas as referências a endereços no programa são posições físicas na
memória, ou seja, o programa só poderia ser carregado a partir do endereço de
memória especificado no seu próprio código. A esse tipo de alocação de memória
chamou-se alocação particionada estática absoluta.
Coma evolução dos compiladores, linkeditores, montadores e loaders, o código
gerado deixou de ser absoluto e passou a ser relocável . No código relocável, todas as
referências a endereços no programa são relativas ao início do código e não a endereços
fixos na memória. Desta forma, os programas puderam ser alocados em qualquer
partição livre, independente do endereço inicial e da partição para a qual o código foi
criado. A esse tipo de alocação deu-se o nome de alocação particionada estática
relocável.
Tanto nos sistemas de alocação absoluta como nos de alocação relocável, os
programas, normalmente, não ocupam totalmente as partições onde são alocados,
deixando algum espaço livre dentro das partições. Este tipo de problema, decorrente do
esquema de alocação fixa de partições, é chamado fragmentação interna.
110
Apostila Fundamentos de Sistemas Operacionais
.
A figura a seguir mostra um gráfico representando o particionamento estático de
uma memória e sua fragmentação interna.
Memória Principal
Sistema
Operacional
Programa C
1 KB
Programa A
3 KB
Fragmentação
interna
Programa E
5 KB
Alocação particionada estática com fragmentação interna
9.6
Alocação Particionada Dinâmica:
A alocação particionada estática deixou clara a necessidade de uma nova forma
de gerência de memória principal, onde o problema da fragmentação interna fosse
reduzido e, conseqüentemente, o grau de compartilhamento da memória aumentado.
Na alocação particionada dinâmica, foi eliminado o conceito de partições de
tamanho fixo. Nesse esquema, cada programa, ao ser carregado, utilizaria o espaço
necessário à sua execução, tornando esse espaço a sua partição. Assim, como os
programas utilizam apenas o espaço de que necessitam, no esquema de alocação
particionada dinâmica o problema da fragmentação interna deixa de existir.
Porém, com o término de alguns programas e o início de outros, passam a existir
na memória blocos cada vez menores na memória, não permitindo o ingresso de novos
programas. A este tipo de problema dá-se o nome de fragmentação externa.
Para resolver o problema da fragmentação externa, os fabricantes tentaram duas
soluções:
- reunião de todos os blocos livres adjacentes, formando uma grande área livre,
que se transforma em uma nova partição;
-
realocação de todas as partições ainda ocupadas para a parte inicial da
memória, eliminando os blocos livres entre elas, formando uma grande área
111
Apostila Fundamentos de Sistemas Operacionais
.
livre no final da memória, que podia ser distribuída entre os processos ainda
por executar. A este tipo de compactação de espaços livres foi dado o nome
de alocação particionada dinâmica com realocação.
Estas soluções ajudaram a diminuir os problemas da fragmentação (tanto interna
como externa), mas, devido á complexidade dos algoritmos, nem todos os sistemas
operacionais as utilizaram.
9.7
Estratégias de Alocação de Partição:
Os sistemas operacionais implementam basicamente três estratégias para
determinar em qual área livre um programa será alocado para execução. Essas
estratégias tentam evitar ou diminuir o problema da fragmentação.
A melhor estratégia a ser adotada por um sistema depende de uma série de
fatores, sendo o mais importante o tamanho dos programas executados no ambiente.
Independentemente do algoritmo utilizado, o sistema possui uma lista das áreas
livres, com endereço e tamanho de cada área.
São estratégias de alocação:
-
Best-fit: é escolhida a melhor partição, ou seja, aquela que deixa o menor
espaço sem utilização. Uma grande desvantagem desta estratégia é que, como
são alocados primeiramente as partições menores, deixando pequenos blocos,
a fragmentação aparece mais rapidamente.
-
Worst-fit: aloca o programa na pior partição, ou seja, aquela que deixa o
maior espaço livre. Esta técnica, apesar de aproveitar primeiro as partições
maiores, acaba deixando espaços livres grandes o suficiente para que outros
programas utilizem esses espaços, permitindo que um número maior de
processos se utilizem da memória, diminuindo ou retardando a fragmentação.
-
First-fit: esta estratégia aloca o programa na primeira partição que o couber,
independente do espaço livre que vai deixar. Das três estratégias, esta é a
mais rápida, consumindo menos recursos do sistema.
112
Apostila Fundamentos de Sistemas Operacionais
9.8
.
Swapping:
É uma técnica aplicada à gerência de memória que visa dar maior taxa de
utilização à memória principal, melhorando seu compartilhamento. Visa também resolver
o problema da falta de memória principal num sistema.
Toda vez que um programa precisa ser alocado para execução e não há espaço
na memória principal, o sistema operacional escolhe entre os processos alocados que
não tem previsão de utilizar a CPU nos próximos instantes (quase sempre entre aqueles
que estão em interrupção de E/S ou no final da fila de pronto), e “descarrega” este
processo da memória para uma área especial em disco, chamada arquivo de swap, onde
o processo fica armazenado temporariamente. Durante o tempo em que o processo fica
em swap, o outro que necessitava de memória entra em execução ocupando o espaço
deixado pelo que saiu. Pouco antes de chegar a vez do processo armazenado em swap
utilizar a CPU, o sistema escolhe um outro processo para descarregar para swap e
devolve o anterior da área de swap para a memória principal, para que este possa ser
executado novamente. E vai trabalhando assim até que os processos vão terminando. O
problema dessa técnica é que pode provocar um número excessivo de acesso à memória
secundária (disco), levando o sistema a uma queda de desempenho.
9.9
Memória Virtual:
Anteriormente foram apresentadas diversas técnicas de gerenciamento de
memória que evoluíram no sentido de maximizar o número de processos residentes na
memória principal e reduzir o problema da fragmentação, porém os esquemas vistos se
mostraram muitas vezes ineficientes. Além disso, o tamanho dos programas e de suas
estruturas de dados estava limitado ao tamanho da memória disponível. Como vimos, a
utilização da técnica de overlay para contornar este problema é de difícil implementação
na prática e nem sempre uma solução garantida e eficiente.
Memória virtual é uma técnica sofisticada e poderosa de gerência de memória
onde as memórias principal e secundária são combinadas, dando ao usuário a impressão
de que existe muito mais memória do que a capacidade real de memória principal.
O conceito de memória virtual baseia-se em não vincular o endereçamento feito
pelo programa aos endereços físicos da memória principal. Desta forma, o programa e
suas estruturas de dados deixam de estar limitados ao tamanho da memória física
disponível, pois podem possuir endereços vinculados à memória secundária, que
funciona como uma extensão da memória principal.
Outra vantagem desta técnica é permitir um número maior de processos
compartilhando a memória principal, já que apenas partes de cada processo estarão
residentes. Isto leva a uma utilização mais eficiente do processador, além de minimizar
(ou quase eliminar) o problema da fragmentação.
113
Apostila Fundamentos de Sistemas Operacionais
.
A seguir, os conceitos que envolvem a gerência de memória virtual, incluindo a
paginação:
-
espaço de endereçamento virtual: é o conjunto de endereços virtuais que
-
Espaço de endereçamento real: analogamente, é o conjunto de endereços
-
Mapeamento: como o espaço de endereçamento virtual não tem nenhuma
-
Tabela de endereçamento de páginas: estrutura mantida pelo sistema
-
Memória virtual por paginação: é a técnica de gerência de memória onde
-
Page fault: é a falha de página. Sempre que o processo referencia um
um processo pode endereçar.
reais que um processo pode endereçar.
relação com o espaço de endereçamento real, um programa pode fazer
referência a um endereço virtual que esteja fora dos limites da memória
principal (real), ou seja, os programas e suas estruturas de dados não estão
mais limitados ao tamanho da memória física disponível. Quando um programa
é executado, apenas uma parte do seu código fica residente na memória
principal, permanecendo o restante na memória virtual até o momento de ser
referenciado. Este esquema de endereçamento virtual é ignorado pelo
programador no desenvolvimento das aplicações. Cabe ao compilador e ao
linkeditor gerar códigos executáveis em função do endereçamento virtual, e o
sistema operacional se incumbe de administrar os detalhes durante a sua
execução. O processador apenas executa instruções e referencia dados
residentes no espaço de endereçamento real. Portanto, deve existir um
mecanismo que transforme os endereços virtuais em endereços reais. Este
mecanismo é o que chamamos de mapeamento, e consiste em permitir a
tradução do endereço virtual em endereço real. Como conseqüência, um
programa não mais precisa estar necessariamente em endereços contíguos na
memória real para ser executado.
para armazenar, entre outras informações, o mapeamento. É única e exclusiva
para cada processo, relacionando os endereços virtuais do processo ás suas
posições na memória real.
o espaço de endereçamento virtual e o espaço de endereçamento real são
divididos em blocos do mesmo tamanho chamados páginas. As páginas do
espaço virtual são chamadas páginas virtuais, enquanto as páginas do espaço
real são chamadas páginas reais ou frames.
endereço virtual, o sistema verifica se a página correspondente já está
carregada na memória real. Se não estiver, acontece o page fault. Neste caso,
o sistema deve transferir a página virtual para um endereço na memória real.
Esta transferência é chamada de paginação. O número de page faults gerados
por um processo em um determinado intervalo de tempo é chamado de taxa
de paginação do processo. Se esta taxa atingir valores elevados, pode haver
um comprometimento do desempenho do sistema. Um page fault provoca
114
Apostila Fundamentos de Sistemas Operacionais
.
uma interrupção no processo, pois há a necessidade de acessar operações de
E/S. Assim, sempre que acontece a paginação, uma interrupção de E/S fará
com que o processo em execução seja interrompido e colocado em estado de
espera até que sua intervenção de E/S seja realizada, quando então o
processo voltará à fila de pronto e entrará em execução de acordo com o
escalonamento normal. Enquanto o sistema trata a interrupção deste
processo, um outro ocupará a CPU.
-
Working-set: é o conjunto de páginas de um processo, em memória real, em
-
Thrashing: é o efeito causado pelo excesso de page faults durante a
-
Tamanho
-
Políticas de busca de páginas: definem como as páginas serão carregadas
da memória virtual para a memória real. A política por demanda estabelece
um determinado instante. Este conceito surgiu com o objetivo de reduzir o
problema do thrashing e está relacionado ao princípio da localidade. Existem
dois tipos de localidade que são observados durante a execução da maioria
dos programas. A localidade espacial é a tendência de que, após uma
referência a um endereço de memória, sejam realizadas novas referências a
endereços próximos ou adjacentes. A localidade espacial é a tendência de que,
após a referência a uma posição de memória, esta mesma posição seja
referenciada novamente num curto intervalo de tempo. A partir desse princípio
de localidade, o processador tenderá a concentrar suas referências a um
conjunto de páginas do processo durante um determinado período de tempo.
Imagine um loop principal de um programa que ocupe três páginas. A
tendência é que estas três páginas tenham um alto índice de referências
durante a execução do programa.
execução de um processo. Pode acontecer a nível de programa ou de sistema.
A nível de programa, pode ser provocado por um programa mal escrito, com
desvios incondicionais espalhados por seu código (desobedecendo portanto
aos princípios da localidade), ou por um limite de working-set muito pequeno
(que não comporte o loop principal do programa, por exemplo). A solução
para estes casos é reescrever o programa ou aumentar o limite do workingset. No caso de thrashing de sistema, significa que há mais páginas sendo
requeridas na memória real do que ela pode realmente suportar. A solução é
aumentar o tamanho da memória física.
da
página:
deve estar entre 512 bytes e 128KB,
aproximadamente. Páginas menores promovem maior compartilhamento da
memória, permitindo que mais programas possam ser executados. Páginas
maiores diminuem o grau de compartilhamento da memória, com menos
programas disputando o processador. Assim conclui-se que quanto menor o
tamanho da página, MAIOR é o grau de compartilhamento da memória e da
CPU.
que uma página somente será carregada quando for referenciada. Este
mecanismo é conveniente, pois leva para a memória real somente as páginas
realmente necessárias à execução do programa, ficando as outras na memória
115
Apostila Fundamentos de Sistemas Operacionais
.
virtual. A outra política, chamada paginação antecipada, funciona carregando
antecipadamente várias páginas da memória virtual para a principal, na
tentativa de economizar tempo de E/S. Nem sempre o sistema acerta na
antecipação, mas o índice de acertos é quase sempre maior que o de erros.
-
Políticas de alocação de páginas: determinam quantos frames cada
processo pode manter na memória real. A política de alocação fixa determina
um limite de working-set igual para todos os processos, e pode ser vista como
uma política injusta, na medida em que processos maiores normalmente
necessitam de um working-set maior. A outra política é a variável, que define
um limite de working-set diferente e variável para cada processo, em função
de seu tamanho, taxa de paginação ou até mesmo da taxa de ocupação da
memória principal.
-
Políticas de substituição de páginas: definem onde serão trocadas as
páginas, quando se fizer necessária uma substituição. Na política local,
somente as páginas do processo que gerou o page fault são candidatas a
serem substituídas.Já na política global, todas as páginas alocadas na memória
principal são candidatas à substituição, independente do processo que gerou o
page fault. Como uma página de qualquer processo pode ser escolhida, pode
ser que este processo sofra um aumento temporário da taxa de paginação em
função da diminuição das suas páginas alocadas em memória.
9.10 Algoritmos de substituição de páginas:
O maior problema na gerência de memória virtual por paginação não é decidir
quais páginas carregar para a memória real, mas sim quais páginas liberar. Quando há a
necessidade de carregar uma página, o sistema deve selecionar entre as diversas
páginas alocadas na memória qual delas deverá ser liberada pelo processo.
Os algoritmos de substituição de páginas têm o objetivo de selecionar os frames
que tenham as menores chances de serem referenciados num futuro próximo. Caso
contrário, o frame poderia retornar diversas vezes para a memória real, provocando
excesso de page faults.
São algoritmos de substituição de páginas:
-
algoritmo ótimo: impossível de ser implementado, pois o processador não
-
Algoritmo aleatório: escolhe qualquer página, entre as alocadas na
consegue prever com segurança qual frame não será mais referenciado
durante a execução do programa. Tal fato deve-se à lógica do programa e aos
dados que ele manipula, desconhecidos pelo processador.
memória, para fazer a substituição. Em função de sua baixa eficiência, este
algoritmo não muito utilizado, embora consuma poucos recursos do sistema.
116
Apostila Fundamentos de Sistemas Operacionais
.
-
Algoritmo FIFO (first in, first out): escolhe a página que está há mais
-
Algoritmo LFU (least frequently used): elege a página menos
-
Algoritmo LRU (least recently used): elege a página menos recentemente
-
Algoritmo NRU (not recently used): elege a página menos recentemente
tempo na memória principal para fazer a troca. É um algoritmo de simples
implementação, mas corre o risco de retirar uma página que, embora tenha
sido carregada há mais tempo, esteja sendo muito utilizada. Por essa razão
não é muito usado.
freqüentemente usada para efetuar a troca. Através de um contador,
armazenado na tabela de endereçamento de páginas, mo sistema identifica
quantas referências cada página teve e utiliza esta informação para escolher a
página.
usada para fazer a troca. O sistema mantém na tabela de endereçamento de
páginas um campo onde são armazenadas a data e a hora da última referência
de cada página, e com base nestas informações faz a seleção.
usada para efetuar a troca. O sistema exclui da decisão a página mais recente
e escolhe entre as outras, pelo método FIFO, qual página deve sair.
117
Apostila Fundamentos de Sistemas Operacionais
.
Capítulo 10
Gerência de Sistemas de Arquivos
10.1 Estrutura de Diretórios:
É como o Sistema organiza logicamente os arquivos. Contém entradas associadas aos
arquivos, com as informações de localização, nome, organização e outros atributos:

Nível único: é a implementação mais simples de uma estrutura de diretórios,
onde existe um único diretório contendo todos os arquivos do disco. É muito
limitado, não permitindo a criação de arquivos com o mesmo nome.

Diretório pessoal: Evolução do modelo anterior, permite a cada usuário ter ser
“diretório” particular, sem a preocupação de conhecer os outros arquivos do
disco. Neste modelo há um diretório “master” que indexa todos os diretórios
particulares dos usuários, provendo o acesso a cada um.

Múltiplos níveis (ÁRVORE): É o modelo utilizado hoje em dia em quase todos
os Sistemas Operacionais. Nesta modalidade cada usuário pode criar vários níveis
de diretórios (ou sub-diretórios), sendo que cada diretório pode conter arquivos e
sub-diretórios. O número de níveis possíveis depende do Sistema Operacional.
10.2 Sistemas de alocação de arquivos:

FAT: sistema criado no MS-DOS e depois utilizado no Windows. Usa listas
encadeadas, tem um limite de área utilizável em partições de 2 GB, caracteriza-se
por um baixo desempenho no acesso e armazenamento.

FAT32: igual ao FAT no que diz respeito a organização e desempenho, mas pode
trabalhar com partições de até 2TB.

NTFS: NT File System, original da plataforma Windows NT/2000/XP. Opera com
uma estrutura em árvore binária, oferecendo alto grau de segurança e
desempenho:
-

nomes de arquivo com até 255 caracteres, podendo conter maiúsculas,
minúsculas e espaços em branco;
dispensa ferramentas de recuperação de erros;
bom sistema de proteção de arquivos;
criptografia;
suporta discos de até 264 bytes.
UNIX: Usa diretório hierárquico, com um raiz e outros diretórios subordinados.
Neste Sistema Operacional todos os arquivos são considerados apenas como uma
“seqüência” de bytes, sem significado para o Sistema. É responsabilidade da
118
Apostila Fundamentos de Sistemas Operacionais
.
aplicação controlar os métodos de acesso aos arquivos. O UNIX utiliza também
alguns diretórios padronizados, de exclusividade do Sistema.
10.3 Gerência de espaço livre:
São três as formas de se implementar estruturas de espaços livres. Uma delas é
através de uma tabela denominada mapa de bits, onde cada entrada da tabela é
associada a um bloco do disco representado por um bit, que estando com valor 0 indica
que o espaço está livre, e com valor 1 representa um espaço ocupado. Gasta muita
memória, pois para cada bloco do disco há uma entrada na tabela.
A segunda forma é utilizando uma lista encadeada dos blocos livres do disco.
Desse modo, cada bloco possui uma área reservada para armazenar o endereço do
próximo bloco livre. Apresenta problemas de lentidão no acesso, devido às constantes
buscas seqüenciais na lista.
A terceira forma é a tabela de blocos livres. Nesta, leva em consideração que
blocos contíguos de dados geralmente são alocados/liberados simultaneamente. Desta
forma, pode-se enxergar o disco como um conjunto de segmentos de blocos livres.
Assim, pode-se manter uma tabela com o endereço do primeiro bloco de cada segmento
e o número de blocos contíguos que se seguem.
-
Alocação contígua: armazena o arquivo em blocos seqüencialmente
dispostos no disco. O arquivo é localizado através do endereço do primeiro
bloco de sua extensão em blocos. O principal problema neste tipo de
alocação é a existência de espaço livre para novos arquivos, que deve ser
contígua. Utiliza as estratégias best-fit, worst-fit e first-fit (já conhecidas)
para definir onde o arquivo será alocado. Causa alto índice de
fragmentação no disco.
-
Alocação encadeada: nesta modalidade o arquivo é organizado como
um conjunto de blocos ligados logicamente no disco, independente de sua
localização física, onde cada bloco possui um ponteiro para o bloco
seguinte. A fragmentação não representa problemas na alocação
encadeada, pois os blocos livres para alocação do arquivo não
necessariamente precisam estar contíguos. O que acontece é a quebra do
arquivo em vários pedaços, o que aumenta o tempo de acesso. Neste tipo
de alocação só se permite acesso seqüencial aos blocos do arquivo, sendo
esta uma das principais desvantagens da técnica. Outra desvantagem é a
perda de espaço nos blocos com o armazenamento dos ponteiros.
-
Alocação indexada: esta técnica soluciona a limitação da alocação
encadeada, no que diz respeito ao acesso, pois permite acesso direto aos
blocos do arquivo. Isso é conseguido mantendo-se os ponteiros de todos
os blocos do arquivo em uma única estrutura chamada bloco de índice.
Este tipo de alocação, além de permitir acesso direto aos blocos, não utiliza
informações de controle nos blocos de dados.
119
Apostila Fundamentos de Sistemas Operacionais
.
10.4 Proteção de acesso:
Considerando-se que os meios de armazenamento são compartilhados por vários
usuários, é fundamental que mecanismos de proteção sejam implementados para
garantir a integridade e proteção individual dos arquivos e diretórios:
-
Senha de acesso: mecanismo de simples implementação, mas apresenta
duas desvantagens: não é possível determinar quais os tipos de operação
podem ser efetuadas no arquivo, e, se este for compartilhado, todos os
usuários que o utilizam devem conhecer a senha de acesso.
-
Grupos de usuário: é muito utilizada em muitos Sistemas Operacionais.
Consiste em associar cada usuário a um grupo. Os grupos são organizados
logicamente com o objetivo de compartilhar arquivos e diretórios no disco.
Este mecanismo implementa três níveis de proteção: OWNER (dono),
GROUP (grupo) e ALL (todos). Na criação do arquivo o usuário especifica
se o arquivo pode ser acessado somente pelo seu criador, pelo grupo ou
por todos os usuários, além de definir que tipos de acesso podem ser
realizados (leitura, escrita, execução e eliminação)
-
Lista de controle de acesso: é uma lista associada ao arquivo onde são
especificados quais os usuários e os tipos de acesso permitidos. O tamanho
dessa estrutura pode ser bastante extenso se considerarmos que um
arquivo pode ser compartilhado por vários usuários. Além deste problema,
há o inconveniente de se fazer acesso seqüencial à lista toda vez que um
acesso é solicitado. Em determinados sistemas de arquivos pode-se utilizar
uma combinação de proteção por grupos de usuários ou por listas de
acesso, oferecendo assim maior flexibilidade ao mecanismo de proteção de
arquivos e diretórios.
120
Apostila Fundamentos de Sistemas Operacionais
.
BIBLIOGRAFIA
Arquitetura de Sistemas Operacionais
Francis B. Machado
Ed. LTC
Sistemas Operacionais: Conceitos e Aplicações
Abraham Silberschatz
Ed. Campus
Sistemas Operacionais Modernos
A.S. Tanenbaum
Operating Systems: Design And Implementation
Andrew S. Tanenbaum - Editora Prentice Hall
121
Download