Você está na página 1de 215

01_SisOps.

qxp 11/2/2009 11:34 Page 1

Sistemas Operacionais
01_SisOps.qxp 11/2/2009 11:34 Page 2
01_SisOps.qxp 11/2/2009 11:34 Page 3

Universidade do Estado do Amazonas

Tecnologia em Análise e Desenvolvimento de Sistemas


(Sistema Presencial Mediado)

Danielle Gordiano Valente


Edward David Moreno Ordonez
José Roberto Vasques do Nascimento

Sistemas Operacionais

Manaus - AM

2009
01_SisOps.qxp 11/2/2009 11:35 Page 4

Ficha Técnica

Governo do Estado do Amazonas

Carlos Eduardo de Souza Braga


Governador do Estado

Omar José Abdel Aziz


Vice-Governador do Estado

Universidade do Estado do Amazonas

Marilene Corrêa da Silva Freitas


Reitora

Carlos Eduardo de Souza Gonçalves


Vice-Reitor

Fares Franc Abinader Rodrigues


Pró-Reitor de Administração

Osail Medeiros de Souza


Pró-Reitor de Planejamento

Edinea Mascarenhas Dias


Pró-Reitora de Ensino de Graduação

José Luiz de Souza Pio


Pró-Reitor de Pós-Graduação e Pesquisa

Rogelio Casado Marinho Filho


Pró-Reitor de Extensão e Assuntos Comunitários

Escola Superior de Tecnologia

Vicente de Paulo Queiroz Nogueira


Diretor

Curso Superior de Tecnologia em Análise e Desenvolvimento de Sistemas


(Sistema Presencial Mediado por Tecnologia)

Ednaldo Coelho Pereira


Coordenador Geral

Ângela Timótia Pereira Lima


Coordenadora Pedagógica

Nilo Barreto Falcão Neto


Coordenador de Tecnologia Educacional

Érica Lima
Projeto gráfico

Diana Maria da Câmara Gorayeb


Revisão

Valente, Danielle Gordiano.

V154s Sistemas operacionais / Danielle Gordiano Valente, Edward David Moreno Ordonez,
José Roberto Vasques Nascimento – Manaus/AM: UEA Edições, 2009.

215 p.: il. ; 23 cm.

Inclui bibliografia e anexo.


ISBN: 978-85-7883-022-9

1.Sistemas operacionais(Computadores). I. Ordonez, Edward David Moreno. II.


Nascimento, José Roberto Vasques do. III. Título.
CDU (1997): 004.451
01_SisOps.qxp 11/2/2009 11:35 Page 5

Perfil dos Autores

Danielle Gordiano Valente


Professora da Escola Superior de Tecnologia (EST/UEA)
Mestre em Ciência da Computação
pela Universidade de Minas Gerais (UFMG)

Edward David Moreno Ordonez


Professor da Escola Superior de Tecnologia
da Universidade do Estado do Amazonas (EST/UEA)
Pós-doutor em Ciência da Computação (UFSCAR)
Doutor em Engenharia Elétrica (POLI-USP)

José Roberto Vasques do Nascimento


Especialista em Tecnologias WEB
pela Universidade Federal do Amazonas (UFAM)
01_SisOps.qxp 11/2/2009 11:35 Page 6

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas
01_SisOps.qxp 11/2/2009 11:35 Page 7

Laboratório de Tecnologia em Análise e


Tecnologia em Análise e
Estrutura de Dados I
Sistemas Operacionais Desenvolvimento de Sistemas
Desenvolvimento de Sistemas
Agradecimentos

Agradeço a Deus por mais esta pequenina obra.


Que ela possa ajudar no progresso de todos
que precisarem do seu conteúdo.
Agradeço à minha mãe Marília,
à minha tia Myrtes e à minha irmã Danna
que, como todas as mulheres, são multithreaded.

Danielle Gordiano Valente

Agradeço a Deus pelas vibrações eternas de amor com toda a Criação. A minha
esposa Elena, e meus filhos pelo constante amor e harmonia em família. Eles
inspiram e fortalecem cada segundo das nossas vidas.

Edward David Moreno Ordonez

Agradeço primeiramente a Deus pela oportunidade e pelo privilégio que me foi


dado em participar de tamanha experiência e por ter colocado em minha vida
uma pessoa maravilhosa, minha amada esposa Fabiane Gomes, estimuladora de
meus sonhos, apoiando-me em todas as horas.
Obrigado pelo carinho e compreensão no dia a dia.

José Roberto Vasques do Nascimento


01_SisOps.qxp 11/2/2009 11:35 Page 8

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8
01_SisOps.qxp 11/2/2009 11:35 Page 9

Palavra da Reitora

Nos últimos anos, o avanço da tecnologia da informática mudou os conceitos de


ensino e de trabalho. A preocupação com o que se denominou de "inclusão digital"
passou a ser um problema urgente a ser enfrentado pelos dirigentes do País, já que
todos os processos de novas tecnologias deságuam no conhecimento de informática.
No Amazonas, a dificuldade de locomoção na região, por falta de rodovias, por sua
grande extensão territorial, pela baixa densidade demográfica e pelo subdesenvolvi-
mento secular imposto à população ribeirinha, torna-se árduo o esforço do Governo
para tornar realidade à inclusão digital.

A UEA, que já nasceu moderna, incorporando tecnologias educacionais de


ponta, utilizando-se particularmente da informática pela massificação do uso de
microcomputadores combinados com uma rede complexa de acesso à Internet, não
poderia ficar alheia a essa necessidade premente. Por isso, propôs e realizou o
primeiro vestibular para levar a 12 municípios um curso que formasse a mão-de-obra
inicial que tornasse a inclusão digital uma realidade em nosso Estado.

A proposta do curso de Tecnologia em Análise e Desenvolvimento de Sistemas


oferecido pela UEA vislumbra criar mão-de-obra qualificada em um número significa-
tivo de localidades do Estado, cabendo às pessoas beneficiadas com essa iniciativa
a tarefa de irradiar o uso de tecnologias de informática, abrindo caminhos novos e
suscitando novos empregos para a população local, consolidando, assim, o exercício
da cidadania.

Prof.a Dr.a Marilene Corrêa da Silva Freitas


Reitora da Universidade do Estado do Amazonas
01_SisOps.qxp 11/2/2009 11:35 Page 10
01_SisOps.qxp 11/2/2009 11:35 Page 11

Sumário

Lista de Figuras ........................................................................15


Lista de Tabelas ........................................................................19
Lista de Programas ....................................................................21

CAPÍTULO 1 - VISÃO GERAL .........................................................23


1.1 Introdução........................................................................23
1.2 Um pouco de história ..........................................................24
1.3 Conceitos Importantes .........................................................27

CAPÍTULO 2 - PROCESSOS............................................................29
2.1 Execução de um Processo .....................................................30

CAPÍTULO 3 - THREADS...............................................................33
3.1 Introdução........................................................................33
3.2 Modelos de criação de threads ...............................................35
3.2.1 Modelo muitos-para-um .................................................35
3.2.2 Modelo um-para-um .....................................................36
3.2.3 Modelo muitos-para-muitos ............................................37
3.3 Operações realizadas sobre threads .........................................38

CAPÍTULO 4 - ESCALONAMENTO DE PROCESSOS ................................39


4.1 Introdução........................................................................39
4.2 Troca de Contexto ..............................................................39
4.3 Preempção de Processos .......................................................40
4.4 Objetivos do Escalonamento do Processador ...............................41
4.5 Algoritmos de Escalonamento.................................................41
4.5.1 Escalonamento FIFO-First-In, First-Out...............................41
4.5.2 Escalonamento SJF (Shortest Job First) ..............................43
4.5.3 Escalonamento por Prioridades ........................................45
4.5.4 Escalonamento Round Robin (Alternância Circular) ................46
4.5.5 Escalonamento em Filas Multiníveis Com Realimentaçao .........47

CAPÍTULO 5 - COMUNICAÇÃO E SINCRONIZAÇÃO DE PROCESSOS ............49


5.1 Introdução........................................................................49
5.2 Programação Concorrente .....................................................49
5.3 Problemas de Compartilhamento de Recursos .............................55
5.4 Exclusão Mútua ..................................................................57
5.4.1 Soluções em Hardware ..................................................60
5.4.2 Soluções em Software ...................................................63
01_SisOps.qxp 11/2/2009 11:35 Page 12

5.5 Algoritmo de Peterson..........................................................71


5.6 Sincronização Condicional .....................................................72
5.7 Semáforos ........................................................................74
5.8 Monitores .........................................................................82

CAPÍTULO 6 - GERENCIAMENTO DE MEMÓRIA REAL .............................89


6.1 Conceitos Básicos e Funcionalidades ........................................89
6.2 Gerenciamento de Memória...................................................91
6.2.1 Monoprogramação sem Trocas de Processos ou Paginação ........92
6.2.2 Modelagem da Multiprogramação .....................................94
6.3 Relocação e Proteção de Partições ..........................................98
6.4 Gerenciamento de Memória com Mapas de Bits ...........................103
6.5 Alocação de Segmentos Livres ................................................106

CAPÍTULO 7 - GERENCIAMENTO DE MEMÓRIA VIRTUAL.........................109


7.1 PRINCÍPIOS DE MEMÓRIA VIRTUAL ............................................109
7.2 Conceitos de Paginação ........................................................111
7.2.1 Implementação da Paginação ..........................................114
7.2.2 Tabelas de Páginas Multiníveis .........................................119
7.2.3 Tabelas de Páginas Invertidas ..........................................121
7.3 TLB – Tabela de Tradução de Endereços.....................................123
7.4 Paginação por Demanda e o Modelo do Conjunto de Trabalho ..........124
7.5 Política de Substituiçãpo de Páginas ........................................127
7.6 Gerenciamento de Memória Cache ..........................................130
7.7 Segmentação.....................................................................132
7.7.1 Funcionamento da Segmentação ......................................132
7.7.2 Falta de Segmentos......................................................135
7.7.3 Vantagens da Segmentação.............................................135
7.7.4 Segmentação com Paginação...........................................137
7.8 Resumo dos principais conceitos .............................................138
7.9 Gerencia de Memória no Windows ...........................................140
7.10 Gerencia de Memória no UNIX e Linux .....................................145

CAPÍTULO 8 – ENTRADA E SAÍDA....................................................155


8.1 Gerenciamento de Entrada/Saída ............................................156
8.1.1 Entrada e Saída Programada ...........................................157
8.1.2 Interrupção de Entrada e Saída........................................159
8.1.3 Acesso Direto à Memória................................................161
8.2 Deadlock..........................................................................165
8.2.1 Prevenção de Deadlock ................................................167
8.2.2 Detecção e Recuperação................................................168
8.2.3 Evitar Deadlock...........................................................170
8.3 Discos .............................................................................171
8.3.1 Acesso ao Disco...........................................................173
8.3.2 Entrelaçamento ..........................................................174
12
01_SisOps.qxp 11/2/2009 11:35 Page 13

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.4 RAID (Redundant Array of Independent Disks) .............................175


8.4.1 Níveis de RAID ............................................................177
8.5 Entrada e Saída no Linux ......................................................181

CAPÍTULO 9 - ARQUIVOS .............................................................185


9.1 Tipos de Arquivo ................................................................186
9.2 Sistemas de Arquivo ............................................................188
9.3 Acesso a Arquivos ...............................................................192
9.6 Diretórios.........................................................................200
9.6.1 Estrutura de Diretórios..................................................201
9.7 NFS - Network File System ....................................................203
9.7.1 Funcionamento ...........................................................203
9.7.2 Serviço de Nomes ........................................................206
9.8 Sistema de Arquivo no Linux ..................................................207

BIBLIOGRAFIA...........................................................................213

13
01_SisOps.qxp 11/2/2009 11:35 Page 14

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

14
01_SisOps.qxp 11/2/2009 11:35 Page 15

Lista de Figuras

Figura 1.1: Visão geral de um sistema computacional.


Figura 1.2: Visão da memória em um sistema monoprogramado.
Figura 1.3: Visão da memória em um sistema multiprogramado.

Figura 2.1: Alternância de ciclos de CPU e E/S na execução das instruções de


um processo. Fonte: [Silberschatz, 2004]
Figura 2.2: Diagrama de estados de um processo. Fonte: [Silberschatz, 2004]
Figura 3.1(a): Um processo com uma única thread. Figura 3.1(b): Um processo
com múltiplas threads. Fonte: [Silberschatz, 2004]
Figura 3.2: Modelo muitos-para-um.
Figura 3.3: Modelo um-para-um.
Figura 3.4: Modelo muitos-para-muitos.
Figura 4.1: Filas em multinível com realimentação.
Figura 5.1: Comunicação e Sincronização de dois processos acessando um buffer
[Machado, 2007][Pinto, 2008]

Figura 5.1: Comunicação e Sincronização de dois processos acessando um buffer


Figura 5.2: Concorrência em Programas

Figura 6.1: Hierarquia de Memória em Sistemas Computacionais


Figura 6.2: Multiprogramação com partições Fixas
Figura 6.3: Multiprogramação com partições fixas
Figura 6.4: Um exemplo do impacto da multiprogramação
Figura 6.5: Análise do Desempenho de um Sistema Multiprocessado com 4
processos
Figura 6.6: Proteção das partições
Figura 6.7: Visualização do uso de memória conforme o tempo e número de
processos
Figura 6.8: Uso da Memória nos Programas A e B
15
01_SisOps.qxp 11/2/2009 11:35 Page 16

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 6.9: Gerenciamento de memória com Mapas de Bits e Listas Encadeadas


Figura 6.10: Combinações para uso de memória antes e depois de finalizar
processos
Figura 6.11: Alocação de segmentos livres

Figura 7.1: Utilização de Overlays (zonas de sobreposição) nos Programas


Figura 7.2: Endereçamento Possível e Real
Figura 7.3: Exemplo de Endereçamento para Espaços de 4K
Figura 7.4: Posição e Função da MMU
Figura 7.5: Exemplo de uma implementação de memória virtual
Figura 7.6: Exemplo de Tabelas de Páginas para o exemplo da figura 7.5
Figura 7.7: Operação interna da MMU com 16 páginas de 4KB
Figura 7.8: Exemplo de uma entrada típica da tabela de páginas
Figura 7.9: Campos de uma Estrutura que defina o mapeamento
Figura 7.10: Exemplo de Campos na Tabela de Páginas Multinível
Figura 7.11: Estrutura de Tabela de Página de 2 Níveis
Figura 7.12: Comparação de uma tabela de páginas tradicional com uma tabela
de páginas invertidas
Figura 7.13: Uso de TLB em Processadores Intel
Figura 7.14: Passos na Paginação por Demanda
Figura 7.15: Conjunto de Trabalho de uma Aplicação
Figura 7.16: Exemplo de Falha no Algoritmo LRU
Figura 7.17: Arquitetura processador memória e cachê
Figura 7.18: Segmentos mais usados no espaço de endereçamento virtual
Figura 7.19: Segmentos mais usados na segmentação
Figura 7.20: Processos usando segmentação
Figura 7.21: Segmentação e Paginação
Figura 7.22: Exemplo de Segmentação e paginação
Figura 7.23: Layout de Figura Virtual no Windows
Figura 7.24: Entrada Padrão na Tabela de Páginas no Windows
Figura 7.25: Base de Dados de Molduras de Páginas
Figura 7.26: Divisão da Memória usando o algoritmo Buddy-Heap

Figura 8.1: Modelo e interligação, CPU, memória, controladores e dispositivos


de entrada e saída.
Figura 8.2: Entrada e saída programada
Figura 8.3: Sistema de interrupção e exceções
Figura 8.4: Entrada e saída por DMA

16
01_SisOps.qxp 11/2/2009 11:35 Page 17

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 8.5: Esquema de funcionamento – DMA


Figura 8.6: Processos sem Deadlock
Figura 8.7: Processos com Deadlock
Figura 8.8: Organização física do disco magnético.
Figura 8.9: Trilha com 16 setores e diferentes fatores de entrelaçamento.
Figura 8.10: RAID 0
Figura 8.11: RAID 1
Figura 8.12: RAID 5
Figura 8.13: RAID 6

Figura 9.1: Esquema – System Calls


Figura 9.2: Lista encadeada de bloco em disco
Figura 9.3: Lista encadeada utilizando tabela na memória principal
Figura 9.4: Lista Nó-I
Figura 9.5: Único diretório compartilhado por todos os usuários.
Figura 9.6: Um diretório por usuário.
Figura 9.7: Árvore arbitrária por usuário.
Figura 9.8: Funcionamento – NFS.
Figura 9.9: Estrutura NFS – Serviços de Nome.

17
01_SisOps.qxp 11/2/2009 11:35 Page 18

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

18
01_SisOps.qxp 11/2/2009 11:35 Page 19

Lista de Tabelas

Tabela 5.1 Execução do Programa test-and-set

Tabela 7.1. TLBs – Translation Lookaside Buffers


Tabela 7.2 Exemplo de Tabela de Segmentos
Tabela 7.3. Resumo dos Conceitos de Paginação e Segmentação
Tabela 7.4 Funções usadas pela API Win 32

Tabela 8.1 Diretórios

Tabela 9.1 Atributos dos arquivos.


Tabela 9.2 Tipos de arquivos.
Tabela 9.3 Tipos de sistemas operacionais e sistemas de arquivos
Tabela 9.4 Funções – System Calls

19
01_SisOps.qxp 11/2/2009 11:35 Page 20

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

20
01_SisOps.qxp 11/2/2009 11:35 Page 21

Lista de Programas
Programa 5.1: Exemplo de uso dos comandos fork e join.
Programa 5.2: Exemplo do uso dos comandos PARBEGIN e PAREND.
Programa 5.3: Exemplo de concorrência usando threads.
Programa 5.4: Exemplo básico de região crítica.
Programa 5.5: Exemplo de uso de interrupções e região crítica.
Programa 5.6: Exemplo de uso do comando test and set.
Programa 5.7: Exemplo de exclusão mútua - Algoritmo 1.
Programa 5.8: Exemplo de exclusão mútua - Algoritmo 2.
Programa 5.9: Exemplo de exclusão mútua - Algoritmo 3.
Programa 5.10: Exemplo de exclusão mútua - Algoritmo 4.
Programa 5.11: Exemplo de exclusão mútua - Algoritmo de Peterson.
Programa 5.12: Exemplo de produtor/consumidor.
Programa 5.13: Exemplo de semáforo - Instruções DOWN e UP.
Programa 5.14: Exemplo de semáforo - Instruções V(sem) e P(sem).
Programa 5.15: Exemplo de concorrência usando threads e primitivas P(sem)
e V(sem).
Programa 5.16: Exemplo básico de exclusão mútua usando monitores.
Programa 5.17: Exemplo usando monitores.
Programa 5.18: Exemplo de monitores condicionais.

21
01_SisOps.qxp 11/2/2009 11:35 Page 22

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

22
01_SisOps.qxp 11/2/2009 11:35 Page 23

CAPÍTULO 1

Visão Geral

1.1 Introdução

Sistemas operacionais são conjuntos de programas que controlam


o uso do hardware por usuários (pessoas ou outros programas) através
de programas aplicativos ou de sistema.

Após o processo de inicialização da máquina, o sistema opera-


cional toma o controle do computador, gerenciando o acesso aos
recursos de hardware, assim como organiza a execução dos diversos
programas do usuário, além dos seus próprios programas de
gerenciamento. A Figura 1.1 mostra uma visão geral de um sistema
computacional, que é composto por usuários que utilizam o hardware
através de programas, todos sob a supervisão do sistema operacional
[Silberschatz, 2004].

Figura 1.1: Visão geral de um sistema computacional.

23
01_SisOps.qxp 11/2/2009 11:35 Page 24

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Existem diversos sistemas operacionais no mercado, eles variam


de acordo com o hardware da máquina que irão gerenciar
(PC, mainframe, palmtop, celular, TV Digital, carro), o fabricante do
sistema operacional e o propósito a que se destina (propósito geral,
propósito específico, tempo real).

O sistema operacional tem muitas funções em sua tarefa de


gerenciar o uso do hardware e a execução dos programas, entre elas:

1. Gerenciamento dos processos;


2. Gerenciamento da memória;
3. Gerenciamento de entrada e saída (E/S);
4. Gerenciamento do sistema de arquivos;
5. Proteção e segurança do sistema;
6. Gerenciamento de memória secundária;
7. Conexão em rede.

Neste livro serão focadas as funções de 1 a 4, que estão presentes


em todo sistema operacional de propósito geral.

O Gerenciamento de processos trata da maneira como se dará a


execução dos programas. O Gerenciamento de memória mostra a
organização da memória principal e as estratégias de uso.
O Gerenciamento de E/S controla o acesso aos diversos dispositivos de
hardware. O Gerenciamento do sistema de arquivos promove a
organização dos arquivos nos dispositivos de armazenamento.

1.2 Um pouco de história

Os primeiros computadores, na década de 40, não tinham


teclado, nem mouse, nem monitor. Eram extremamente caros e sua
aplicação estava na realização de cálculos complexos. A programação
era feita diretamente em linguagem de máquina, bit a bit, em chaves
eletrônicas e os resultados eram impressos. Não tinham sistemas
operacionais [Deitel, 2005].
24
01_SisOps.qxp 11/2/2009 11:35 Page 25

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Os primeiros sistemas operacionais surgiram na década de 50 e


eram muito simples, além do próprio sistema operacional, executava
apenas um programa de cada vez, chamado de Job. Este programa era
carregado de uma só vez a partir de uma leitora de cartões
perfurados, unidade de fita, ou disco (assim como o sistema
operacional), executava e o resultado era impresso. Eram sistemas
operacionais monoprogramados. Enquanto o job realizava E/S (muitas
vezes projetada pelo programador), a CPU ficava ociosa. Veja a
utilização da memória nestes sistemas na Figura 1.2.

Figura 1.2: Visão da memória em um sistema monoprogramado.

Na década de 60, com a evolução do hardware, o aumento do


número de periféricos, da capacidade de processamento e memória,
os projetistas de sistemas operacionais decidiram melhorar a
utilização da CPU. Carregando vários jobs na memória, o sistema
operacional poderia alocar a CPU a um job enquanto outro realiza
E/S. Assim surgiram os sistemas multiprogramados. Veja na Figura 1.3
um esquema da utilização da memória nestes sistemas.

25
01_SisOps.qxp 11/2/2009 11:35 Page 26

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 1.3: Visão da memória em um sistema multiprogramado.

Com a invenção dos terminais para mainframes, ainda na década


de 60, os funcionários de uma instituição poderiam utilizar
diretamente o computador, submetendo seus jobs diretamente do
terminal. Surgiram os sistemas de tempo compartilhado (time
sharing). Nestes sistemas operacionais, a cada processo é dada uma
fatia (quantum) de tempo de execução. Ao término da fatia de tempo,
outro processo será executado. Assim, a execução de um processo
tornou-se a soma de pequenas execuções, até que finalmente, o
processo terminava. O progresso da execução de todos os jobs
carregados em memória era satisfatório, dando a impressão aos
usuários do mainframe que tinham o computador só para si.

Os conceitos de multiprogramação e tempo compartilhado são


utilizados até hoje nos sistemas operacionais modernos.

Os computadores evoluíram, tanto em hardware como em


software. Diminuíram de tamanho, sendo chamados de estações de
trabalho (workstations), desktop; foram interligados em redes;
incluíram mobilidade nos notebooks e palmtops; estão presentes em
sistemas embutidos como TVs, aparelhos de DVD, microondas,
máquina de lavar, entre outros dispositivos eletro-eletrônicos.

26
01_SisOps.qxp 11/2/2009 11:35 Page 27

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

1.3 Conceitos Importantes

Os sistemas de computação modernos têm uma variedade de


chamadas a Interfaces de Programação de Aplicativos
(API – Application Programming Interface). O uso destas interfaces
libera o programador da dificuldade de acessar diretamente o
hardware. Os programas realizam chamadas de sistemas disponibi-
lizadas pelas APIs. Idealmente os processos só podem utilizar o
hardware através destas chamadas de sistemas, tanto pela
simplicidade, quanto para proteção do hardware e do sistema
operacional de acessos indevidos, incorretos ou maliciosos. De fato, as
chamadas de sistemas são a interface entre um processo e o sistema
operacional [Silberschatz, 2004].

Para viabilizar a idéia das chamadas de sistemas, os sistemas


operacionais possuem um modo de operação dual. Nesta estratégia,
existe um bit de proteção no hardware que indica o modo de
operação. No modo usuário, as instruções privilegiadas de acesso ao
hardware NÃO podem ser executadas e o modo monitor, apenas os
processos do núcleo do sistema operacional podem executar. Neste
modo de operação, quaisquer instruções podem ser executadas,
inclusive instruções privilegiadas. Na prática, os processos de usuário
e de sistema executam em modo usuário e realizam chamadas de
sistemas para acesso ao hardware. Atendendo às chamadas de
sistemas os processos do núcleo mudam o modo de operação para o
modo monitor, realizam as solicitações e demais atividades de
gerência e, ao terminar sua execução, mudam novamente para modo
usuário, para execução de processos comuns.

A operação em modo dual é uma maneira de se proteger o sistema


através do hardware. Outras formas de proteção incluem o próprio
conceito de tempo compartilhado, que impede que um processo tome
o controle do processador indefinidamente e a proteção de memória
que impede que um processo acesse o espaço de memória de outro
processo em permissão.

A maioria dos sistemas operacionais é orientada a interrupção.


Isto quer dizer que ao realizar E/S, não ficam inquirindo (polling) o
hardware à espera da resposta. Ao contrário, o processo que executou
uma instrução de E/S fica aguardando, em uma fila do dispositivo em
questão, até que este termine e sinalize uma interrupção para a CPU.
27
01_SisOps.qxp 11/2/2009 11:35 Page 28

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Ao receber um sinal de interrupção, a CPU verifica em uma estrutura


especial, o vetor de interrupções, de qual dispositivo veio a
interrupção. Ao descobrir o dispositivo que está gerando a
interrupção, executa uma rotina de tratamento de interrupção
(interrupt handler) adequada ao dispositivo. Esta rotina lida com o
controlador do dispositivo, trazendo o resultado da instrução de E/S.
Com esta abordagem, a CPU fica livre para executar outros processos,
ao invés de ficar inquirindo um determinado dispositivo, aguardando
por uma E/S, por vezes demorada [Deitel, 2005].

As chamadas de sistemas e erros de execução também geram


interrupções de software, conhecidas como exceções (trap). Também
possuem entradas no vetor de interrupções a fim de que seja execu-
tada a rotina de tratamento associada a cada exceção.

28
01_SisOps.qxp 11/2/2009 11:35 Page 29

CAPÍTULO 2

Processos

Processos são programas em execução. Quando se fala em progra-


ma, deseja-se falar do código executável. O programa é uma entidade
passiva, pois não realiza por si só, nenhuma computação, estando
armazenado em uma mídia não-volátil.

Porém, ao ser executado, o programa passa à condição de


processo, uma entidade ativa. Nesta condição, controlado pelo
sistema operacional, é carregado na memória a partir de uma imagem
no disco e suas instruções são executadas na CPU. Pode solicitar o uso
de dispositivos de E/S, arquivos, receber/enviar sinais ou mensagens
para outros processos.

Em um computador pessoal, dezenas de processos executam em


um determinado momento. São processos do próprio sistema
operacional (kernel ou núcleo), processos do sistema ou processos
aplicativos. É para executar processos aplicativos que os usuários
utilizam os computadores. São editores de texto, planilhas, sistemas
gerenciadores de bancos de dados, compiladores, navegadores, entre
outros. Assim, o sistema operacional tem a importante tarefa de
coordenar o uso do hardware de forma que TODOS os processos sejam
executados de forma a satisfazer o usuário, isto é, procurando
minimizar o tempo de resposta das aplicações.

Coordenar a execução dos processos não é uma tarefa trivial, pelo


contrário. Existem diversas estratégias para realizar esta tarefa,
propostas em diversos sistemas operacionais no decorrer da evolução
da computação no mundo.

29
01_SisOps.qxp 11/2/2009 11:35 Page 30

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

2.1 Execução de um Processo

Após escrever um programa, este deverá se compilado (ou inter-


pretado) a fim de que possa executar. Isto porque o computador só
pode executar as instruções da sua própria arquitetura do conjunto de
instruções. Assim, o programa executável possui um conjunto de
instruções de baixo nível (linguagem Assembly). Estas instruções
deverão ser executadas seqüencialmente até o término da execução
do processo.

As instruções são basicamente de dois tipos: instruções de CPU


(tais como instruções aritméticas, acesso à memória) e instruções de
E/S (acesso a outros dispositivos de hardware (tais como disco,
teclado, mouse).

Um processo inicia sua execução executando instruções e


eventualmente executa uma instrução de E/S [Silberschatz, 2004]. O
acesso ao hardware é muito mais lento que o processador e a
memória, portanto, até que a E/S termine, dizemos que o processo
está em um ciclo de espera por E/S. Quando o processo executa
instruções de CPU, dizemos que está em um ciclo de CPU. Na
verdade, a execução de qualquer processo é uma alternância entre
ciclos de CPU e espera por E/S. A Figura 2.1 ilustra esta idéia.

Um processo sempre inicia e termina em um ciclo de CPU.

30
01_SisOps.qxp 11/2/2009 11:35 Page 31

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 2.1: Alternância de ciclos de CPU e E/S na execução das instruções de um processo.
Fonte: [Silberschatz, 2004]

No decorrer do tempo de vida de um processo, ele passa por


alguns estágios. Inicialmente o processo está no estado NOVO,
quando está sendo criado. Quando está apto a executar, é admitido no
sistema e passa ao estado de PRONTO. Quando chega a vez deste
processo executar, é escolhido pelo escalonador (é escalonado),
assim, passa ao estado de EXECUTANDO.

Quando está executando, podem acontecer três eventos


[Silberschatz, 2004]:

1. O processo executa a sua última instrução e termina, indo para


o estado TERMINADO. Nesta situação o processo é removido do sis-
tema.
2. O processo é interrompido (acontece a preempção),
normalmente causada pela estratégia de escalonamento dos
processos. Neste caso o processo volta ao estado de PRONTO.
3. O processo executa uma instrução de E/S ou aguarda um sinal.
Para não deixar a CPU ociosa, o processo que aguarda o evento fica
em uma fila de espera relacionada com o evento esperado.
É o estado BLOQUEADO.
31
01_SisOps.qxp 11/2/2009 11:35 Page 32

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Quando evento aguardado chega, o processo sai da fila de espera


e retorna ao estado de PRONTO, a fim de aguardar sua vez de
executar. Este processo cíclico se repete até que o processo esteja no
estado TERMINADO. A Figura 2.2 mostra o diagrama de estados de um
processo.

Figura 2.2: Diagrama de estados de um processo.


Fonte: [Silberschatz, 2004]

32
01_SisOps.qxp 11/2/2009 11:35 Page 33

CAPÍTULO 3

Threads

3.1 Introdução

Os primeiros sistemas operacionais permitiam que os processos


tivessem apenas uma linha de execução. A relativa simplicidade das
aplicações não exigia mais que isto. Com o aumento da complexidade
das aplicações, os sistemas operacionais passaram a permitir mais de
uma linha de execução pó processo, incorporaram o conceito de
threads.

Os programas que utilizam o recurso de multithreading se


caracterizam por ter mais de uma linha de execução, independentes
ou cooperativas. Veja exemplos de aplicações com várias linhas de
execução:

1. Editores de texto: edição do texto; corretor ortográfico;


tratamento de imagens; auto-gravação;
2. Navegadores: exibição de texto; exibição de imagens ou
animações; preenchimento/submissão de formulários;
3. Servidores Web: uma thread para atendimento de cada cliente
Web.

De fato, a maioria dos aplicativos comerciais se aproveita do


recurso de multithreading na abertura de múltiplas janelas.

Threads são conhecidas como “processos peso leve” (lightweight


process) [Silberschatz, 2004], pois compartilham o espaço de
33
01_SisOps.qxp 11/2/2009 11:35 Page 34

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

endereçamento do seu processo. Isto quer dizer que o processo de


criação de uma thread é mais rápido que a criação de um novo
processo, devido ao aproveitamento da estrutura já alocada ao seu
processo. Na Figura 3.1 é exibido um esquema de um processo com
uma thread e com várias threads.

Figura 3.1(a): Um processo com uma única thread.


Figura 3.1(b): Um processo com múltiplas threads.
Fonte: [Silberschatz, 2004]

Muitas vantagens podem ser ditas sobre o uso de várias threads


em uma aplicação. A vantagem mais óbvia é o paralelismo real em
sistemas multiprocessados, isto é, mais de uma thread de um mesmo
processo pode estar em execução ao mesmo tempo, acelerando o
término do processamento. Mesmo com o uso de um único processador
pode haver ganho de velocidade de processamento, pois threads
bloqueadas em espera por E/S não interferem na execução de outras
threads [Deitel, 2005].

Outra vantagem é a organização da lógica da aplicação, pois seus


módulos podem ser definidos como threads, sendo desenvolvidos em
unidades de código separadas. A própria lógica da aplicação pode
exigir o uso de múltiplas threads para explorar a concorrência de
execução, onde threads cooperativas realizam atividades distintas,
modificando dados compartilhados, como no problema do
produtor/consumidor.

34
01_SisOps.qxp 11/2/2009 11:35 Page 35

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

3.2 Modelos de criação de threads

A criação e execução de threads difere de um sistema operacional


para outro. As estratégias variam, mas podem ser resumidas em três
esquemas: modelo muitos-para-um, modelo um-para-um, modelo
muitos-para-muitos.

3.2.1 Modelo muitos-para-um

Neste esquema de criação de threads, o programador da aplicação


pode definir as threads de seu processo (threads de usuário) mas o
sistema operacional irá mapear apenas uma thread que será
efetivamente escalonada para o processador (thread de kernel).
A Figura 3.2 ilustra a idéia deste modelo [Silberschatz, 2004] [Deitel,
2005].

Figura 3.2: Modelo muitos-para-um.

Uma vantagem desta abordagem é que o sistema operacional não


precisa dar suporte a multithreading, facilitando a portabilidade,
além de permitir á aplicação ajustar a sua estratégia de
escalonamento de acordo com sua necessidade. Outra vantagem é que
processos com necessidade de comunicação e sincronização não
necessitam solicitar chamadas de sistemas para este fim, diminuindo
o custo operacional (overhead).

35
01_SisOps.qxp 11/2/2009 11:35 Page 36

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A desvantagem clara é a perda da concorrência ou paralelismo,


pois nunca duas threads do mesmo processo serão escalonadas
independentemente pelo sistema operacional. Isto acontece porque o
sistema operacional vê o processo como tendo uma única thread. Por
exemplo, quanto uma thread de um processo realizar E/S, todas as
threads ficarão bloqueadas até que a E/S solicitada termine.

3.2.2 Modelo um-para-um

Muito utilizado atualmente, este esquema de criação de threads


permite o máximo paralelismo ou concorrência das threads de cada
processo. Isto acontece pois cada thread de usuário é mapeada para
uma thread de kernel, sendo escalonadas independentemente umas
das outras. A Figura 3.3 mostra este mapeamento.

Figura 3.3: Modelo um-para-um.

Ao contrário do modelo anterior, o bloqueio de uma thread não


provoca o bloqueio das demais threads do mesmo processo.

Uma possível desvantagem deste modelo é o custo operacional de


operações de comunicação e sincronização, que serão mais lentas por
acontecer no ambiente do kernel.

36
01_SisOps.qxp 11/2/2009 11:35 Page 37

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

3.2.3 Modelo muitos-para-muitos

Esta estratégia tenta aproveitar as vantagens dos outros dois


modelos de mapeamento de threads de usuário para thread de kernel.
Nela, as threads de usuários são mapeadas para um número igual ou
menor de threads de kernel [Silberschatz, 2004].

Processos que tenham muitas linhas de execução podem obter


menos threads de kernel. Assim, o sistema operacional se previne
contra uma sobrecarga no número de threads de kernel, já que cada
uma consome memória e recursos de gerenciamento.

Uma abordagem de implementação deste modelo é o uso de


reservatório de threads (threads pool). Assim, a aplicação informa
quantas threads de núcleo necessitará e o sistema operacional
gerencia sua execução. Esta estratégia melhora a execução como um
todo pois reduz o custo de criação e destruição de threads, uma vez
que a aplicação usará um número fixo de threads de kernel,
pré-alocadas.

Na figura 3.4 temos a ilustração deste modelo.

Figura 3.4: Modelo muitos-para-muitos.

Um problema com esta estratégia é que complica bastante do


projeto do sistema operacional, introduzindo a complexidade de
gerenciar o mapeamento das threads.

37
01_SisOps.qxp 11/2/2009 11:35 Page 38

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

3.3 Operações realizadas sobre threads

As operações básicas realizadas sobre threads são:


• Criar: inicia a execução da thread. Uma thread costuma ser uma
função ou procedimento que é iniciado após o início do proces-
so, utilizando uma API específica.
• Terminar: Finaliza a execução da thread. Pode ser de dois tipos:
Cancelar: tenta finalizar a thread mas este sinal pode
ser mascarado
Abortar: finaliza imediatamente a thread.
• Suspender: Comum em sistemas unix. A thread fica bloqueada
até receber o sinal de retomada.
• Retomar: Retorna a thread do estado de suspensão.
• Dormir: Bloquea a thread por um período de tempo ou até que
receba um sinal de acordar.
• Acordar: Retoma a execução de uma thread bloqueada para
dormir.

Algumas implementações permite que uma thread primária seja


definida e que, ao terminar, finaliza o processo como um todo. Assim,
existe a operação associar (join) que não permite que a thread
primária termine até que threads associadas finalizem.

38
01_SisOps.qxp 11/2/2009 11:35 Page 39

CAPÍTULO 4

Escalonamento
de Processos

4.1 Introdução

O escalonador de curto prazo, o escalonador da CPU é o


responsável por escolher o próximo processo a executar na CPU. É um
programa do sistema operacional que é executado a toda troca de
contexto, ou seja, toda vez que um processo deixa a CPU. Neste
capítulo serão vistos alguns algoritmos que são utilizados para realizar
a escolha ou escalonamento do próximo processo (ou thread caso o SO
suporte).

4.2 Troca de contexto

Sempre que, por alguma razão um processo deixa a CPU, outro


processo deve ser escolhido para execução. É importante lembrar que
os processos executam alternando-se na CPU, seguindo o conceito de
tempo compartilhado. Isto implica na necessidade do processo
continuar do ponto de onde parou a cada retorno para execução
[Silberschatz, 2004].

O conjunto de todas as informações necessárias para a execução


de um processo é gravado em uma estrutura de dados chamada Bloco
de Controle de Processo ou PCB (Process Control Block). No PCB é

39
01_SisOps.qxp 11/2/2009 11:35 Page 40

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

copiado o conteúdo dos registradores, a pilha, mais informações sobre


o estado do processo, lista de arquivos abertos, contador de programa
(PC – Program Counter) entre outras.

O PCB é usado para salvar todas as informações sobre o processo


e sua execução de modo que ele possa sempre continuar de onde
parou. Trata-se do contexto do processo. Toda vez que um processo
deixa a CPU, o seu contexto deve ser salvo no seu PCB e o contexto do
próximo processo deve ser carregado para que execute. Esta é a troca
ou comutação de contexto. O número de troca de contexto não pode
ser tão elevado pois implicaria em um custo operacional (overhead)
proibitivo para o sistema.

4.3 Preempção de processos

A estratégia de tempo compartilhado implica em poder inter-


romper um processo em execução quando o seu tempo para executar
se expira. Mas esta não é a única razão para se interromper um
processo. Dependendo do tipo do algoritmo de escalonamento, podem
existir outros motivos.

Esta interrupção de um processo em execução, ou seja, no meio


de um ciclo de CPU, é chamada de preempção. Em sistemas
não-preemptivos, um processo somente deixa a CPU para realizar E/S
ou quando termina, ou seja, sempre completa seu ciclo de CPU.
Sistemas preemptivos permitem que um processo seja interrompido,
de acordo com a estratégia de escalonamento como será visto no
decorrer deste capítulo.

40
01_SisOps.qxp 11/2/2009 11:35 Page 41

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

4.4 Objetivos do escalonamento do processador

Existem diversas estratégias para realizar escalonamento do


processador [Silberschatz, 2004]. Mas de uma maneira geral todas têm
os objetivos de:
• Maximizar a utilização da CPU;
• Maximizar o rendimento (throughput), ou seja, atender ao
maior número de processos por unidade de tempo;
• Minimizar o tempo de resposta;
• Minimizar o tempo de espera dos processos na fila de prontos e
• Minimizar o tempo total de execução dos processos
(turnaround).

Dependendo do objetivo do sistema operacional, pode-se priorizar


alguns objetivos em detrimento de outros. Por exemplo, sistemas
interativos devem priorizar o mínimo tempo de resposta enquanto que
sistemas de tempo real devem valorizar o rendimento de processos
críticos.

4.5 Algoritmos de escalonamento

Os sistemas operacionais normalmente baseiam-se nas estratégias


FIFO, SJF, Prioridade e Round Robin, e suas combinações.

4.5.1 Escalonamento FIFO-First-In, First-Out

Neste algoritmo não-preemptivo, a idéia é atender aos processos


na ordem em que são submetidos ao sistema, ou seja, na ordem que
são admitidos na fila de processos prontos. O exemplo abaixo mostra
quatro processos que entraram no sistema em tempos distintos e têm
executados seus ciclos de CPU completamente antes de dar a vez para
o próximo processo [Silberschatz, 2004] [Deitel, 2005].
41
01_SisOps.qxp 11/2/2009 11:35 Page 42

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

O gráfico de Gantt abaixo mostra a execução dos processos na


linha do tempo.

No exemplo acima temos os seguintes tempos de espera e tempo


total:

E o tempo de espera médio fica em 8,75.

O algoritmo de escalonamento FIFO não é inteligente. Mas é sim-


ples de se implementar.

42
01_SisOps.qxp 11/2/2009 11:35 Page 43

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

4.5.2 Escalonamento SJF (Shortest Job First)

O escalonamento de Menor Job Primeiro ou Menor Processo


primeiro é o melhor algoritmo possível para escalonamento pois tem
o melhor rendimento. A idéia é atender ao processo com menor tempo
de pico de CPU primeiro [Silberschatz, 2004].

Abaixo segue o exemplo anterior utilizando este algoritmo em sua


versão não-preemptiva:

Para esta execução, temos os seguintes tempos de espera e tempo


total:

43
01_SisOps.qxp 11/2/2009 11:35 Page 44

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

O tempo de espera médio fica em 7, melhorando o desempenho


do sistema, pois prioriza os menores processos, aumentando o
rendimento. Note que o processo P1 inicia a execução pois ao chegar,
é o único, portanto não há nenhuma consideração de escalonamento
a ser feita. O mesmo exemplo é mostrado a seguir em uma versão do
algoritmo SJF com preempção.

Note que o desempenho do algoritmo aumenta substancialmente,


com um tempo médio de espera de apenas 3,5.

Infelizmente para este algoritmo ser viável nos sistemas modernos


seria necessário um conhecimento prévio do tamanho dos ciclos de
CPU dos processos, o que é impossível. Mesmo uma estimativa traria
mais custo, inviabilizando a estratégia. Contudo, este algoritmo é
importante para fins de comparação em simulações.

44
01_SisOps.qxp 11/2/2009 11:35 Page 45

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

4.5.3 Escalonamento por prioridades

Neste algoritmo, a cada processo é associada uma prioridade de


acordo com algum critério. Por exemplo, pode-se priorizar um
processo de tempo real ou um processo do sistema em detrimento de
processos comuns do usuário. Normalmente a prioridade é um número
e existem duas convenções possíveis: quanto menor o número maior a
prioridade ou quanto maior o número maior a prioridade. Vamos uti-
lizar a primeira convenção. Veja o exemplo do capítulo acrescido de
prioridades preemptivo [Silberschatz, 2004].

45
01_SisOps.qxp 11/2/2009 11:35 Page 46

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

4.5.4 Escalonamento Round Robin (Alternância Circular)

Neste algoritmo, cada processo tem direito a executar por um


período de tempo (fatia ou quantum de tempo). Ao término deste
tempo, o processo é interrompido e segue para o final da fila de
prontos, até que termine sua execução. Este algoritmo é muito
utilizado pois é ele que implementa a idéia do tempo compartilhado.
É um algoritmo justo, pois dá aos processos igual condição para
execução. A idéia é realizar um atendimento FIFO com preempção
causada pelo fim da fatia de tempo [Silberschatz, 2004].

O exemplo do capítulo é revisitado utilizando o algoritmo Round


Robin.

O tempo médio de espera neste exemplo fica em 7,75. Vale


ressaltar que, mais que simplesmente maximizar o rendimento, este
algoritmo executa de maneira igualitária os processos, sendo
adequado a processos interativos, reduzindo o tempo de resposta.

Uma questão que deve ser considerada sobre o algoritmo Round


Robin é o tamanho da sua fatia de tempo. Se o quantum for muito
pequeno, provocará alto overhead de trocas de contexto. Caso seja
muito grande, o escalonamento terá o efeito de FIFO, pois a fatia será
grande o suficiente para executar todo o ciclo de CPU dos processos.

46
01_SisOps.qxp 11/2/2009 11:35 Page 47

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

4.5.5 Escalonamento em Filas Multiníveis Com Realimentaçao

É comum que os sistemas operacionais utilizem não apenas uma,


mas várias filas de processos prontos. A cada fila é associada uma
prioridade e os processos são alocados às diversas filas de acordo com
os critérios de cada sistema. Cada fila pode ter seu próprio algoritmo
de escalonamento. Assim, um processo importante pode ser colocado
em uma fila de prioridade mais alta que um processo menos
importante [Silberschatz, 2004] [Deitel, 2005].

Existem duas abordagens para a execução os processo nas filas em


multiníveis. Com a prioridade absoluta, um processo de uma fila só
pode executar se não tiver nenhum processo nas filas de mais alta
prioridade. Esta estratégia pode causar starvation, ou seja, um
processo pode nunca ser executado se tiver uma prioridade muito
baixa.

A outra abordagem é dar porcentagens do tempo de execução


para cada fila. Esta estratégia inibe o problema de starvation, pois
todos os processos têm chance de executar.

A realimentação é a possibilidade de permitir a troca de


prioridade entre os processos. Isto pode ser dinâmico ou pela
intervenção eventual do usuário. Um processo pode trocar de
prioridade para melhorar seu tempo de resposta (aumentando de
prioridade) ou pode ir para uma fila de menor prioridade por ser
limitado por CPU. Depende dos critérios de cada desenvolvedor do
sistema operacional.

No exemplo da Figura 4.1, um processo poderia ser iniciado na fila


de mais alta prioridade. Caso utilizasse toda sua fatia de tempo, seria
deslocado para a fila de prioridade mais baixa, tendo uma fatia de
tempo maior. E assim por diante, até que na última fila, com
escalonamento FIFO, ficariam apenas os processos limitados por CPU,
que podem executar todo seu ciclo de CPU sem preempção.
N prática, as altas prioridades ficariam para os processos interativos
limitados por E/S.

47
01_SisOps.qxp 11/2/2009 11:35 Page 48

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 4.1: Filas em multinível com realimentação.

Os algoritmos e estratégias vistos neste capítulo mostram os


conceitos que são utilizados de maneira combinada e/ou modificada
nos sistemas operacionais disponíveis no mercado.

48
01_SisOps.qxp 11/2/2009 11:35 Page 49

CAPÍTULO 5

Comunicação e
Sincronização de
Processos

5.1 Introdução

Este capítulo apresenta como pode ser implementada a


concorrência de processos, os problemas do compartilhamento de
recursos e alguns dos mecanismos do sistema operacional para
sincronizar processos concorrentes. As soluções mais usadas são
semáforos e monitores, por isso, damos maior atenção a esses
mecanismos de sincronização.

5.2 Programação Concorrente

Com o surgimento da multiprogramação (também chamados de


sistemas multiprogramáveis) foi possível estruturar aplicações de
modo que trechos diferentes do código do programa pudessem
executar concorrentemente. Essa forma de execução recebeu o nome
de programação concorrente, pois tem como base a execução
cooperativa de múltiplos processos ou threads (também conhecidos
como processos leves) que trabalham em uma mesma tarefa na busca
de um resultado comum.

49
01_SisOps.qxp 11/2/2009 11:35 Page 50

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Em um sistema multiprogramável com um único processador, os


processos alternam sua execução seguindo critérios de escalonamen-
to estabelecidos pelo sistema operacional. Mesmo existindo
paralelismo implícito em nível de instrução, a programação
concorrente pode trazer benefícios no desempenho e execução da
aplicação. Já no caso de se ter multiprocessadores (sistemas com
múltiplos processadores), e aplicações que têm a possibilidade de exe-
cutar instruções em paralelo a programação concorrente exploram
ainda mais as vantagens de paralelismo implícito.

Infelizmente, no caso de programação concorrente, os processos


precisam compartilhar recursos do sistema (exemplo arquivos,
registradores, dispositivos de E/S e áreas de memória).
O compartilhamento desses recursos entre processos pode ocasionar
situações não desejadas que possam comprometer a execução das
aplicações.

Para evitar esse tipo de problema, os processos concorrentes


devem executar de forma sincronizada, e para isso se usam
mecanismos que são oferecidos pelo próprio sistema operacional.
Assim, se satisfaz o objetivo de ter a execução correta dos programas.

Em uma aplicação concorrente, em algumas situações, é


necessário que processos se comuniquem entre si. Esta comunicação
pode ser implementada usando diversos mecanismos tais como
variáveis compartilhadas na memória principal ou mecanismos de
trocas de mensagens. Em ambas as situações, é necessário que os
processos concorrentes tenham sua execução sincronizada através de
mecanismos do sistema operacional.

A figura 5.1 apresenta um exemplo no qual dois processos concor-


rentes compartilham um buffer para trocar informações por meio de
operações de escrita e leitura. Neste exemplo, um processo só poderá
gravar (escrever) dados no buffer caso este não esteja cheio. Da
mesma forma, um processo só poderá ler dados armazenados do
buffer caso exista algum dado para ser lido. Em ambas as situações,
os processos deverão aguardar até que o buffer esteja pronto de exe-
cutar essas operações (escrita e leitura).

50
01_SisOps.qxp 11/2/2009 11:35 Page 51

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 5.1: Comunicação e Sincronização de dois processos acessando um buffer


[Machado, 2007][Pinto, 2008]

Os mecanismos que garantem a comunicação entre processos


concorrentes e o acesso a recursos compartilhados são chamados de
mecanismos de sincronização. No projeto de sistemas operacionais
multiprogramados, é fundamental a implementação estes mecanismos
para garantir a integridade e a confiabilidade na execução das
aplicações concorrentes.

A sincronização e comunicação se aplicam também para


sub-processos e threads. Importante lembrar também que há
concorrência existe entre os processos e os recursos compartilhados.

Existem várias notações utilizadas para especificar a concorrência


em programas, ou seja, as partes de um programa que devem ser
executadas concorrentemente. As técnicas mais recentes tentam
expressar a concorrência no código dos programas de uma forma mais
clara e estruturada.

Segundo [Machado, 2007] [Tanenbaum, 2003] [Deitel, 2005]


[Silberschatz, 2004], uma das notações mais utilizadas é usando as
primitivas FORK e JOIN, que foram introduzidos por Conway, em 1963,
e Dennis e Van Horn, em 1966. Com o comando fork() é possível criar
um novo processo (ou thread), chamado de filho, que gera então um
problema computacional pois gera cncorrência entre o processo pai
(que fez o chamado do fork) e o processo (ou thread) novo recém
criado.

51
01_SisOps.qxp 11/2/2009 11:35 Page 52

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

O trecho seguinte exemplifica essa situação com dois processos


[Machado, 2007]: O programa A começa a ser executado e, ao
encontrar a primitiva fork, cria-se um outro processo que irá
executar o programa B, de forma concorrente com o programa A.
O comando join permite que os dois programas A e B, sejam
sincronizados. Quando o programa A encontrar o comando join só
continuará a ser executado após o termino da execução do programa
B.

Esses comandos, fork e join, são muito utilizados em sistemas


UNIX e Linux.

PROGRAM A; Program B;
FORK B' .
JOIN B' .
.

End
END.

Programa 5.1: Exemplo de uso dos comandos fork e join.

Segundo o Prof.º Machado (2008) “uma das implementações mais


claras e simples de expressar concorrência em um programa é por
meio do uso dos comandos PARBEGIN e PAREND”, que foram criados
por Dijkstra em 1965 [Machado, 2008]. Em várias linguagens de
programação, eles são chamados de COBEGIN e COEND.

O comando PARBEGIN especifica que a seqüência de comandos


deve ser executada concorrentemente em uma ordem imprevisível,
conforme se observa na figura 5.2. O exemplo mostra que o programa
executando via processo principal, mas depois cria-se novos processos
(Processo_l, Processo_2, Processo_n) para cada comando
(Comando_l, Comando_2, Comando_n). O comando PAREND define
um ponto de sincronização onde o processamento só continuará
quando todos os processos (ou threads) criados já tiverem terminado
suas execuções. Os comandos delimitados pelos comandos PARBEGIN e
PAREND podem ser comandos simples, como atribuições ou chamadas
a procedimentos (ver figura 5.2).

52
01_SisOps.qxp 11/2/2009 11:35 Page 53

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 5.2: Concorrência em Programas [Machado, 2007][Pinto, 2008]

Para exemplificar melhor o funcionamento dos comandos


PARBEGIN e PAREND em uma aplicação concorrente, considerem um
programa que resolve o cálculo do valor da expressão aritmética
seguinte [Machado, 2007]:

X := SQRT (1024) + (35.4 * 0.23) - (302 / 7)

Nesse programa [Machado, 2007] se observa que os três cálculos


podem ser realizados de forma concorrente pois eles são
independentes e se encontram dentro da estrutura PARBEGIN e
PAREND. O cálculo final da variável X só pode ser realizado quando
todas variáveis dentro da estrutura tiverem sido calculadas

53
01_SisOps.qxp 11/2/2009 11:35 Page 54

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

PROGRAM Calculo
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.

Programa 5.2: Exemplo do uso dos comandos PARBEGIN e PAREND.

54
01_SisOps.qxp 11/2/2009 11:35 Page 55

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

5.3 Problemas de Compartilhamento de Recursos

O exemplo seguinte é tomado do livro [Ribeiro, 2005]. Nesse


exemplo se observa que há problemas no acesso da variável conta,
pois não interessa qual dos dois processos (threads) atualize primeiro
essa variável, o valor dela estará gravado de forma inconsistente com
o desejado pelo programa.

#include <pthread.h>
#include <stdio.h> pthread_t tid1,tid2;
long conta=8;
void * t1()
{
long i ;
for (i=0; i<500000; i++) {
conta = conta + 5 ;}
printf("Encerrei t1\n");
}
void * t2()
{
long i ;
for (i=0; i<200000; i++) {
conta = conta + 2; }
printf("Encerrei a t2\n");
}
int main()
{
pthread_create(&tid1, NULL, t1, NULL);
pthread_create(&tid2, NULL, t2, NULL);
pthread_join(tid1,NULL);
pthread_join(tid2,NULL);
printf("O valor da variavel conta ~: %d\n", conta);
}

Programa 5.3: Exemplo de concorrência usando threads.

55
01_SisOps.qxp 11/2/2009 11:35 Page 56

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

No programa anterior, as threads t1 e t2 compartilham a variável


conta. Cada processo leve criado faz várias operações de adição a esta
variável. O esperado é que este programa sempre produza o valor
7.000.000, mas, quando se executa várias vezes, pode-se perceber
que o resultado é sempre diferente.

Isso acontece na troca de controle de processador entre as


threads. Imagine que o processo leve t1 esteja incrementando e o
valor da conta seja 100. O controle do processador é entregue para a
thread t2 que recebe o valor de conta igual a 100. Esta incrementa a
variável até 122. Ao retornar o controle para a thread t1, o valor de
conta é restaurado para 100, gerando incoerência do resultado.

A causa do problema está no acesso simultâneo à variável por t1


e t2. Para isto ser resolvido, o acesso à conta deverá ser feito de forma
mutuamente exclusiva.

A parte do código aonde uma ou mais variáveis compartilhadas


com outros processos são atualizadas é chamada de seção crítica.

As sessões críticas vão acontecer todas as vezes que:


• Um sistema excuta N processos, sendo N>1;
• Cada processo pode ter um código próprio;
• Os processos compartilham dados variáveis, de qualquer tipo;
• Cada processo possui sessões críticas onde atualizam os dados
compartilhados.

Portanto, é possível concluir que em qualquer situação, onde dois


ou mais processos (threads) compartilhem o mesmo recurso, há
possibilidades de uso inadequado (conflitos), que obriga a ter
mecanismos de controle para evitar esse tipo de problemas
(conhecidos como race conditions – condições de corrida).

Esses problemas podem ser resolvidos usando objetos especiais


para sincronização de processos, que são mais bem conhecidos como
semáforos. Esses objetos fazem a sincronização permitindo que
recursos que são compartilhados sejam utilizados de forma ordenada
e que o resultado de um programa seja sempre correto.
56
01_SisOps.qxp 11/2/2009 11:35 Page 57

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Os conflitos de acesso a um mesmo recurso, por processos concor-


rentes, são conhecidos como exclusão mútua.

5.4 Exclusão Mútua

A solução mais simples para evitar os problemas de


compartilhamento de recursos é impedir que dois ou mais processos
acessem um recurso de forma simultânea. Para isso, enquanto um
processo estiver acessando determinado recurso, todos os demais
processos que precisem acessá-lo deverão esperar pelo término da sua
utilização. Essa idéia de exclusividade de acesso é o que se conhece
de exclusão mútua (do inglês mutual exclusion).

A exclusão mútua deve afetar apenas os processos concorrentes


somente quando um deles estiver fazendo acesso ao recurso
compartilhado. Lembrando, a parte do código do programa onde é
feito o acesso ao recurso compartilhado é denominada região crítica
(do inglês critical region) [Machado, 2007] [Deitel, 2005] [Tanenbaum,
2003] [Silberschatz, 2004].

Se for possível evitar que dois processos entrem em suas regiões


críticas ao mesmo tempo, ou seja, se for garantida a execução
mutuamente exclusiva das regiões críticas, os problemas decorrentes
do compartilhamento seriam evitados.

Os mecanismos que implementam a exclusão mútua utilizam


protocolos de acesso à região crítica. Toda vez que um processo
precisar executar instruções de sua região crítica, obrigatoriamente
deverá executar antes um protocolo de entrada para poder ter
acesso nessa região. Da mesma forma, ao sair da região critica um
protocolo de saída deverá ser executado. Os protocolos de entrada e
saída garantem a exclusão mútua da região critica de um programa,
conforme se observa no trecho de código seguinte.

57
01_SisOps.qxp 11/2/2009 11:35 Page 58

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

BEGIN
*
*
*
Entra_Regiao_Critica; (* Protocolo de Entrada *)

Regiao_Critica;

Sai_Regiao_Critica; (* protocolo de Saida *)


*
*
END.

Programa 5.4: Exemplo básico de região crítica.

No caso de um programa que possua uma variável compartilhada,


como é o caso da variável conta em um programa de Conta Corrente,
a aplicação dos protocolos para dois processos (A e B) pode ser
implementada no compartilhamento do arquivo dessas
contas-correntes [Machado, 2007]. Sempre que o Processo A for
atualizar o saldo de um cliente, antes de ler o registro o acesso
exclusivo ao arquivo deve ser garantido por meio do protocolo de
entrada da sua região critica. O protocolo indica se já existe ou não
algum processo acessando o recurso. Caso o recurso esteja livre, o
Processo A pode entrar em sua região critica para realizar a
atualização da variável. Durante este período, caso o Processo B tente
acessar o arquivo, o protocolo de entrada faz com que esse processo
fique aguardando até que o Processo A finalize o acesso ao recurso e
faça sua atualização.

Quando o Processo A finalizar a execução de sua região critica,


deve sinalizar aos demais processos concorrentes que o acesso ao
recurso foi concluído. Isso é realizado usando o protocolo de saída,
que informa aos outros processos que o recurso já está livre e pode ser
utilizado de maneira exclusiva por um outro processo.

Assim, para garantir a implementação da exclusão mútua os


processos envolvidos devem fazer acesso aos recursos de forma
sincronizada.

58
01_SisOps.qxp 11/2/2009 11:35 Page 59

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Além de se programar esses mecanismos de exclusão mútua,


devem-se também oferecer suporte para evitar duas outras situações,
as quais são indesejadas.

A primeira situação indesejada é conhecida como espera indefini-


da (starvation) [Machado, 2007][Pinto, 2008], que é a situação em que
um processo nunca consegue executar sua região critica e, conse-
quentemente, acessar o recurso compartilhado. No momento em que
um recurso alocado é liberado, o sistema operacional possui um
critério para selecionar, dentre os processos que aguardam pelo uso do
recurso, qual será o escolhido.

Dependendo do critério de seleção, pode acontecer o problema do


starvation. Os critérios de escolha aleatória ou com base em
prioridades são exemplos de situações que podem gerar esse
problema. No primeiro caso, não é garantido que um processo em
algum momento fará uso do recurso que é compartilhado, pois a
seleção é de forma randômica. No segundo caso, a baixa prioridade de
um processo em relação aos demais pode impedir o processo de
acessar o recurso compartilhado. Uma solução bastante simples para
esse problema é a criação de filas de pedidos de alocação para cada
recurso, que usam a política de uso conhecida como FIFO.

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 localizado nessa fila.

Segundo Machado (2007), a segunda situação indesejada na


implementação da exclusão mútua é aquela em que um processo fora
da sua região crítica impede que outros processos entrem nas suas
próprias regiões críticas. No caso de esta situação acontecer, um
recurso estaria livre, porém alocado a um processo. Com isso, vários
processos estariam sendo impedidos de utilizar o recurso, reduzindo,
então, o grau de compartilhamento.

Várias soluções foram propostas para garantir a exclusão mútua de


processos concorrentes. A seguir, são apresentadas algumas soluções
de hardware e de software com discussões sobre os benefícios e
problemas de cada proposta.

59
01_SisOps.qxp 11/2/2009 11:35 Page 60

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

5.4.1 Soluções em Hardware

A exclusão mútua pode ser implementada usando mecanismos de


hardware, como por exemplo, soluções que desabilitam as
interrupções e instruções especiais do tipo test-and-set [Machado,
2007].

Desabilitar as interrupções:

É a solução mais simples para o problema da exclusão mútua


consiste em fazer com que o processo desabilite todas as interrupções
antes de entrar em sua região critica, e as reabilite após deixar a
região crítica. Como a mudança de contexto de processos só pode ser
realizada por meio de interrupções, então, o processo que as
desabilitou tem acesso exclusivo garantido.

A seguir um trecho de código que implementa esse mecanismo.


Esta solução é simples e apresenta algumas limitações. Primeiro, a
multiprogramação pode ficar seriamente comprometida, já que a
concorrência entre processos tem como base o uso de interrupções.
Um caso mais grave poderia ocorrer caso um processo desabilite as
interrupções e não as habilite novamente. Neste caso, é provável que
o sistema venha a ter seu funcionamento seriamente comprometido.

BEGIN
*
*
Desabilita_Interrupcoes;
Regiao Critica;
Habilita_Interrupcoes;
*
*
END

Programa 5.5: Exemplo de uso de interrupções e região crítica.

60
01_SisOps.qxp 11/2/2009 11:35 Page 61

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Em sistemas com múltiplos processadores, essa 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. Outra consideração é que o mecanismo de relógio
(clock) do sistema é implementado usando as interrupções, devendo
esta solução ser utilizada com muito cuidado e com critérios muito
bem estabelecidos.

Apesar dessas limitações, essa solução pode ser útil quando se


deseja que a execução de parte do núcleo do sistema operacional
ocorra sem que haja interrupção. Dessa forma, o sistema pode garan-
tir 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:

Machado (2007) afirma que muitos processadores possuem a


instrução especial, instrução test-and-set, de máquina, que permite
ler uma variável, armazenar seu conteúdo em uma outra área e
atribuir um novo valor à mesma variável. Essa instrução tem como
característica que é executada sem interrupção, ou seja, é uma
instrução indivisível. Dessa forma, é garantido que dois processos não
manipulem uma variável compartilhada ao mesmo tempo,
possibilitando a implementação da exclusão mútua.

A instrução test-and-set possui o seguinte formato, e quando


executada, o valor lógico da variável Y é copiado para X, sendo
atribuído à variável Y o valor lógico verdadeiro [Machado, 2007]
[Tanenbaum, 2007].

Test-and-Set (X, Y);

Para coordenar o acesso concorrente a um recurso, a instrução


test-and-set utiliza uma variável lógica global, que no programa
Test-and-Set recebe o nome de Bloqueio, ver exemplo do livro de
[Machado, 2007]. Quando a variável Bloqueio for falsa, qualquer
processo poderá alterar seu valor para verdadeiro por meio da
instrução test-and-set e, assim, acessar o recurso de forma exclusiva.

61
01_SisOps.qxp 11/2/2009 11:35 Page 62

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Ao terminar o acesso, o processo deve simplesmente retornar o


valor da variável para falso, liberando o acesso ao recurso (veja o
exemplo, tomado de [Machado, 2007]).

PROGRAM Test and Set;


VAR Bloqueio: BOOLEAN;

PROCEDURE Processo_A;
VAR Pode_A : BOOLEAN;
BEGIN
REPEAT
Pode_A := true;
WHILE (Pode AI DO
Test and Set (Pode A, Bloqueio);
Regiao Critica A;
Bloqueio := false
UNTIL false;
END;

PROCEDURE processo_B;
VAR Pode_B : BOOLEAN;
BEGIN
REPEAT
Pode_B := true;
WHILE (Pode B) DO
Test_and_Set (pode_B, Bloqueio);
Regiao Critica B;
BloqueIo := false;
UNTIL false;
END;

BEGIN
Bloqueio := false;
PARBEGIN
Processo_A;
processo_B;
PAREND;
END.
Programa 5.6: Exemplo de uso do comando test and set.

Interessante que em Machado (2007) e Pinto(2008) se oferece um


exemplo de execução desse programa. Os resultados são indicados na
tabela 5.1, e nela se observa que o Processo B executa a instrução

62
01_SisOps.qxp 11/2/2009 11:35 Page 63

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Test_and_Set antes do processo A, alterando o valor da variável


Bloqueio para true e executando a Regiao_Critica_B. Enquanto o
Processo B não alterar o valor da variável Bloqueio para false, o
Processo A ficará bloqueado. Quando o Processo B desbloquear o
acesso ao recurso, o Processo A poderá executar a Regiao_Critica_A.

Tabela 5.1: Execução do Programa test-and-set [Machado, 2007]

Importante salientar que o uso de uma instrução especial de


máquina oferece algumas vantagens, como a simplicidade de
implementação da exclusão mútua em múltiplas regiões criticas e o
uso da solução em arquiteturas com múltiplos processadores (multi-
processadores). Porém, apresenta como desvantagem a possibilidade
de ter starvation uma vez que a seleção do processo para acesso ao
recurso compartilhado é arbitrária.

5.4.2 Soluções em Software

Na tentativa de implementar a exclusão mútua por meio de


soluções de software têm sido propostos vários algoritmos.
Inicialmente, as soluções trataram apenas da exclusão mútua para
dois processos e, nas suas primeiras versões, apresentavam alguns
problemas.

63
01_SisOps.qxp 11/2/2009 11:35 Page 64

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A seguir apresenta-se de forma evolutiva como foi o desenvolvi-


mento de uma solução definitiva para a exclusão mútua entre vários
(N) processos, usando como referencia o material capítulo 7 do livro
[Machado, 2007].

5.4.2.1 Algoritmo 1

Este algoritmo apresenta uma solução para exclusão mútua entre


dois processos, onde um mecanismo de controle alterna a execução
das regiões críticas. No trecho de código seguinte, cada processo
(A e B) é representado por um procedimento que possui um laço (loop)
infinito (REPEAT/UNTIL), onde é feito o acesso a um recurso por
diversas vezes. A sequência de comandos, dentro do laço, é formada
por um protocolo de entrada, uma região crítica e um protocolo de
saída. A região critica é representada por uma rotina, onde o acesso
ao recurso realmente acontece. Após o acesso à região crítica, tanto
o Processo A quanto o Processo B realizam processamentos individuais.

O mecanismo utiliza uma variável de bloqueio, indicando qual


processo pode ter acesso à região critica. Inicialmente, a variável
global Vez é igual a 'A', indicando que o Processo A pode executar sua
região critica. O Processo B, por sua vez, fica esperando enquanto Vez
for igual a 'A'. 0 Processo B só executará sua região crítica quando o
Processo A atribuir o valor 'B' à variável de bloqueio Vez. Desta forma,
estará garantida a exclusão mútua entre os dois processos.

PROGRAM Algoritmo_l;
VAR Vez : CHAR;
PROCEDURE Processo_A;
BEGIN
REPEAT
WHILE (Vez = 'B') DO (* Nao faz nada *);
Regiao_Critica_A;
Vez := 'B';
processamento_Ai
UNTIL false;
END;

64
01_SisOps.qxp 11/2/2009 11:35 Page 65

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

PROCEDURE processo B;
BEGIN - -
REPEAT
WHILE (Vez = 'A') DO (* Nao faz nada *);
Regiao_Critica_B;
Vez :: 'A';
processamento_B;
UNTIL false; END;
BEGIN
Vez := ‘A’;
PARBEGIN
processo_A;
processo_B;
PAREND;
END.

Programa 5.7: Exemplo de exclusão mútua - Algoritmo 1.

Este algoritmo, apesar de implementar a exclusão mútua,


apresenta duas limitações, das quais a primeira surge do próprio
mecanismo de controle utilizado. O acesso ao recurso compartilhado
só pode ser realizado para dois processos e sempre de maneira
alternada; com isso, um processo que necessite utilizar o recurso mais
vezes do que outro permanecerá grande parte do tempo bloqueado.

No exemplo do algoritmo 1, é bom observar que caso o Processo A


fique muito tempo na rotina Processamento_A, é possível que o
Processo B queira executar sua região critica e não consiga, mesmo
que o Processo A não esteja utilizando o recurso. Como o Processo B
pode executar seu laço (loop) mais rapidamente que o Processo A, a
possibilidade de executar sua região critica fica limitada pela
velocidade de processamento do Processo A.

Segundo Machado (2007) e Renan Pinto (2008), outro problema


existente no algoritmo 1 é que no caso da ocorrência de algum
problema com um dos processos, de forma que a variável de bloqueio
não seja alterada, o outro processo permanecerá indefinidamente
bloqueado, aguardando o acesso ao recurso.

65
01_SisOps.qxp 11/2/2009 11:35 Page 66

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

5.4.2.2 Algoritmo 2

No caso do algoritmo 1, ambos os processos usam a mesma


variável que foi declarada como global e seu conteúdo indica qual
processo tem o direito de entrar na região crítica. Para evitar essa
situação, o algoritmo 2 propõe usar uma variável para cada processo
(CA e CB) que indica se o processo estão ou não em sua região crítica.
Neste caso, toda vez que um processo desejar entrar em sua região
crítica a variável do outro processo é testada para verificar se o
recurso está livre para uso.

O código do algoritmo 2 é apresentado no trecho seguinte, e é


tomado do livro [Machado, 2007]. Neste algoritmo, o uso do recurso
não é realizado necessariamente alternado. Caso ocorra algum
problema com um dos processos fora da região crítica, o outro
processo não ficará bloqueado, mas o problema não é resolvido de
forma completa. Uma vez que, caso um processo tenha um problema
dentro da sua região crítica, ou antes, de alterar a variável, o outro
processo permanecerá indefinidamente bloqueado. Na prática, esta
solução é pior do que o primeiro algoritmo, pois além desse bloqueio
nem sempre a exclusão mútua é garantida.

PROGRAM Algoritmo_2;
VAR CA, CB: BOOLEAN;
PROCEDURE Processo_A;
BEGIN
REPEAT
WHILE (CB) DO (* Nao faz nada *);
CA := true;
Regiao_Critica_A;
CA : = false;
processamento_A;
UNTIL false;
END;

66
01_SisOps.qxp 11/2/2009 11:35 Page 67

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

PROCEDURE Processo_B; BEGIN


REPEAT
WHILE (CA) DO (* Nao faz nada *);
CB : = true;
Regiao_Critica_B;
CB : = false;
Processamento_B;
UNTIL false;
END;
BEGIN
CA : = false;
CB : = false;
PARBEGIN
processo_A;
processo_B;
PAREND;
END.

Programa 5.8: Exemplo de exclusão mútua - Algoritmo 2.

67
01_SisOps.qxp 11/2/2009 11:35 Page 68

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

5.4.2.3 Algoritmo 3

O algoritmo 3 tenta solucionar o problema apresentado no


algoritmo 2, colocando a instrução de atribuição das variáveis CA e CB
antes do laço de teste (ver código seguinte, tomado do livro
[Machado, 2007]).

PROGRAM Algoritmo_3;
VAR CA, CB : BOOLEAN;
PROCEDURE processo_A;
BEGIN
REPEAT
CA : = true:
WHILE (CB) DO (* Nao faz nada *);
Regiao_Critica_A;
CA : = false;
processamento_A;
UNTIL false;
END;
PROCEDURE processo_B;
BEGIN
REPEAT
CB : = true:
WHILE (CA) DO (* Nao faz nada *);
Regiao_Critica_B;
CB := false;
processamento_B;
UNTIL false;
END;

Programa 5.9: Exemplo de exclusão mútua - Algoritmo 3.

Essa alteração faz com que exista garantia da exclusão mútua,


mas introduz um novo problema, relacionado com a possibilidade de
bloqueio indefinido de ambos os processos (conhecido como
deadlock) [Tanenbaum, 2003] [Deitel, 2005] [Silberschatz, 2004].

68
01_SisOps.qxp 11/2/2009 11:35 Page 69

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Isso acontece na situação em que os dois processos alterem as


variáveis CA e CB antes da execução da instrução WHILE, e neste caso,
nenhum dos dois processos poderá entrar em suas respectivas regiões
críticas, como se o recurso já estivesse alocado.

A possível existência desse problema dá origem ao algoritmo 4,


que tenta resolvê-lo.

5.4.2.4. Algoritmo 4

No caso do algoritmo 3, cada processo altera o estado da sua


variável indicando que irá entrar na região crítica sem conhecer o
estado do outro processo, e por isso gera o problema de deadlock
[Deitel, 2005].

O algoritmo 4 apresenta uma implementação onde o processo, da


mesma forma, altera o estado da variável antes de entrar na sua
região crítica, mas conforme se explica em Machado (2007), ainda
assim existe a possibilidade de esta alteração ser revertida. O código
segue o exemplo apresentado por Machado (2007).

Apesar de a solução garantir a exclusão mútua e não gerar


bloqueio simultâneo dos processos, uma nova situação indesejada
pode ocorrer eventualmente. No caso de os tempos aleatórios serem
próximos e a concorrência gerar uma situação onde os dois processos
alterem as variáveis CA e CB para falso antes do fim do laço, nenhum
dos dois processos conseguirá executar sua região crítica. Assim, esta
solução pode ainda gerar alguns problemas.

69
01_SisOps.qxp 11/2/2009 11:35 Page 70

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

PROGRAM Algoritmo_4;
VAR CA,CB : BOOLEAN;
PROCEDURE Processo_A;
BEGIN
REPEAT
CA := true;
WHILE (CB) DO
BEGIN
CA : = false;
{ pequeno intervalo de tempo aleatorio } CA := true
END;
Regiao_Critica_A:
CA :=false;
UNTIL false;
END

PROCEDURE Processo_B;
BEGIN
REPEAT
CB := true;
WHILE (CA) DO
BEGIN
CB : = false;
{ pequeno intervalo de tempo aleatorio } CB := true;
END;
Regiao_Critica_B;
CB := false;
UNTIL false;
END;
BEGIN
CA : = false;
CB : = false;
PARBEGIN
processo_A;
processo_B;
PAREND;
END.

Programa 5.10: Exemplo de exclusão mútua - Algoritmo 4.

70
01_SisOps.qxp 11/2/2009 11:35 Page 71

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

5.5 Algoritmo de Peterson

Conforme explica o professor Machado (2007) e Sementille (2006),


a primeira solução de software que garantiu a exclusão mútua entre
dois processos sem a incorrência de outros problemas, foi proposta
pelo matemático holandês T. Dekker, que tomou como base os
algoritmos 1 e 4. Esse algoritmo é conhecido como algoritmo de
Dekker e possui uma lógica bastante complexa e pode ser encontrado
em Stallings (2007). Posteriormente, G. L. Peterson propôs outra
solução mais simples para o problema da exclusão mútua entre dois
processos (ver trecho seguinte, tomado de [Machado, 2007]).

PROGRAM Algoritmo_peterson;
VAR CA,CB: BOOLEAN;
Vez : CHAR;
PROCEDURE Processo_A;
BEGIN
REPEAT
CA : = true:
Vez := 'B'i
WHILE (CB and Vez = `B`) DO (* Não faz nada *);
Regiao_Critica_A;
CA := false;
processamento_A;
UNTIL false;
END;
PROCEDURE Processo_B;
BEGIN
REPEAT
CB : = true;
Vez := 'A'i
WHILE (CA and Vez = ‘A’) DO (* Não faz nada *);
Regiao_Critica_B;
CB : = false:
processamento_B:
UNTIL false;
END;
BEGIN
CA := false;
CB := false;
PARBEGIN
processo_A;
processo_B;
PAREND;
END.

Programa 5.11: Exemplo de exclusão mútua - Algoritmo de Peterson.

71
01_SisOps.qxp 11/2/2009 11:35 Page 72

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Similar ao algoritmo 3, o algoritmo de Peterson, além de usar as


variáveis condicionais (CA e CB), que indicam o desejo de cada
processo entrar em sua região crítica, introduz a variável Vez para
resolver os conflitos gerados pela concorrência.

Neste caso, antes de acessar a região crítica, o processo sinaliza


esse desejo através da variável de condição, porém, o processo cede
o uso do recurso ao outro processo, indicado pela variável ‘Vez’. Em
seguida, o processo executa o comando WHILE como protocolo de
entrada da região crítica. Neste caso, além da garantia da exclusão
mútua, o bloqueio indefinido de um dos processos no laço nunca
ocorrerá, já que a variável Vez sempre permitirá a continuidade da
execução de um dos processos.

O algoritmo proposto por G. L. Peterson pode ser facilmente


generalizado para o caso de N processos.

5.6 Sincronização Condicional

A sincronização condicional acontece quando o acesso ao recurso


compartilhado exige a sincronização de processos e está vinculada a
urna condição de acesso. Um recurso pode não se encontrar pronto
para uso devido a uma condição específica. Nesse caso, o processo que
deseja acessá-lo deverá permanecer bloqueado até que o recurso
fique disponível.

Um exemplo clássico dessa situação é a comunicação entre dois


processos por meio de operações de escrita e leitura em um buffer
(lembrar exemplo da figura 5.1). Esses processos geram informações
(processos produtores) que são utilizadas por outros processos
(processos consumidores).

Nessa comunicação, enquanto um processo escreve dados em um


buffer, o outro lê os dados, de forma concorrente. Os processos
envolvidos devem estar sincronizados a uma variável de condição, de
forma que um processo não tente escrever dados em um buffer cheio
ou realizar uma operação de leitura em um buffer vazio.
72
01_SisOps.qxp 11/2/2009 11:35 Page 73

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

O trecho de código do exemplo, baseado no exemplo da


[Machado, 2007] mostra o problema da sincronização condicional,
também conhecido como problema do produtor/consumidor ou do
buffer limitado.

PROGRAM Produtor_Consumidor_l;
CONST TamBuf = (* Tamanho gualguer *);
TYPE Tipo_Dado = (* Tipo gualguer *);
VAR Buffer: ARRAY [l .. TamBufJ OF Tipo_Dado;
Dado_l :Tipo_Dado;
Dado_2 : Tipo_Dado;
Cont : O .. TamBuf;
PROCEDURE Produtor;
BEGIN
REPEAT
Produz_Dado (Dado_l);
WHILE (Cont = TamBuf) DO (* Nao faz nada *);
Grava_Buffer (Dado_l, Buffer);
Cont := Cont + 1;
UNTIL false;
END;
PROCEDURE Consumidor;
BEGIN
REPEAT
WHILE (Cont = 0) DO (* Nao faz nada *);
Le_Buffer (Dado_2, Buffer);
Consome_Dado (Dado_2);
Cont := Cont - 1;
UNTIL false;
END;
BEGIN
Cont := 0;
PARBEGIN
produtor;
Consumidor;
PAREND;
END.

Programa 5.12: Exemplo de produtor/consumidor.

73
01_SisOps.qxp 11/2/2009 11:35 Page 74

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

É possível observar que o recurso compartilhado é um buffer,


definido no algoritmo com o tamanho TamBuf e está sendo controlado
pela variável Cont. Sempre que a variável Cont for igual a 0, significa
que o buffer está vazio e o processo Consumidor deve permanecer
aguardando até que se escreva um dado. Da mesma forma, quando a
variável Cont for igual a TamBuf, significa que o buffer está cheio e o
processo Produtor deve aguardar a leitura de um novo dado. Como se
observa no código, a tarefa de colocar e retirar os dados do buffer é
realizada, respectivamente, pelos procedimentos Grava_Buffer e
Le_Buffer, que são executados de forma mutuamente exclusiva. Nesse
algoritmo, não está sendo considerada a implementação da exclusão
mútua com a variável compartilhada Cont.

Com esta solução consegue-se resolver o problema da


sincronização condicional, porém existe possibilidade de acontecer o
problema da espera ocupada. Isso somente é resolvido usando
mecanismos de sincronização conhecidos como semáforos e
monitores.

5.7 Semáforos

O conceito de semáforos foi proposto pelo professor E. W.


Dijkstra, em 1965. A solução é um mecanismo de sincronização de
processos que permite implementar, de forma simples, a exclusão
mútua e a sincronização condicional.

A utilização de semáforos é hoje um dos principais mecanismos


usados em projetos de sistemas operacionais e em aplicações
concorrentes. Atualmente, a maioria das linguagens de programação
disponibiliza bibliotecas para uso de semáforos.

Um semáforo é uma variável do tipo inteiro que só pode ser


manipulada por duas instruções. No livro [Machado, 2007] elas são
denominadas de DOWN e UP, mas o Prof. Dijkstra as chamou,
inicialmente, de instruções P (proberen, que significa teste em
holandês) e V (verhogen, que em holandês significa incremento).

74
01_SisOps.qxp 11/2/2009 11:35 Page 75

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Essas duas instruções P( ) = UP e V( ) = DOWN são indivisíveis, isto


é, a execução destas instruções não pode ser interrompida, conforme
se observa no trecho de código seguinte.

PROGRAM Semaforo_l;
VAR s : Semáforo := 1; (* inicializa o semáforo *)

PROCEDURE Processo_A;
BEGIN
REPEAT
DOWN (s);
Regiao_Critica_A;
UP (s);
UNTIL false;
END;

PROCEDURE Processo_B;
BEGIN
REPEAT
DOWN (s);
Regiao_Critica_B;
UP (s);
UNTIL false;
END;

BEGIN
PARBEGIN
processo_A;
processo_B;
PAREND;
END.

Programa 5.13: Exemplo de semáforo - Instruções DOWN e UP.

A instrução UP incrementa uma unidade ao valor do semáforo,


enquanto a DOWN decrementa a variável. Por definição, não há como
atribuir valores negativos a um semáforo, então, a instrução DOWN
executada em um semáforo com valor 0 faz com que o processo entre
no estado de espera.
75
01_SisOps.qxp 11/2/2009 11:35 Page 76

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Em geral, essas instruções são implementadas no processador, que


deve garantir todas essas condições.

Os semáforos podem ser classificados como binários ou


contadores. Os binários são também chamados de mutexes (mutual
exclusion semaphores), só podem assumir os valores 0 e 1, enquanto
os semáforos contadores podem assumir qualquer valor inteiro
positivo, além do O.

A exclusão mútua pode ser implementada usando um semáforo


binário, o qual é associado ao recurso compartilhado. A principal
vantagem desta solução em relação aos algoritmos estudados
anteriormente, é que não há espera ocupada.

As instruções DOWN e UP funcionam como protocolos de entrada


e saída, respectivamente, para que um processo possa entrar e sair de
sua região crítica. O semáforo fica associado a um recurso
compartilhado, indicando quando o recurso está sendo acessado por
um dos processos concorrentes. Quando o valor do semáforo é igual a
1, indica que nenhum processo está utilizando o recurso, enquanto o
valor 0 indica que o recurso está sendo utilizado.

Toda vez que um processo deseja entrar na sua região critica, um


processo executa uma instrução DOWN. Se o semáforo for igual a 1,
este valor é decrementado, e o processo que solicitou a operação
pode executar as instruções da sua região critica. De outra forma, se
uma instrução DOWN é executada em um semáforo com valor igual a
0, o processo fica impedido do acesso, permanecendo em estado de
espera e, consequentemente, não gera sobrecarga (overhead) no
processador.

O processo que está acessando o recurso, ao sair de sua região


crítica, executa a instrução UP, incrementando o valor do semáforo e
liberando o acesso ao recurso. Se um ou mais processos estiverem
esperando pelo uso do recurso (operações DOWN pendentes), o sis-
tema selecionará um processo na fila de espera associada ao recurso
e alterará o seu estado para pronto.

76
01_SisOps.qxp 11/2/2009 11:35 Page 77

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

O trecho de código anterior mostra um exemplo de uso de


semáforo. O exemplo foi tomado de [Machado, 2007][Silberschatz,
2005]. Pode-se observar que o semáforo é inicializado com o valor 1,
indicando que nenhum processo está executando sua região crítica.

Importante salientar que toda vez que se muda os valores dos


semáforos, eles são realizados com código que fica inserido como
biblioteca, e por esse motivo existe uma biblioteca que permite a
realização atômica dessas instruções.

Em programas que usam linguagem C, o código da biblioteca é


feito e deve ser incluído como um include, para assim poder utilizar
as chamadas aos procedimentos P( ) e V( ). Geralmente essa
biblioteca é armazenada com o nome do seu criador, neste caso,
Dijkstra.c, e colocada então nas primeiras linhas de código, junto aos
include como <include dijkstra.h>.

Segundo [Ribeiro, 2005], quando se faz uso da biblioteca dijkstra,


ela oferece aos programas, basicamente as seguintes quatro funções:

Sem_Create(key_t key, int initval): Cria um conjunto de


semáforos com a chave key e com o valor inicial do semáforo
initval.
P(int semid): A operação P bloqueia o recurso se o valor do
semáforo for 0 e -1 bloqueia 0 processo.
v(int semid): A operação V libera o recurso.
sem_delete(int semid): Remove o semáforo criado.

A seguir um exemplo em C do uso de semáforos, usando a


biblioteca [Ribeiro, 2005]. Conforme explica [Ribeiro, 2005], suponha
que o programa foi salvo com o nome "semaforo_binario.c", então,
para compilá-lo deve-se digitar o seguinte comando:

gcc semaforo_binario.c -o semaforo_binario

Em [Ribeiro, 2005] aparece quando o programa é executado


(# ./semaforo_binario) se produz o seguinte resultado:

77
01_SisOps.qxp 11/2/2009 11:35 Page 78

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Um semaforo foi criado com o identificador 98304.


Processo filho usa o recurso.
Processo PAI bloqueia ao tentar acessar recurso.
Processo filho libera o recurso.
Recurso disponivel para o processo PAI.

Nesse exemplo, o semáforo vai controlar um recurso


compartilhado qualquer disputado por dois processos concorrentes
criados com a primitiva fork(). O processo filho bloqueia os recursos
com a instrução P(). Quando o processo pai tentar utilizar o recurso
usando também a instrução P() é bloqueado até que o processo filho
libere os recursos com a função V().

78
01_SisOps.qxp 11/2/2009 11:35 Page 79

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <unistd.h>
#include "dijkstra.h"
#define KEY 123

int main()
{
int sem;
sem = sem_create(KEY,l)
printf("Um semaforo foi criado com 0 identificador
%d.\n",sem);
if (fork() == 0)
{
printf("\tProcesso filho usa 0 recurso \n");
P (sem) ;
sleep(8) ;
printf("\tProcesso filho libera 0 recurso.\n");
V(sem) ;
sleep (1) ;
else
{
sleep(l) ;
printf("Processo PAl bloqueia ao tentar acessar
recurso.\n");
P(sem) ;
printf("Recurso disponivel para o processo
PAI.\n");
sem_delete(sem) ;
}
exit (0);
}
Programa 5.14: Exemplo de semáforo - Instruções V(sem) e P(sem).

Para enfatizar ainda mais o uso dos semáforos na linguagem C, a


seguir se apresenta o código certo que sincroniza dois processos
acessando a mesma variável, chamada de cont, no inicio do capítulo
79
01_SisOps.qxp 11/2/2009 11:35 Page 80

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

e que apresentava problemas de acesso, pois era compartilhada e


quando se executava dava problemas sempre imprimindo os valores
inadequados dessa variável. O exemplo é aquele existente em
[Ribeiro, 2005].

Conforme explica [Ribeiro, 2005], supondo que esse programa é


armazenado com o nome: exclusaomLitua_ok.c, então, para compilar
deve-se usar o seguinte comando:

# gcc -lpthread exclusaomutua_ok.c -0 exclusaomutua_ok

Na execução se observa que um novo semáforo binário é criado


com a função sem_create() e seu identificador é passado como
argumento para as threads, as quais são criadas com a instrução
pthread_create(). Cada processo leve (thread) solicitará o recurso
compartilhado usando a primitiva P() antes de começar suas
respectivas operações na seção crítica. Observe também que ao
finalizar o acesso à seção crítica, cada procedimento libera o acesso
ao recurso compartilhado usando a primitiva V().

Quando algum thread ganhar a concessão do recurso com a função


P(), o outro processo que tentar acessar o recurso ficará suspenso até
que o primeiro execute a primitiva V(). O semáforo garante que não
haverá conflito pelo uso da variável conta e o resultado da operação
sempre será o correto e o esperado.

Os semáforos binários são simples e fáceis de implementar em


programas concorrentes e resolvem com elegância a maioria dos
problemas de exclusão mútua.

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include "dijkstra.h"
#include <pthread.h>
#include <stdio.h>
#define KEY 1234

80
01_SisOps.qxp 11/2/2009 11:35 Page 81

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

pthread_t tid1.tid2;
long conta=0;

void * t1(int sem) {


P (sem) ;
long i :
for (i=0; i<1000000; i++) {
conta = conta + 5
}
printf("Encerrei t1\n");
V(sem) ;
}
void * t2(int sem) {
P (sem) :
long i :
for (i=0: i<1000000; i++) {
conta = conta + 2; }
printf("Encerrei a t2\n");
V(sem);
}
int main()
{
int sem;
sem = sem_create(KEY.1) ;
printf("Um semaforo foi criado com o identificador
%d.\n".sem);
pthread_create(&tid1. NULL. t1. (void *)sem);
pthread_create(&tid2. NULL. t2. (void *)sem) ;
pthread_join(tid1.NULL) ;
pthread_join(tid2.NULL) ;
sem_delete(sem);
printf("O valor da variável conta igual a: %d\n". conta);;
}

Programa 5.15: Exemplo de concorrência usando threads e primitivas P(sem) e V(sem).

81
01_SisOps.qxp 11/2/2009 11:35 Page 82

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

5.8 Monitores

Monitores são mecanismos de sincronização de alto nível, tornan-


do mais simples o desenvolvimento de aplicações concorrentes.

Em Machado (2007) se explica que o conceito de monitores foi


proposto por Brinch Hansen, em 1972, e desenvolvido por C.A.R.
Hoare em 1974, como um mecanismo de sincronização estruturado.
Lembrar que os semáforos são considerados não-estruturados.

Lembrar que o uso de semáforos exige do desenvolvedor bastante


cuidado, pois qualquer engano pode levar a problemas de
sincronização imprevisíveis e difíceis de serem reproduzidos devido à
execução concorrente dos processos.

Monitores são considerados mecanismos de alto nível e devem ser


estruturados, pois estão em função de serem implementados pelo
compilador. Assim, o desenvolvimento de programas concorrentes fica
relativamente mais fácil e diminui as chances de erro.

Conforme se explica em [Machado, 2007][Silberschatz, 2004],


inicialmente, algumas poucas linguagens de programação, como
Concurrent Pascal, Modula-2 e Modula-3, ofereceram suporte ao uso
de monitores. Atualmente, a maioria das linguagens de programação
disponibiliza rotinas para uso de monitores.

O monitor é formado por procedimentos e variáveis encapsulados


dentro de um módulo. Possui como principal característica a
implementação automática da exclusão mútua entre os
procedimentos declarados, isto é, somente um processo pode estar
executando um dos procedimentos do monitor em um determinado
instante.

Toda vez que algum processo faz uma chamada a um desses


procedimentos, o monitor verifica se já existe outro processo
executando algum procedimento do monitor. Caso exista, o processo
ficará aguardando a sua vez em uma fila de entrada. As variáveis
globais de um monitor são visíveis apenas aos procedimentos da sua
estrutura, sendo inacessíveis fora do contexto do monitor.
82
01_SisOps.qxp 11/2/2009 11:35 Page 83

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A inicialização das variáveis é realizada por um bloco de


comandos do monitor, sendo executado apenas uma vez, na ativação
do programa onde está declarado o monitor [Silberschatz, 2004].

Um monitor é definido especificando seu nome e declarando as


variáveis locais, assim como definindo os procedimentos e um código
de inicialização. A estrutura de um monitor é mostrada no seguinte
trecho de código [Machado, 2007]:

MONITOR Exclusão Mutua;


(* Declaração das Variáveis do Monitor *)

PROCEDURE Região_Critica_1;
BEGIN


END;

PROCEDURE Regiao_Critica_2;
BEGIN


END;
BEGIN
(* Codigo de Inicializacao *)
END;

Programa 5.16: Exemplo básico de exclusão mútua usando monitores.

Importante salientar que quando se usam monitores, a exclusão


mútua não é realizada diretamente pelo programador (ao contrário do
uso de semáforos). As regiões críticas devem ser definidas como
procedimentos no monitor, e então, o compilador se encarregará de
garantir a exclusão mútua entre esses procedimentos.

A comunicação do processo com o monitor é feita unicamente por


meio de chamadas a seus procedimentos com seus respectivos
parâmetros.
83
01_SisOps.qxp 11/2/2009 11:35 Page 84

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A seguir mostra-se o exemplo de uso de um monitor, baseado no


material [Pinto, 2008][Machado, 2007], no qual dois processos se
comunicam e realizam operações de incrementar (soma especial: X
+1) e decrementar (subtração especial: X – 1), de modo concorrente,
na mesma variável X que é compartilhada.

A inicialização da variável X com o valor zero só acontecerá uma


vez, no momento da inicialização do monitor Regiao_Critica. No
exemplo mostrado, pode-se garantir que o valor de X ao final da
execução dos processos concorrentes Soma e Diminui será igual a
zero, uma vez que os procedimentos estão definidos dentro do
monitor se garante então a execução com exclusão mútua.

PROGRAM Monitor_1;
MONITOR Região_Critica;
VAR X: Integer;

PROCEDURE Soma;
BEGIN
X:= X +1;
END;

PROCEDURE Diminui;
BEGIN
X := X – 1;
END;
BEGIN
X := 0;
END;
BEGIN
PARBEGIN
Regiao_Critica.Soma;
Regiao_Critica.Diminui;
PAREND;
END.

Programa 5.17: Exemplo usando monitores.

84
01_SisOps.qxp 11/2/2009 11:35 Page 85

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Importante salientar também que os monitores podem ser usados


na implementação da sincronização condicional, pois se usando de
variáveis especiais de condição, é possível associar a execução de um
procedimento que faz parte do monitor a uma determinada condição,
garantindo então a sincronização condicional [Machado,
2007][Deitel, 2001].

As variáveis especiais de condição são manipuladas por


intermédio de duas instruções, conhecidas como WAIT e SIGNAL.
A instrução WAIT faz com que o processo seja colocado no estado de
espera, até que algum outro processo indique (usando o sinal SIGNAL)
que a condição de espera já foi satisfeita (ver o seguinte exemplo de
trecho de código [Machado, 2007]). No caso da instrução SIGNAL for
executada e não houver processo aguardando a condição, não haverá
efeito nenhum.

MONITOR Condicional;
Var Cheio, Vazio: (* Variáveis especiais de condição *);
PROCEDURE Produz;
BEGIN
IF (Cont = TamBuf) THEN WAIT (Cheio);


IF (Cont = 1) THEN SIGNAL (Vazio);
END;

PROCEDURE Consome;
BEGIN
IF (Cont = 0) THEN WAIT (Vazio);


IF (Cont = TamBuf - 1) THEN SIGNAL (Cheio);
END;
BEGIN
END;

Programa 5.18: Exemplo de monitores condicionais.

85
01_SisOps.qxp 11/2/2009 11:35 Page 86

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Em Machado (2007) se destaca que é possível que vários processos


estejam com suas execuções suspensas, aguardando a sinalização de
diversas condições. Nesse caso, o monitor organiza os processos em
espera utilizando filas associadas às condições de sincronização.

A execução da instrução SIGNAL libera apenas um único processo


da fila de espera da condição associada. Um processo pode executar
um procedimento de um monitor, mesmo quando um ou mais
processos estão na fila de espera de condições.

Considerando que o exemplo do produtor e consumidor é


importante, a seguir se apresenta mais um exemplo dele, mas usando
na solução de sincronização um monitor condicional com duas
variáveis especiais de condição que indicam a situação de Cheio e
Vazio, e os dois procedimentos Produz e Consome.

Sempre que o processo produtor pretender escrever um dado no


buffer, então deve fazê-lo realizando uma chamada ao procedimento
do monitor, chamado de Produz (no exemplo, aparece como
Condicional.Produz [Machado, 2007[Deitel, 2005].

Nesse procedimento, verifica-se se o número de posições


ocupadas no buffer é igual ao seu tamanho, isto é, testa-se se o buffer
está cheio. Caso o teste seja verdadeiro, o processo deve executar um
WAIT na variável Cheio, indicando que a execução dependerá dessa
condição, e permanece aguardando em uma fila de espera associada
à variável Cheio. O processo bloqueado só continuará sua execução
quando um processo Consumidor executar um SIGNAL na variável
Cheio, indicando então que um elemento do buffer foi consumido.

No caso do processo Consumidor, sempre que tentar ler um dado


do buffer deve realizá-lo usando uma chamada ao procedimento do
monitor, chamada Consome (no exemplo, aparece como
Condicional.Consome [Machado, 2007]. Sua condição de execução
depende da existência, de no mínimo, um elemento no buffer. Quando
o buffer está vazio, o processo deve executar um WAIT na variável
Vazio, indicando que a execução desse processo depende desta
condição e deve permanecer aguardando em uma fila de espera asso-
ciada à variável Vazio.

86
01_SisOps.qxp 11/2/2009 11:35 Page 87

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

O processo produtor que inserir o primeiro elemento no buffer


deverá sinalizar esta condição usando o comando SIGNAL na variável
Vazio, então libera o consumidor.

87
01_SisOps.qxp 11/2/2009 11:35 Page 88

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

88
01_SisOps.qxp 11/2/2009 11:35 Page 89

CAPÍTULO 6

Gerenciamento de
Memória Real

6.1 Conceitos Básicos e Funcionalidades

Idealmente os programadores querem uma memória que tenha as


seguintes características:
• Grande;
• Rápida;
• Não volátil;
• Baixo custo.

Infelizmente a tecnologia atual das memórias não comporta todas


essas características de forma integrada.

Assim, a maioria dos computadores utiliza o conceito de


Hierarquia de Memória, conforme se observa na figura 6.1. Esta
hierarquia, geralmente, oferece as seguintes combinações:

• Uma pequena quantidade de memória cache, a qual possui as


seguintes características: é volátil, muito rápida e de alto custo.

• Uma grande memória principal (RAM), que é volátil, e com


tamanhos que podem mudar de centenas de MB (mega bytes) ou
poucos GB (giga bytes), de velocidade e custo médios.

89
01_SisOps.qxp 11/2/2009 11:35 Page 90

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

• Uma memória secundária, a qual é não volátil, portanto,


localiza-se em disco ou fita, e possui tamanho considerável,
geralmente, na margem de vários gigabytes (e pode chegar até
TB - terabytes), velocidade e custo baixos.

Figura 6.1: Hierarquia de memória em sistemas computacionais [Stallings, 2007]

Além da hierarquia de memória, é bom lembrar que


historicamente sempre houve a preocupação por memória. Assim, os
programadores ou usuários de computadores deviam ter os cuidados
para programar de forma eficiente para não usar memória desneces-
sariamente. Ainda hoje com muita mais capacidade de memória e com
preços acessíveis, o assunto de gerenciamento de memória é funda-
mental para qualquer sistema operacional.

O assunto se torna ainda mais relevante quando a máquina está


sendo usada por vários programas (conceito de multiprogramação),
vários usuários (múltiplos usuários), pois o SO deve cuidar de oferecer
acessos e restrições para que todos possam usar a máquina sem

90
01_SisOps.qxp 11/2/2009 11:35 Page 91

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

interferir nas atividades dos outros, oferecendo segurança de acesso e


execução e, sem degradar o desempenho.

Assim, as Funções Básicas relacionadas com o gerenciamento de


memória são [Machado, 2007]:
• Manter o maior número de processos na memória;
• Maximizar o compartilhamento da UCP e demais recursos ;
• Swapping;
• Execução de programas maiores que memória disponível;
• Proteção;
• Compartilhamento.

6.2 Gerenciamento de Memória

Cabe ao Gerenciador de Memória gerenciar a hierarquia de


memória. Este gerenciador deve controlar as partes da memória que
estão sendo usadas e conhecer e gerenciar também aquelas seções da
memória que ainda não estão sendo usadas, de forma a:
• alocar memória aos processos, quando estes precisarem;
• liberar memória quando um processo termina; e
• tratar do problema do swapping (quando a memória se torne
insuficiente).

A realização dessas tarefas cria uma primeira classificação de sis-


temas operacionais. Assim, os Sistemas de Gerenciamento de
Memória, podem ser divididos em 2 classes:
• Sistemas mais simples que não fazem troca de processos e nem
paginação.
• Sistemas que durante a execução levam e trazem processos
entre a memória principal e o disco (conhecido como troca de
processos e paginação)

91
01_SisOps.qxp 11/2/2009 11:35 Page 92

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

6.2.1 Monoprogramação sem trocas de processos ou paginação

No começo da computação, os sistemas existentes funcionavam


com o conceito de Monoprogramação, que significa que um único
programa está sendo executado e para isso deve-se ter seus dados e
instruções presentes na memória principal. Esses sistemas funcionam
sem trocas de processos e não usam o conceito de paginação.

No caso de ter Sistemas Mono-usuários (um único usuário) a


gerência de memória é bem simples, pois toda a memória é alocada à
próxima tarefa, incluindo a área do S.O. Infelizmente, podem
acontecer erros de execução que podem vir a danificar o S.O. Neste
caso, a destruição do S.O. é um pequeno inconveniente, resolvido pelo
re-carregamento do mesmo.

A Figura 6.2 permite visualizar a existência de três (3) simples


esquemas de organização de memória.

No primeiro caso se observa uma memória dividida em dois


grandes setores, um deles dedicado aos programas ou processos do
usuário (espaço de usuário) e o outro aos processos próprios do
sistema operacional. Inicialmente, o SO existia em disco ou em fita e
devia ser carregado para a memória principal ou memória do tipo
RAM.

Na parte (b) da Figura 6.2 se observa uma outra possibilidade que


consiste em ter o sistema operacional armazenado em memória do
tipo ROM. Já a parte (c) apresenta uma proposta hibrida, onde alguns
processos do sistema operacional devem estar em memória RAM,
enquanto alguns programas e respectivas configurações,
especialmente, de dispositivos periféricos (ou melhor conhecidos
como device drivers) devem estar em memórias do tipo ROM,
enquanto os processos do SO devem estar na RAM.

92
01_SisOps.qxp 11/2/2009 11:35 Page 93

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 6.2: Multiprogramação com partições Fixas [Tanenbaum, 2003]

Atualmente os Sistemas Monoprogramados (apresentados


anteriormente) são raramente usados. Ao invés disso, os Sistemas
modernos acompanham o fluxo normal de utilização dos sistemas
computacionais, pois os usuários estão sempre desejando executar
vários programas (Por exemplo, enquanto estão acessando internet e
esperam por alguma conexão ou serviço, abre a calculadora e fazem
algum cálculo, e abre o editor de texto e inicia a escrita de algum
documento, ou abre um acrobat reader e lê algum texto, ou etc.).
Isto é, os modernos sistemas operacionais devem permitir
multiprogramação.

A maneira mais comum de realizar a multiprogramação é simples-


mente dividir a memória em um determinado número de partições
(provalmente de tamanhos diferentes, mas por facilidade de
implementação, no começo, os SO adotaram que essas partições
fossem de tamanho fixo,). Esta divisão pode ser feita de maneira
manual, quando o sistema é inicializado. Ao chegar um job ou uma
tarefa, pode ser colocado em uma fila de entrada associada à menor
partição, grande o suficiente para armazená-lo.

Na Figura 6.3 é possível observar um exemplo de sistema


operacional que leva em consideração o conceito de partições de
memória fixa. Neste caso, existe uma fila separada para cada
partição, e existem partições de diferentes tamanhos predefinidos.
Por exemplo, no lado esquerdo dessa figura se observa que há quatro
partições de tamanhos 100, 200, 300 e 100 Kbytes de memória,
alocados respectivamente para as partições 1, 2, 3 e 4. Se observa
também que há um espaço de memória de 100K reservado para as
funções próprias do sistema operacional. Importante observar também

93
01_SisOps.qxp 11/2/2009 11:35 Page 94

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

que existe a possibilidade de cada partição ter a sua própria fila,


portanto existe o conceito de múltiplas filas de entrada. Isso permite
que cada processo esteja na fila adequada em função do tamanho da
partição que precisar.

O fato de ter várias filas, em função de cada partição, permite


que o sistema possua um melhor desempenho, pois assim cada
processo será atendido mais prontamente, o que produz um ganho de
desempenho fazendo com que o tempo de resposta seja menor. Já do
lado direito da Figura 6.3 se observa o mesmo conceito de partições
fixas, mas neste caso há uma única fila de entrada, facilitando o
controle do gerenciamento das partições, mas gera problemas de
desempenho.

Figura 6.3: Multiprogramação com partições fixas [Tanenbaum, 2003][Sementille, 2006]

6.2.2 Modelagem da Multiprogramação

O uso da Multiprogramação pode melhorar a utilização da UCP


uma vez que em algumas situações a CPU deve ficar parada, sem fazer
nada, esperando por muito tempo algum dado ou informação para dar
continuidade na execução de um determinado processo ou programa.
Neste caso, quando o tempo de parar é muito alto, poderia-ser dar o
processador a outro processo ou programa para que execute
94
01_SisOps.qxp 11/2/2009 11:35 Page 95

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

instruções ou atividades, aproveitando assim a CPU e portanto,


diminuindo o tempo de ociosidade do processador. O que sempre se
procura é que o processador esteja o mais ocupado possível, tomara
sempre fosse 100%.

Assim, a multiprogramação melhora o uso do processador. Mas


para isso é necessário que cada processo ou programa que esteja
usando o processador deverá conter seus dados ou informações
carregadas na memória. Portanto, multiprogramação exige mais
cuidado no gerenciamento de memória.

Para entender melhor esse aproveitamento, considerere a


utilização da UCP de modo probabilístico:
• Suponha que um processo gaste uma fração p de seu tempo
esperando pela finalização de sua solicitação de E/S;
• Com n processos simultâneos na memória, a probabilidade de
todos os n processos estarem esperando por E/S (situação em que
a UCP está ociosa) é pn;
• A utilização da UCP é dada pela expressão: 1 – pn

A Figura 6.4 mostra o impacto da multiprogramação, vista como a


porcentagem de uso do processador (CPU) em função do número de
processos ou programas sendo executados, quando se varia o tempo
de espera de operações de entrada e saída. Nessa figura se observam
3 casos, 20, 50 e 80% de uso de entrada e saída (ou I/O – do inglês
Input e Output).

Grau de Multiprogramação
Figura 6.4: Um exemplo do impacto da multiprogramação [Silberschatz, 2001][Sementille, 2006]

95
01_SisOps.qxp 11/2/2009 11:35 Page 96

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Na figura 6.4 se observa que quando se aumenta o número de


processos se consegue uma melhor utilização da CPU. Esse número
alcança um ponto de saturação, próximo de 100%, em torno de 4 e 5
processos quando o tempo de I/O é inferior a 50%, isto é, não é bom
colocar mais processos para serem executados `ao mesmo tempo`
uma vez que o processador já está no seu valor limite de uso.

Já para porcentagens maiores de 50%, veja o caso de 80%, é


possível usar mais processos em execução e o ponto de saturação
demora mais em ser alcançado. Isso quer dizer que como as atividades
de I/O aumentaram, então haverá mais tempo livre da CPU, a qual
poderá ser usada por mais processos.

Importante lembrar que nesses casos, o gerenciamento de


memória é mais crítico, pois deverá oferecer suporte aos dados e
instruções que cada processo deve usar, e eles deverão estar presentes
na memória quando iniciarem a execução.

A Figura 6.5 apresenta um outro exemplo de uso da CPU como uma


função do número de processos na memória. Ela está dividida em 3
partes. Na primeira parte se observa que há quatro processos (chama-
dos de jobs), sendo executados, e o respectivo tempo em que
chegaram e iniciaram atividades com a CPU, assim como o tempo, em
minutos, de CPU que cada um deles precisa para finalizar a tarefa.

Na parte (b) se observa o uso de cada processo, mostrando a


porcentagem de uso de CPU, a porcentagem em que a CPU está livre,
e finaliza com o tempo real alocado a cada processo (CPU/processo).
Como exemplo, se observa que o processo número 1 ocupa a CPU em
20%, ou em outras palavras, a CPU está livre ou esperando por
operações de I/O em 80% (pois, para cada processo, o tempo livre de
CPU é igual a 1 menos o tempo ocupado).

A parte (c) da figura oferece uma melhor visualização da execução


dos processos conforme o tempo avança, tomando como base o tempo
de chegada do processo 1. Nele se observa que no tempo 10 o
processo 1 já tem usado a CPU durante 2 minutos. No instante 10:10
chega o processo 2, e a CPU é dada para esse novo processo. No
intervalo de tempo de 10:10 às 10:15, tanto o processo 1 quanto o 2
usam a CPU de forma uniforme, cada um deles 0.9 minutos. Assim, no
96
01_SisOps.qxp 11/2/2009 11:35 Page 97

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

instante 10:15b quando chega o processo 3, o processo 1 já executou


2.9 minutos dos 4 que precisa, e o processo 2 tem 0.9 dos 3
necessários. Nesse momento o processo assume o controle da CPU e
assim sucessivamente até finalizar a execução de todos os processos.
Nessa figura se observa que o processo 1 finaliza no instante 10:22,
enquanto o 2 em 10:282, o 3 em 10:276 (antes do processo 2 que
chegou antes dele) e o 4 em 10:317.

Veja que a CPU fica sendo usada por todos os processos, é isso
implica que os dados que precisa devem estar na memória, e é isso
que o gerenciamento de memória deve fazer. Essa é uma das tarefas
mais delicadas e complexas executadas pelo sistema operacional.

Esse fenômeno, de usar a CPU por vários programas chamasse


multiprogramação. A CPU nunca é usada por um único programa até
finalizar. Assim, a CPU fica chaveando os programas ou processos. Isso
se chama de chaveamento de processos. Em cada um desses instantes,
o sistema operacional deve guardar os estados e as informações do
processo que estava executando (pois não pode perder informação
nenhuma), e carrega o novo espaço de memória que será usado pelo
novo processo. Essas operações de guardar os dados e carregar os
novos demanda certo tempo, o qual gera uma sobrecarga de
processamento (pois deve ser feita pela própria CPU – tempo da CPU
dedicado a operações do próprio sistema operacional). Esse tempo
deve ser o menos possível de modo a não gerar prejuízos de
desempenho.

Um outro ponto importante de destacar é que na parte (b) da


Figura 6.5 se observa que na medida em que os processos vão
chegando, precisam mais da CPU, o que diminui o tempo livre de CPU,
o que se valida com o tempo maior que a CPU fica ocupada e a
diminuição de CPU por cada processo linha 3 da tabela).

97
01_SisOps.qxp 11/2/2009 11:35 Page 98

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 6.5: Análise do desempenho de um sistema multiprocessado com 4 processos


[Sementille, 2006]

6.3 Relocação e Proteção de Partições

Quando se executa ou se deseja executar um programa, ele


deverá estar na memória principal. Neste caso, pode não se ter
certeza de onde o programa será carregado na memória. Isto
acontece, pois as localizações de endereços de localização das
variáveis e do código das rotinas não podem ser absolutas. Isso obriga
a manter um programa fora das partições de outros processos.

Portanto, há a necessidade de uso de valores de base e limite, os


quais possuem as seguintes características:
• Os endereços das localizações são somados a um valor de base
para mapear um endereço físico;
• Valores de localizações maiores que um valor limite é
considerado um erro.

98
01_SisOps.qxp 11/2/2009 11:35 Page 99

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A Figura 6.6 mostra que cada partição deve ser alocada e


protegida. No caso mostrado nessa figura isso se faz usando dois
registradores que permitem definir o endereço inicial e final de cada
partição. No caso da partição com alocação simples contígua só se
precisa de dois registradores. Mas tendo-se mais partições, cada uma
delas deve ter seu par de registradores especiais para guardar e
definir cada partição. Assim, cada processo ou programa poderá usar
uma ou várias partições sem problemas, pois existe a delimitação de
espaço que pode ser usados por ele. No caso de exceder do limite
permitido para seu uso, então estará entrando no espaço de outra
partição, e neste caso, o sistema operacional acusa erro de violação
de espaço de endereçamento.

Figura 6.6: Proteção das partições [Machado, 2007][Pinto, 2008]

99
01_SisOps.qxp 11/2/2009 11:35 Page 100

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Troca de Processos

Com um sistema em lote, é simples e eficiente organizar a


memória em partições fixas. Já em sistemas de tempo compartilhado,
como aquele mostrado na Figura 6.5 no qual há vários processos sendo
executados, deve-se levar em consideração os seguintes aspectos:
• Pode não existir memória suficiente para conter todos os
processos ativos.
• Os processos excedentes são mantidos em disco e trazidos
dinamicamente para a memória a fim de serem executados.

Nestes dois problemas, existem 2 procedimentos gerais que


podem ser usados:
• A troca de processos (swapping): forma mais simples, e consiste
em trazer totalmente cada processo para a memória, executá-lo
durante um tempo e, então, devolvê-lo ao disco.
• Memória Virtual: permite que os programas possam ser
executados mesmo que estejam parcialmente carregados na
memória principal.

Na Figura 6.7 se observa que a alocação de memória muda à


medida que os processos chegam e deixam a memória. Na Figura 6.7
se observam 7 situações. Em todos os casos, se visualiza o espaço
definido para as atividades do sistema operacional e para os processos
que vão chegando. Na primeira, parte (a) existe somente espaço
alocado para o processo A. As regiões sombreadas representam o
espaço de memória não usada. È possível observar que a região
sombreada vá diminuindo de tamanho conforme chegam mais
processos. Observa-se também que a alocação de espaço não se dá de
forma contígua e uniforme pois cada processo requer determinado
espaço e o sistema operacional entrega uma partição de tamanho
adequado para ele. Quando o processo não usa mais a CPU, o espaço
alocado deve deixar a memória, veja o exemplo da figura (d), que
somente possui os processos B e C e o processo A deixou a memória, e
esse espaço fica disponível, motivo pelo qual fica novamente
sombreado. Quando outro processo, neste caso o D, entra para
execução, ele é carregado em lugar que tenha o espaço adequado ao
tamanho exigido por ele (caso do processo D – parte (e). Na situação
seguinte, parte (f), o processo B finaliza o sai de execução, e deixa
novamente memória disponível (região sombreada).
100
01_SisOps.qxp 11/2/2009 11:35 Page 101

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Interessante observar a situação seguinte, na qual o processo A


ganha de novo o uso do processador e deve então possuir seus dados
em memória. Neste caso, o sistema operacional aloca novamente
espaço, e o coloca onde houver espaço disponível. Neste caso, o
processo A fica em outra região de memória, distinta daquela que
ocupava inicialmente, pois foi esse o espaço que o sistema operacional
encontrou para fazer a nova locação.

Figura 6.7: Visualização do uso de memória conforme o tempo e número de processos


[Deitel, 2005]

Na Figura 6.7 se observa que as regiões sombreadas mudam a cada


momento, é isso gera um problema conhecido como fragmentação
interna. Neste caso, não há espaço disponível de forma contígua. Isso
pode gerar problemas de desempenho pois afeta a locação eficiente
de processos em memória.

Uma forma de evitar essa situação é mostrada na Figura 6.8, na


qual se tem dois processos. Inicialmente o processo A possui um
espaço reservado para aquilo que efetivamente precisa, mas se deixa
um espaço reservado caso necessite expansão. Existe também o
processo B, na mesma situação, um espaço para aquilo que precisa
num instante e um espaço reservado caso necessite expansão. Entre
os dois processos há um espaço sombreado, sem uso.

A parte (b) mostra uma outra solução, a qual aloca espaço tanto
para o processo A quanto para o processo B. Mas neste caso, se
observa que há áreas dedicadas para certas atividades do processo.
Por exemplo, o processo A possui um espaço dedicado para atividades
do próprio programa (A-programa), outro espaço para dado (A-data) e
101
01_SisOps.qxp 11/2/2009 11:35 Page 102

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

outro para o uso da pilha (A-stack), e um espaço não usado, porém


reservado e disponível, para o caso em que o processo A necessite ser
expandido, somente para uso de pilha ou de dados. Similar acontece
com o processo B. Esta situação é melhor, pois aloca espaço para cada
processo o qual possui regiões dedicadas conforme o uso. Isso facilita
o compartilhamento de dados e faz com que o processo de compilação
seja mais eficiente, pois caso o programa mude somente um trecho
dele, então, somente a parte que mudou deverá ser recompilada (seja
a parte do programa, dos dados, ou da pilha) para a correta alocação
de memória, e a parte que não mudou fica intacta, tanto na sua fun-
cionalidade como uso do espaço de memória a ela alocada, o que faz
com que compilação seja mais eficiente.

Assim, a Figura 6.8 mostra as duas situações: (a) Alocação de


espaço para uma área de dados em expansão e, (b) Alocação de
espaço para uma pilha e uma área de dados, ambos em expansão.

Figura 6.8: Uso da Memória nos Programas A e B [Tanenbaum, 2003][Sementille, 2006]

102
01_SisOps.qxp 11/2/2009 11:35 Page 103

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

6.4 Gerenciamento de Memória com Mapas de Bits

Quando a memória é alocada dinamicamente, o sistema opera-


cional deve gerenciar esta situação. Basicamente, existem duas for-
mas de fazer isto:
• Técnica do Mapa de Bits (Bitmap)
• Técnica de Lista de Disponíveis

Na técnica de Mapa de Bits (Bitmap), a memória é dividida em


unidades de alocação (com tamanhos que podem variar de poucas
palavras a vários KB - Kilobytes).

A cada unidade de alocação é associado um bit no mapa de bits,


o qual vale 0 (se a unidade está disponível) e 1 (se estiver ocupada).

Na Figura 6.9 se observa um exemplo, com as seguintes


particularidades:

(a) Uma parte da memória com 5 processos (A, B, C, D e E), e há


3 regiões disponíveis (localizadas entre os espaços dos processos A
e B, C e D e, após o processo E.
• As regiões em branco, desocupadas, isto é, 1 no bitmap,
marcam as unidades já alocadas, e,
• As regiões disponíveis ou sombreadas, estão com valor 0 no
bitmap, pois marcam as unidades desocupadas.

(b) Aparece o Bitmap correspondente.


(c) A mesma informação aparece como uma lista encadeada.

103
01_SisOps.qxp 11/2/2009 11:35 Page 104

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 6.9: Gerenciamento de memória com Mapas de Bits e Listas Encadeadas


[Tanenbaum, 2003][Sementille, 2006]

Outra maneira de gerenciar a memória é manter uma lista


encadeada, neste caso, segmentos de memória são alocados e se
indica quais os segmentos que estão disponíveis. Nesta técnica, cada
elemento desta lista possui três campos, os quais são específicos para
indicar as seguintes três funções (ver Figura 6.9):

• O primeiro campo indica se o segmento de memória está


disponível, sendo indicado pela letra H (do inglês Hole, que
indica buraco ou região sombreada), ou alocado a um processo,
neste caso indicado pela letra P – de processo, e deve-se colocar
o nome daquele processo.
• O segundo campo indica o endereço onde se inicia este
segmento.
• O terceiro e último campo é um ponteiro que aponta para o
próximo elemento da lista encadeada.

Como exemplo desta lista, na parte (c) da Figura 6.9 se observa o


seguinte padrão: P indica qual o processo, e depois o espaço que
ocupa. No exemplo, o primeiro item da lista indica P, que seria para o
processo A, e está ocupado no espaço indicado pelos bits 0 até 5. Após
aparece uma região sombreada ou disponível, valor 0, no espaço dos
bits que começam no bit 5 e são 3 buracos, o próximo campo é um
ponteiro que aponta para o próximo elemento, que neste caso
corresponde ao processo que inicia no bit 8 e vá 6 posições, isto é, até
o bit 14, depois se aponta para o próximo que é um processo e assim
sucessivamente.

104
01_SisOps.qxp 11/2/2009 11:35 Page 105

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Na Figura 6.10 aparece um exemplo com quatro combinações.


Existem três processos, A, B e X. A parte da esquerda mostra o
fenômeno da alocação de memória antes dos processos finalizarem, e
a parte (b) a memória quando os processos finalizam. Observa-se que
inicialmente os três processos estão sendo executados e estão na
memória na ordem indicada A X B. Suponha que o processo X finaliza
então a memória fica conforme se observa no lado direito (ver região
sombreada, disponível, entre os processos A e B).

Na situação (b) se supõe que somente estão os processos A e X


(lado esquerdo) e suponha que o processo X finaliza então a memória
fica conforme se indica no lado direito, e assim por diante.

Figura 6.10: Combinações para uso de memória antes e depois de finalizar processos [Deitel,
2005][Sementille, 2006]

105
01_SisOps.qxp 11/2/2009 11:35 Page 106

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

6.5 Alocação de Segmentos Livres

Existem três métodos que podem ser usados para selecionar uma
região para um processo. Para isso é necessário que existam
algoritmos que permitam fazer essa alocação. Os algoritmos mais
conhecidos e usados são:
Melhor escolha (Best fit): colocar o processo no bloco com o
mínimo resto de memória;
Pior escolha (worst fit): usar o bloco com o maior resto de
memória;
Primeira escolha (First fit): ir sequencialmente através dos
blocos, e tomar o primeiro bloco que seja grande e suficiente para
alocar espaço para esse processo.

Na Figura 6.11 se observa o funcionamento e o impacto na


utilização da memória em cada um desses algoritmos. É possível
observar as três principais consequências:
• O algoritmo de melhor escolha deixa o menor resto, porém
após um longo processamento poderá deixar “buracos” muito
pequenos para serem úteis.
• A pior escolha: deixa o maior espaço após cada alocação, mas
tende a espalhar as porções não utilizadas sobre áreas não
contínuas de memória e, portanto, pode tornar difícil alocar
grandes jobs.
• A primeira escolha: tende a ser um meio termo entre o
algritmo da melhor e a pior escolha, com a característica
adicional de fazer com que os espaços vazios migrem para o final
da memória.

106
01_SisOps.qxp 11/2/2009 11:35 Page 107

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

a) Início b) Melhor c) Pior d) Primeira


Figura 6.11: Alocação de segmentos livres [Deitel, 2005]

107
01_SisOps.qxp 11/2/2009 11:35 Page 108

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

108
01_SisOps.qxp 11/2/2009 11:35 Page 109

CAPÍTULO 7

Gerenciamento de
Memória Virtual

Este capítulo apresenta os conceitos básicos relacionados com a


importante técnica para se ter gerenciamento de memória,
conhecida como gerenciamento de memória virtual (MV). Ele está
dividido em dez seções, a saber: a seção 1 apresenta um pouco do
histórico até se chegar no problema do gerenciamento de memória.
As seções 2 e 3 destacam os conceitos relacionados com paginação e
segmentação. As outras seções apresentam conceitos relacionados
com implementação, finalizando com exemplos de gerência de
memória no Windows e no Linux.

7.1 Princípios de Memória Virtual

No começo da computação, o programador dividia o programa em


certo número de porções, denominadas de sobreposições (overlays).
Esse conceito nasceu no tempo em que os computadores possuíam
pouca memória, e não comportavam programas grandes. A idéia
principal consistia em dividir o programa em partes (módulos), de
modo que cada um caiba na memória. Assim, cada overlay devia caber
na memória.

109
01_SisOps.qxp 11/2/2009 11:35 Page 110

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Para executar o programa, a primeira sobreposição tinha que ser


trazida para memória e a máquina executava durante certo tempo.
Quando terminava, lia a próxima sobreposição e a chamava, e assim
por diante.
O programador era responsável por fragmentar o programa em
sobreposições, decidir em que lugar da memória secundária cada
sobreposição seria mantida, resolver o transporte da sobreposição
entre a memória principal e memória secundária, em geral, gerenciar
todo o processo de sobreposição sem auxilio do computador.
A Figura 7.1 exemplifica bem como era este processo, de inteira
responsabilidade do programador.

Figura 7.1: Utilização de Overlays (zonas de sobreposição) nos Programas [Sementille, 2008]

Um grupo de pesquisadores em Manchester - Inglaterra, em 1968,


propuseram um método para executar o processo de sobreposição de
forma automática, sem que o programador soubesse o que estava
acontecendo. Este método, hoje é conhecido como memória virtual.

Hoje, até computadores de um único chip, incluindo o Pentium 4


e UltraSparc, têm sistemas de memória virtual de alta sofisticação.

Com o objetivo de automatizar o mecanismo de overlay, um grupo


de pesquisa em Manchester (1961), criou um método, hoje conhecido
e chamado de Memória Virtual [Fotheringham, 1961].

110
01_SisOps.qxp 11/2/2009 11:35 Page 111

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

7.2 Conceitos de Paginação

A idéia principal da paginação é separar os conceitos de espaço de


endereçamento e posições de memória.

Considere o seguinte exemplo. Suponha que um usuário possui um


computador com um campo de endereço de 16 bits e uma memória
principal de 4096 bytes (4K).

Qualquer programa neste computador pode, então, gerar


endereços que variam de 0 à 64 kbytes (pois esse número é obtido com
todas as combinações de endereços alcancavéis com 16 bits = 216),
apesar das posições de endereços acima de 4096 não existirem
fisicamente.

O hardware forçava uma correspondência de um para um entre


espaços de endereçamento e endereços reais.

Na figura 7.2 se observa que no caso exemplo citado


anteriormente, há duas possibilidades de ter os endereços:

(a) endereçamento possível (aquele que um programa poderia ter,


pois o barramento de endereço é composto por 16 bits = 216 = 65536
posições = 64 Kbytes)

(b) Endereçamento real (aquele que realmente existe na máquina


real, uma memória de 4K = 4096 bytes, neste caso, se precisaria de
somente 12 bits para o endereço).

Parte (a) - Endereçamento possível:

Figura 7.2a: Endereçamento real:

111
01_SisOps.qxp 11/2/2009 11:35 Page 112

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Parte (b) - Endereçamento Real

Figura 7.2b: Endereçamento Possível e Real

A idéia de separar o espaço de endereçamento (os possíveis


endereços) e os endereços de memória (física) é a seguinte: em
qualquer instante, somente 4096 bytes podem ser acessados, mas não
precisam corresponder aos endereços 0 à 4096, conforme se observa
na Figura 7.3.

Figura 7.3: Exemplo de Endereçamento para Espaços de 4K [Tanenbaum, 2007]

Observando a Figura 7.3, podemos ter a seguinte situação: O que


acontece se um programa salta para um endereço entre 8192 e 12287
(seria a terceira região no espaco de memória indicado no lado
esquerdo da figura?

Neste caso, aconteceriam os seguintes cinco passos:


1. O conteúdo da memória principal seria salvo na memória
secundária (disco);
2. As posições entre 8192 e 12287 seriam localizadas na memória
secundária;

112
01_SisOps.qxp 11/2/2009 11:35 Page 113

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

3. Esses endereços de memória devem ser trazidos para a


memória principal;
4. O mapa de endereços seria trocado para mapear os endereços
de 8192 a 12287, que se mantém nas mesmas posições indicadas
de 0 a 4095;
5. A execução continuaria como se nada tivesse acontecido, do
ponto de vista do usuário.

Essa técnica de sobreposição automática é denominada de


paginação, e os trechos de programa lidos do disco são denominados
de páginas. Assim, a paginação dá ao programador a ilusão de uma
memória principal grande, linear e contínua, do mesmo tamanho do
espaço de endereçamento, quando, de fato, a memória principal
disponível pode ser menor que o espaço de endereçamento.

A simulação desta memória ampla não pode ser detectada por


programa (exceto pela execução de testes de temporização) e é um
mecanismo transparente ao usuário, pois o programador pode
programar como se a paginação não existisse.

Para um melhor entendimento dos conceitos de memoria virtual,


se faz necessário ter os seguintes termos, os quais são importantes:
Espaço de endereçamento virtual: são os endereços que o pro-
grama pode referenciar.
Espaço de endereçamento físico: são os endereços reais de
memória.
Mapa de memória ou Tabela de Páginas: relaciona cada endereço
físico ao correspondente endereço virtual.

Nos computadores modernos, há um módulo físico (real) em


hardware que está presente na UCP que é responsável pela conversão
do endereço virtual em endereço físico. Esse módulo é conhecido
como MMU (Management Memory Unit) – Unidade de Gerenciamento
de Memória.

113
01_SisOps.qxp 11/2/2009 11:35 Page 114

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A Figura 7.4 mostra como seria esse módulo.

Figura 7.4: Posição e função da MMU [Tanenbaum, 2007][Stallings, 2007]

7.2.1 Implementação da Paginação

Inicialmente supomos que existe uma memória secundária (disco)


suficiente para manter um programa completo e seus dados.

A cópia de um programa na memória secundária pode ser


considerado o original. Enquanto isso, as partes trazidas à memória
principal, de vez em quando, podem ser consideradas cópias.
Portanto, quando modificações são feitas na cópia da memória
principal, elas devem ser refletidas na versão original, isto é, aquela
que existe no disco.

Características da Implementação

O espaço de endereçamento virtual é dividido em páginas de


tamanhos iguais (geralmente, os tamanhos mais usados variam de 512
a 32K endereços por página).

114
01_SisOps.qxp 11/2/2009 11:35 Page 115

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

O espaço de endereçamento físico tem tamanho de página


idêntico ao do endereçamento virtual (estas páginas são chamadas
páginas físicas, ou molduras de páginas – page frames).

A Figura 7.5 mostra um exemplo de uma implementação, na qual


a memória física é de 32K (32767 endereços) e a memória em disco
possui 64K (65536 endereços). Se observa que o tamanho de página
usada é 4K (4096 posições de memória). Dessa forma, o disco possui
16 (numeradas de 0 a 15) páginas, enquanto a memória real (física ou
principal) tem 8 páginas (na figura aparecem com numeração de 0 a
7)

Figura 7.5: Exemplo de uma implementação de memória virtual [Sementille, 2008]

115
01_SisOps.qxp 11/2/2009 11:35 Page 116

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A relação entre endereços virtuais e endereços físicos é dada pela


tabela de páginas, conforme se observa na Figura 7.6.

Figura 7.6: Exemplo de Tabelas de Páginas para o exemplo da figura 7.5 [Sementille, 2006]

Na Figura 7.7 se mostra um exemplo de como é feito um acesso


ao endereço de memória indicado pelo endereço
8196 = 0010 - 000000000100 (16 bits). Inicialmente se pegam os 4
primeiro bits (24 = 16, para identificar em qual página esse dado se
encontra e o endereço restantes dado pelos 12 bits permitem sabem
qual o endereço real dentro dessa página de tamanho
4K = 4096 = 212), que neste caso é 0010 (que corresponde ao número
decimal 2), permitindo identificar em qual das páginas aquele dado se
encontra, e percebe-se que esse endereço se encontra na página 2.
Neste caso, os 3 primeiros bits na tabela de página (valor 110 são
colocados no endereço de saída), e logo depois se verifica o bit de
presença válida ou não para saber se a página está ou não
desatualizada com relação à página de disco. Neste caso, aparece o
bit =1, para indicar que está com uma cópia válida. Assim, se forma o
novo endereço, formado então pelo valor 110 - 000000000100
(15 bits), que corresponde ao endereço 24580. Interessante destacar
que essas operações são feitas de forma automática pelo MMU.

116
01_SisOps.qxp 11/2/2009 11:35 Page 117

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 7.7: Operação interna da MMU com 16 páginas de 4KB

A Figura 7.8 mostra um outro exemplo. Neste caso, o endereço


virtual é composto por 16 bits, enquanto que o endereço físico é de
15 bits. Assim, os 4 primeiros bits da virtual permitem definir em qual
das páginas esse endereço deve ser mapeado.No caso do exemplo,
eles são 0011 = 3, isto é o mapeamento é para a página 3.
Imediatamente depois verifica-se o bit de validade, que neste caso é
igual a ‘1’, o que significa que ele está presente na memória
principal.

Imediatamente se pega a informação que estão no campo ‘número


da moldura’, para fazer o correto mapeamento para memória física.
Neste caso, o valor nesse campo é ‘111’. Esse número somente será
valido se o Bit de validade estiver ‘1’, isto é, se for presente ou
válido. Portanto, o endereço físico correspondente será
111 – 000000010110 (15 bits).

117
01_SisOps.qxp 11/2/2009 11:35 Page 118

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 7.8: Exemplo de uma entrada típica da tabela de páginas

Todo esse processo pode também ser analisado colocando todas as


informações relevantes ao processo de transformação de endereços
em uma única linha, composta de vários campos. Na Figura 7.9 se
observa que há uma estrutura com vários campos, e em função da
informação contida em cada um deles, se realiza então o processo de
mapeamento para cada endereço de entrada. Então, para um melhor
entendimento deve-se ter conhecimento e função dos seguintes
campos:
• Número da moldura de página: número da página física onde a
página virtual (PV) está carregada;
• Bit presente/ausente: se a PV está (bit 1) ou não está (bit 0)
presente na memória principal;
• Proteção: tipos de acesso permitidos, por exemplo, leitura,
escrita ou execução;
• Modificado: serve para indicar se a PV foi ou não modificada na
memória, isto é, se a página na memória virtual (disco) é
consistente com aquela cópia que esta na memória principal;
• Referenciada: se a PV foi referenciada (bit 1) ou não (bit 0),
para leitura/escrita enquanto estava na memória;
118
01_SisOps.qxp 11/2/2009 11:35 Page 119

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

• Bit de cache desabilitado: desabilita o cache para a página em


questão.

Figura 7.9: Campos de uma Estrutura que defina o mapeamento

7.2.2 Tabelas de Páginas Multiníveis

Conforme a capacidade de memória aumenta, o processo de


mapeamento se torna mais complexo. O funcionamento é igual,
porém, localizar a moldura de página se torna um problema
computacional de maior complexidade, exigindo mais tempo de
processamento e, portanto, mais tempo para fazer o processo de
busca. Além disso, o espaço de memória ocupado pela tabela de
páginas também cresce e deve-se então, estudar técnicas para
otimizar essa memória e o tempo de busca.

Muitos computadores dividem a tabela de páginas em múltiplos


níveis, para minimizar o espaço de memória necessário para seu
armazenamento. O segredo para o método de múltiplos níveis de
tabelas de páginas é evitar que todas elas sejam mantidas na memória
ao mesmo tempo.

A Figura 7.10 mostra um exemplo de como fazer o mapeamento,


no caso de se ter um endereço virtual de 32 bits. Neste caso se
observa que é possível ter dois campos separados indicando duas
possíveis tabelas de páginas, indicadas como Pt1 e Pt2, cada uma
delas com 10 bits de cumprimento (isto é, pode mapear até 210 = 1024
páginas). Após localizar qual das tabelas de páginas é interesse para
um endereço se produz um deslocamento indicado pelo último campo
dessa estrutura que possui 12 bits (212 = 4096 Mbytes).

119
01_SisOps.qxp 11/2/2009 11:35 Page 120

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 7.10: Exemplo de Campos na Tabela de Páginas Multinível

A Figura 7.11 permite visualizar o efeito desse múltiplo nível no


acesso a uma memória. Veja que do lado esquerdo aparece a
estrutura da Figura 7.10. O campo PT1 indica qual a página que
mapeia esse endereço na tabela de páginas do primeiro nível, após
isso, nesta tabela se encontra a nova posição indicada no PT2 que
envia a busca para o segundo nível da tabela de páginas. Neste ponto,
se chega à página que efetivamente contém aquele endereço, e para
finalizar se usa o campo de deslocamento para identificar a correta
posição dentro de cada estrutura de tamanho 4M.

120
01_SisOps.qxp 11/2/2009 11:35 Page 121

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 7.11: Estrutura de Tabela de Página de 2 Níveis

7.2.3 Tabelas de Páginas Invertidas

Considerando os avanços em processadores, no momento existem


os computadores de 64 bits, e neste caso, a tabela de páginas é então,
muito grande, tendo como base os modelos tradicionais.

Suponha o seguinte exemplo: se o computador tem 64 bits de


endereço virtual então seu endereçamento virtual é 264 bytes (que é
um número muito grande). Caso se adote páginas de 4096 bytes
(4K = 212), teremos então uma tabela com 252 entradas
(pois 64 – 12 = 52). Se cada entrada tiver 8 bytes, então teremos uma
tabela de 30.000.000 gigabytes de tamanho. Isso é um número muito
grande, e não haveria como termos uma implementação física.

121
01_SisOps.qxp 11/2/2009 11:35 Page 122

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Uma solução é usar o conceito de tabela de páginas invertidas.


Neste caso, tem-se uma entrada por moldura de página na memória
real. Cada entrada informa que o par (processo, página virtual) está
localizado na moldura de página.

Como exemplo, suponha que temos computadores de 64 bits com


páginas de 4KB e 256 MB de RAM, a tabela de páginas terá neste caso
65356 bytes (pois 256 MB/4KB = 64Kbytes).

Como se observa, nada é de graça. Neste caso, a economia de


espaço tem um preço, que é a dificuldade na conversão do endereço
virtual em físico. Se o processo n referência a página virtual p, p não
pode ser usado como índice na tabela. Ao invés disso, o hardware deve
pesquisar toda a tabela de páginas invertidas à procura do par (n, p).

Este procedimento deve ser feito à cada referência à memória.


Para acelerar este processo pode-se manter as páginas mais usadas na
TLB e manter uma tabela hash dos endereços virtuais, conforme se
observa na Figura 7.12.

Figura 7.12: Comparação de uma tabela de páginas tradicional com uma tabela
de páginas invertidas

122
01_SisOps.qxp 11/2/2009 11:35 Page 123

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

7.3 TLB – Tabela de Tradução de Endereços

Usando como base esse exemplo percebe-se as seguintes


considerações importantes: Se o S.O. fizesse a conversão de
endereços, a paginação seria inviável. Então, para acelerar esse
processo de conversão de endereços, uma parte da tabela de páginas
é mantida na UCP em registradores associativos, ou melhor,
conhecidos como TLBs (Tabela de Tradução de Endereços – do inglês
Translation Lookaside Buffers). Portanto, o uso de TLB permite
acelerar os mecanismos de paginação, melhorando então o
desempenho do sistema computacional (ver exemplos do
mapeamento na Tabela 7.1). Por esse motivo, a maioria dos
computadores modernos usam esses TLBs, veja por exemplo os
processadores da Intel (ver Figura 7.13). Nessa figura se observa que
há uma TLB especial para instruções e outra para dados, cada uma
delas próximas das unidades de cachê de instruções e cachê de dados,
respectivamente.

Tabela 7.1: TLBs – Translation Lookaside Buffers [Sementille, 2006]

123
01_SisOps.qxp 11/2/2009 11:35 Page 124

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 7.13: Uso de TLB em Processadores Intel

7.4 Paginação por Demanda e o Modelo do Conjunto de Trabalho

Toda vez que se faz referência a um endereço de uma página que


não está na memória principal se produz então uma falta de página
(page fault). Após a falta de página, o S.O. deve realizar as seguintes
operações:
• Lê a página requerida da memória secundária (disco);
• Coloca sua nova posição de memória física, na tabela de pági-
nas;
• Repete e inicia a execução da instrução que originou a falta de
página.

Dessa maneira, é possível iniciar a execução de um programa,


mesmo que nenhuma página dele esteja na memória principal. Neste
caso, a tabela de páginas deve indicar que todas as páginas estão na
memória secundária (disco). Isto é o que se conhece como paginação
por demanda. A Figura 7.14 mostra como o processo é realizado.

124
01_SisOps.qxp 11/2/2009 11:35 Page 125

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 7.14: Passos na Paginação por Demanda

Então, na paginação por demanda, as páginas são trazidas para a


memória somente quando ocorre uma requisição de uma página, e não
antecipadamente.

Importante lembrar que a questão da demanda só é relevante na


inicialização do sistema. É bom lembrar também que em sistemas
multiprogramados este problema é ainda mais crítico, devido à
comutação constante de processos.

Também é importante lembrar e ter em mente que o mapa de


memória é exclusivo de cada programa.

Grande parte dos programas não referencia seu espaço de


endereço uniformemente, mas as referencias tendem a se aglomerar
em um número pequeno de páginas. Esse comportamento foi
observado pelo professor Denning (1968) e é conhecido como
princípio da localidade.

Assim, surge uma abordagem alternativa que é baseada na


característica da “localidade de referência” e permite, então, a
antecipação das páginas mais usadas. Para isso, se utiliza o conceito
de conjunto de trabalho.

Conjunto de trabalho (WS – do inglês, Working Set), refere-se ao


fato de que no instante ‘t’ existe um conjunto que consiste de todas
as páginas usadas nas K referências mais recentes à memória.

Assim, o WS é o conjunto de páginas que o programa usa muito e


ativamente. Ele varia lentamente com o tempo, e é ideal mantê-las
na memória, para evitar a falta de páginas.
125
01_SisOps.qxp 11/2/2009 11:35 Page 126

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Daí que se realize antecipação das páginas baseada na última


execução. Isso traz como vantagem a economia de tempo, mas possui
a desvantagem que se o conjunto de trabalho não estiver estabilizado
haverá perda do tempo de carregamento. O sistema operacional (SO),
deve observar esse comportamento e descobrir esse conjunto
dinamicamente.

A Figura 7.15 mostra um exemplo do conjunto de trabalho de uma


aplicação. Se observa que em determinado tempo ‘t’, o conjunto de
trabalho quase que usa o mesmo número de páginas (veja o ponto de
saturação da curva).

Se um programa tiver um pequeno WS e couber na memória, e


como o WS muda lentamente, então, ainda que use uma grande
quantidade de espaço de endereço virtual, gerará poucos problemas.

Figura 7.15: Conjunto de Trabalho de uma Aplicação

126
01_SisOps.qxp 11/2/2009 11:35 Page 127

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

7.5 Política de Substituição de Páginas

Um ponto importante que devemos manter em mente é que a


memória principal é limitada, daí a necessidade de termos
substituição de páginas, para poder dar espaço a outras páginas que
venham do disco. Isso leva à seguinte questão, qual das páginas que
esta na memória deve ir para disco, liberando espaço para a nova
página que esta chegando.

A primeira opção que existe é pensar que essa escolha seja feita
de forma aleatória. Isso traz o primeiro algoritmo, conhecido como
algoritmo aleatório ou substituição randômica (random algorithm).
Esta escolha não é muito satisfatória. Portanto, existem alguns
sistemas que tentam fazer predição de quais são as páginas menos
úteis e essas são alvo para serem substituídas.

Algoritmo de Substituição de Página ótimo. É o melhor dos


algoritmos, é fácil de descrever, mas impossível de implementar.

No momento da falta de páginas existe um conjunto de páginas na


memória. Uma delas será referenciada na próxima instrução (página
que contém a instrução que gerou a falta de página). As outras
somente serão referenciadas mais tarde. Assim, cada página pode ser
rotulada com o número de instruções que serão executadas antes de
aquela página seja referenciada pela primeira vez. Então, a idéia do
algoritmo consiste em remover a página com o maior rótulo.

Algoritmo NUR (Não Usada Recentemente)

Substituição da página usada há mais tempo. Na tabela de


páginas cada entrada contém os bits M (modificada) e R
(referenciada). O Bit R é colocado em 1 sempre que a página é lida ou
escrita, enquanto que o Bit M é colocado em 1 sempre que se escreve
na página. Esses bits são atualizados a cada referência a memória.
Portanto, periodicamente o bit R é limpo (a cada tique do
relógio), para diferenciar as páginas que foram referenciadas
recentemente, daquelas que não foram.

127
01_SisOps.qxp 11/2/2009 11:35 Page 128

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Considerando que existem dois bits de controle (M e R), então,


toda vez que acontece uma falta de páginas, o S.O. inspeciona todas
as páginas e as separa em quatro categorias:
• Classe 0: não referenciada, não modificada (R=0 & M = 0)
• Classe 1: não referenciada, modificada (R=0 & M = 1)
• Classe 2: referenciada, não modificada (R=1 & M = 0)
• Classe 3: referenciada, modificada (R=1 & M = 1)

O algoritmo NUR remove aleatoriamente uma página de ordem


mais baixa que não esteja vazia.

Algoritmo LRU

Do inglês Least Recently Used (menos recentemente usado):


Funciona bem na maioria dos casos, porém existem algumas falhas.
Veja o seguinte exemplo de falha do algoritmo (Figura 7.16): suponha
que existe um laço (loop) com 5 páginas, porém a memória principal
só comporta 4 páginas. Nesse caso se observa que a página 0 foi
escolhida para sair da memória e entrou a página 4, porém no seguinte
acesso a página que foi novamente referenciada foi a página 0, mas
ela não estava mais na memória. Isso origina muito tráfego
desnecessário.

Figura 7.16: Exemplo de Falha no Algoritmo LRU [Sementille, 2006]

128
01_SisOps.qxp 11/2/2009 11:35 Page 129

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Algoritmo FIFO (First In - First Out)

Este algoritmo faz a substituição da página carregada há mais


tempo, isto é, aquela que entrou primeiro. Daí o nome, primeiro a
entrar, então primeiro a sair, ou melhor conhecido como FIFO (do
inglês - First In - First Out).

Este algoritmo é de fácil Implementação. A cada página virtual é


associado um contador (na tabela de páginas), que é incrementado
cada vez que a página permanece na memória. A página com o maior
valor no contador é escolhida para substituição.

Algoritmo da Segunda Chance

Este algoritmo consiste em uma pequena mudança no algoritmo


FIFO, para evitar que páginas mais usadas sejam descartadas:
observa-se o bit que mantém se a página é ou não é referenciada (na
tabela de páginas). A página escolhida deve ter seu bit de referencia-
da igual a zero. Substituir somente se mudou, é necessário marcar a
página como limpa (não mudou) ou como suja (mudou), para isso se
usa um bit de controle, conhecido como bit de dirty.

Um programa que gera falta de páginas freqüente e


continuamente provoca um fenomeno conhecido como “trashing”,
que origina uma paginação excessiva, e é uma característica
indesejável. Isto acontece quando o número de páginas físicas é
inferior ao tamanho do conjunto de trabalho.

A seguir alguns exemplos de sistemas que utilizam a paginação


simples:
• DEC PDP-11 - minicomputador popular da década de 70;
• DEC VAX 11-780 - sucessor do PDP-11, minicomputador de 32 bits
(década de 80);
• IBM OS/2 - 2.0 - plataforma Intel 80386 e 80486, operando com
endereçamento de 32 bits e páginas de 4kbytes;
• IBM AS/400 - minicomputador de 64 bits;
129
01_SisOps.qxp 11/2/2009 11:35 Page 130

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

• Microsoft Windows 95 - dirigido para processadores 80386 ou


superiores, com espaço de endereçamento virtual linear de 2GB
(endereços de 32 bits) e páginas de 4KBytes.

7.6 Gerenciamento de Memória Cache

A memória Cache é uma memória de alta velocidade, que contém


aquelas partes do programa e dos dados que são usadas
intensivamente.

A idéia do Cache é que à medida que a velocidade da UCP cresce,


considerações de equilíbrio tornam necessária uma memória de maior
capacidade. Uma alternativa é a construção de uma memória
hierárquica, ver Figura 7.17. Isto é possível porque os programas de
computador exibem uma “localidade de referência” (referências à
endereços tendem a se agruparem).

Figura 7.17: Arquitetura processador memória e cachê [Stallings, 2007]

130
01_SisOps.qxp 11/2/2009 11:35 Page 131

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Funcionamento do CACHE

A memória principal é dividida em blocos. Esses blocos podem ter


tamanhos iguais ou menores do que uma página. Cópias dos blocos
intensivamente usados são mantidos no cache e na memória principal.
Quando um programa tenta referenciar seu espaço de
endereçamento, ele apresenta um endereço virtual ao hardware
(ou microprograma).

Se a página contendo aquele endereço estiver na memória


principal, o endereço virtual é traduzido para o endereço na memória
principal, caso contrário, ocorre uma falta de página.

Esta organização é um sistema de memória de paginação em dois


níveis, porém existem duas diferenças significativas entre paginação
da memória secundária (disco) para a memória principal e a paginação
da memória principal para o cache:

• A memória principal não possui latência: Neste caso a UCP pode


esperar a transferência da memória principal para o cache.
• Devido à rapidez e simplicidade da transferência, ela é
executada por microprograma, sem a assistência do sistema
operacional.

Conforme afirma Tanenbaum (2007), no seu livro de Arquitetura


de Computadores, apesar de memória virtual (paginada por demanda)
e caching não pareçam relacionadas, em termo de conceito elas são
muito similares. Com memória virtual, todo o programa é mantido em
disco e desmembrado em páginas de tamanho fixo. Algum
subconjunto dessas páginas está na memória principal. Se o programa
usarm na maior parte, as páginas na memória, haverá poucas faltas de
página e o programa executará rapidamente. Com caching, todo o
programa é mantido na memória principal e desmembrado em blocos
de cache de tamanho fixo. Algum subconjunto desses blocos é
mantido na cache. Se o programa usar, na maior parte, os dados dos
blocos que estão na cache, então haverá poucas faltas da cache e a
execução do programa será ainda mais rápida. Assim, em termos de
conceito, as duas são idênticas, mas operam em níveis difentes da
hierarquia.

131
01_SisOps.qxp 11/2/2009 11:35 Page 132

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Também há algumas diferenças entre memória virtual e caching.


Uma delas é que as faltas (misses) da cache são manipuladas pelo
hardware, enquanto as faltas de página são manipuladas pelo sistema
operacional. Além disso, os blocos de cache típicos são muito menores
do que páginas, por exemplo, 64 bytes versus 8KB. E mais, o
mapeamento entre páginas virtuais e quadros de página é diferente,
sendo que tabelas de páginas são organizadas indexando para os bits
de ordem alta no endereço virtual, enquanto que caches indexam para
os bits de ordem baixa do endereço de memória. Mas como afirma o
Prof.º Tanenbaum, no livro de Arquitetura de Computadores (2007), é
importante entender que são diferenças de implementação mas os
conceitos são similares.

7.7 SEGMENTAÇÃO

7.7.1 Funcionamento da Segmentação

A idéia da Segmentação é que o espaço de endereçamento


virtual é dividido em vários espaços de endereçamento virtuais
independentes – conhecidos como segmentos (ver figura 7.18).

Segmento: seqüência linear de endereços, de 0 a um valor


máximo.
Sistema Segmentado: cada processo é formado por segmentos.

A divisão em segmentos tem a haver com seus conteúdos

• Usar espaços de endereços completamente independentes,


segmentos, que consiste em uma sequência linear de endereços
de 0 até algum máximo.

• Um segmento é uma entidade lógica, da qual o programador


está ciente e a qual usa como uma entidade lógica. Um segmento
pode conter um procedimento, um vetor, ou uma pilha, ou um
conjunto de variáveis escalares, mas, em geral, não contém uma
mistura de tipos diferentes.
132
01_SisOps.qxp 11/2/2009 11:35 Page 133

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Os segmentos facilitam o manuseio de estruturas de dados, o que


pode aumentar o diminuir automaticamente. Isso facilita compartilhar
procedimentos ou dados entre vários programas, e facilita diferentes
tipos de interação.

Figura 7.18: Segmentos mais usados no espaço de endereçamento virtual

Em um espaço de endereçamento unidimensional com tabelas


crescentes, uma tabela poderá atingir outra. Para evitar isso, uma
memória segmentada permite que cada tabela cresça ou se reduza,
independentemente das outras tabelas (ver Figura 7.19).

Figura 7.19: Segmentos mais usados na segmentação

133
01_SisOps.qxp 11/2/2009 11:35 Page 134

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Quando um processo começa a ser executado, a UCP analisa cada


referência à memória. Se a referência corresponde a um segmento
que já está na memória, a execução prossegue. Mas, se ela se refere
a um segmento que não está na memória, ocorre uma falta de
segmento.

Então, o processo é interrompido, e o sistema operacional deve


trazer à memória principal o segmento necessário, só então, a UCP
pode executar a instrução (ver Figura 7.20).

Figura 7.20: Processos usando segmentação [Machado, 2007][Sementille, 2006]

134
01_SisOps.qxp 11/2/2009 11:35 Page 135

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

7.7.2 Falta de Segmentos

São detectadas na transformação do endereço virtual em real pela


UCP. Neste caso, um endereço virtual contém: um número de
segmento e um valor que indica o deslocamento.

O número do segmento refere-se à uma entrada na “tabela de


segmentos” (ver Tabela 7.2).

Tabela 7.2: Exemplo de Tabela de Segmentos

7.7.3 Vantagens da Segmentação

A segmentação possui as seguintes vantagens (ver Tabela 7.3):


• Facilidade de compilação e ligação de procedimentos separados
em segmentos.
• A mudança de tamanho de um procedimento (se ele está em um
segmento separado) não afetará os demais: pode ser recompila-
do separadamente.
• A segmentação facilita a partilha de procedimentos e dados
entre vários processos (reentrância).
• Como o programador está ciente da existência dos segmentos (e
de seus conteúdos), ele pode protegê-los.

135
01_SisOps.qxp 11/2/2009 11:35 Page 136

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Tabela 7.3: Resumo dos Conceitos de Paginação e Segmentação

A seguir alguns sistemas que utilizam a segmentação pura:

Burroughs B6700 - computador da década de 60


HP3000 - minicomputador cujo espaço de endereçamento lógico
consistia de 255 segmentos de 16Kbytesy
Intel 8086 - microprocessador de 16 bits, com espaço de
endereçamento lógico de 1MB, e segmentos de 64KB
IBM OS/2 - 1.x - plataforma Intel 80286, operando com endereça-
mento virtual de 512 MB e segmentos de 64kbytes
Microsoft Windows 3.x - também para plataforma Intel 80286,
operando com endereçamento virtual de 48 MB e segmentos de
64kbytes

136
01_SisOps.qxp 11/2/2009 11:35 Page 137

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

7.7.4 Segmentação com Paginação

É bom salientar que há um problema com a segmentação, pois os


tamanhos dos segmentos dependem do processo, porém os blocos de
memória são um recurso de hardware (seu tamanho é dependente do
sistema).

Uma solução é ter a combinação de segmentação com a paginação


(ver Figura 7.21).

Neste caso, o sistema pode satisfazer as necessidades de um


processo simplesmente variando o número de páginas de memória
real. Isso é mais difícil de fazer com blocos de tamanho variável, a
menos que seja definido dinamicamente que um bloco terá um
número especificado de páginas na memória real. Fazendo isso, pode-
se preservar a visão do processo de que a memória é segmentada, e
ainda a visão do sistema de que a memória real consiste em páginas
de memória de tamanho fixo.

Para isso, tem-se que redefinir o que parece ser o espaço virtual
de um processo:

Figura 7.21: Segmentação e Paginação

Assim, é possível observar que cada segmento é formado por um


número fixo de páginas. E não se exige que todas as páginas de um
segmento estejam na memória (para se preservar a capacidade de
alocação por página – como se observa na Figura 7.22).

137
01_SisOps.qxp 11/2/2009 11:35 Page 138

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 7.22: Exemplo de Segmentação e paginação

7.8 Resumo dos principais conceitos

A seguir uma pequena lista de alguns sistemas que utilizam a


segmentação com paginação:
Honeywell 6000 - computador da década de 60/70, que operava
com sistema operacional Multics, suportando processos com até
262144 segmentos de até 64KB
IBM System 360 - computador da década de 60, com espaço
lógico de 16MB, divididos em 16 segmentos de 1MB
IBM MVS - permite 2048 segmentos com 256 páginas de 4KB
Família Intel P6: suportando até 64TBytes de endereçamento
virtual e um máximo de 4GBytes de memória física, oferecendo
até 8192 segmentos de até 4GBytes cada um, com páginas de
4KBytes

Com relação ao tamanho de Página e fragmentação, devem-se


levar em conta os conceitos relacionados com a fragmentação interna
devido ao tamanho de página, e realizar uma análise de páginas
pequenas versus grandes.
138
01_SisOps.qxp 11/2/2009 11:35 Page 139

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

No caso dos sistemas operacionais mais conhecidos, temos que o


Linux fornece páginas de tamanho intermediárias: 2K, 4K e 8K,
enquanto que no Windows é 2K e 4K.

Com relação à Implementação de Segmentação: o que se


observa, é que geralmente, há dois modos: por permutação e por
paginação. Na permutação acontece similar à paginação sob
demanda, porém, páginas são de tamanho fixo, enquanto que os
segmentos não são.

Após o sistema executar durante algum tempo, a memória estará


dividida em várias porções, algumas que contêm segmentos cheios e
outras que contêm lacunas. Esse fenômeno é conhecido como
fragmentação externa.

Esse fenômeno faz com que exista a necessidade de compactar a


memória, isto é, reunir todas as lacunas pequenas e inúteis em uma
grande lacuna, na qual um ou mais segmentos possam ser alocados.

Para isso é necessário ter algoritmos. Os mais conhecidos e usados


são:
Melhor Ajuste: escolhe a menor lacuna na qual o segmento
caberá.
Primeiro Ajuste: percorre a lista de lacunas em circulo e escolhe
a primeira com tamanho suficiente para conter o segmento.

O Prof.º Knuth (1997) mostrou que a segunda opção tem bom


desempenho a pesar de ter menos tempo que o melhor ajuste, pois
este tende a gerar muitas lacunas pequenas e inúteis.

Por paginação: dividir cada segmento em páginas de tamanho fixo


e acessá-las sob demanda. Assim, algumas páginas de um segmento
podem estar em memória e outras no disco.

Para paginar um segmento é preciso uma tabela de páginas


separada para cada segmento. Essa idéia foi inicialmente
implementada no MULTICS [Tanenbaum, 2007], precursor do UNIX, e
também é usada nas máquinas da Intel, por exemplo, no Pentium 4.

139
01_SisOps.qxp 11/2/2009 11:35 Page 140

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

7.9 Gerência de Memória no Windows

No Windows NT, o projeto do gerente de VM presume que o


hardware subjacente suporta o mapeamento de virtual para físico, um
mecanismo de paginação e coerência de cache transparente em
sistemas multiprocesssados e permite que múltiplas entradas de
tabela de página mapeiem o mesmo quadro de páginas. O gerente de
VM no NT usa um esquema de gerencia baseado em páginas com
tamanho de 4KB (kilobytes).

Páginas de dados que são atribuídas a um processo, mas não estão


na memória física, são armazenadas em um arquivo de paginação no
disco.

O gerente de VM usa endereços de 32 bits, de modo que cada


processo possui um espaço de endereçamento virtual de 4 GB
(gigabytes). Os 2GB superiores são sempre os mesmos para todos os
processos e são usados pelo NT no modo kernel. Os 2GB inferiores são
distintos para cada processo e são acessíveis por threads tanto em
modo usuário quanto em modo kernel.

A tradução de endereços virtuais no Windows usa várias estruturas


de dados. Cada processo possui um diretório de páginas que contém
1024 entradas de diretórios de páginas com 4 bytes de tamanho
(ver Figura 7.23). Em geral, o diretório de páginas é privado, mas ele
poderia ser compartilhado entre processos caso o ambiente precise.

Cada entrada do diretório de páginas aponta para uma tabela de


páginas que contém 1024 entradas de tabelas de páginas (ou melhor
conhecidas como PTE – Page Tabel Entry) com 4 bytes de tamanho.
Cada PTE aponta para um quadro de páginas de 4 KB na memória
física. O tamanho total de todas as tabelas de páginas para um
processo é de 4 MB (megabytes), de modo que o gerente de VM
descarregará essas tabelas em disco quando necessário (operação de
swap out).

Para poder representar essa estrutura são necessários um inteiro


de 10 bits, pois pode representar todos os valores de 0 a 1023. Assim,
um inteiro de 10 bits pode selecionar qualquer entrada no diretório de
páginas ou em uma tabela de páginas. Essa propriedade é usada
140
01_SisOps.qxp 11/2/2009 11:35 Page 141

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

quando um ponteiro de endereço virtual é traduzido para um


endereço de byte na memória física.

Figura 7.23: Layout de Figura Virtual no Windows [Silberschatz, 2004].

Um endereço de memória virtual de 32 bits é dividido em 3


campos (inteiros). Os primeiros 10 bits do endereço virtual são usados
como índice no diretório de páginas. Esse endereço seleciona uma
entrada do DP, que aponta para uma tabela de páginas. Os 10 bits
seguintes do endereço virtual são usados para selecionar uma PTE
daquela tabela de páginas. A PTE aponta para um quadro de página na
memória física. Os 12 bits restantes do endereço virtual apontam para
um byte específico naquele quadro de página. Um ponteiro para
aquele byte específico na memória física é feito pela concatenação de
20 bits da PTE com os 12 bits inferiores do endereço virtual.

Assim, a PTE de 32 bits possui 12 bits sobrando; esses bits são


usados para descrever a página. Os primeiros 5 bits especificam a
proteção da página, tal como página se somente leitura, ou somente
escrita, ou leitura e escrita. Os 4 bits seguintes especificam qual
arquivo de paginação apóia a página de memória, e os 3 últimos bits
permitem definir o estado da página na memória.

141
01_SisOps.qxp 11/2/2009 11:35 Page 142

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Uma página pode estar em um dos seguintes seis estados: válida,


zerada, livre, em espera, modificada e defeituosa. Uma página válida
está em uso por um processo ativo. Uma página livre é aquela que não
é referenciada em uma PTE. Uma página zerada é uma página livre
que foi preenchida com zeros e está pronta para uso imediato. Uma
página em espera foi removida do conjunto de trabalho de um
processo. Uma página modificada recebeu escrita, mas ainda não foi
copiada para o disco. Uma página defeituosa não é utilizável porque
um erro de hardware foi detectado.

A estrutura real da PTE é mostrada na Figura 7.24. A PTE contém


5 bits para proteção de página, 20 bits para endereço do quadro de
página, 4 bits para seleção de um arquivo de paginação e, 3 bits para
descrever o estado da página.

Caso a página não esteja na memória, os 20 bits do endereço do


quadro de página contêm, em vez disso, um deslocamento no arquivo
de paginação. Uma vez que o código executável e arquivos mapeados
em memória já possuem uma cópia no disco, eles não necessitam de
espaço em um arquivo de paginação.

Caso uma dessas páginas não esteja na memória física, a


estrutura da PTE é a seguinte; o bit mais significativo é usado para
especificar a proteção da página, os 28 bits seguintes são usados como
índice de uma estrutura de dados de sistema que indica um arquivo e
o deslocamento para a página dentro do arquivo, e os 3 últimos bits
permitem especificar o estado da página.

Na figura 7.24, o valor do estado T significa Transição,


D = Modificada e, P = Presente.

Figura 7.24: Entrada Padrão na Tabela de Páginas no Windows [Silberschatz, 2001]


142
01_SisOps.qxp 11/2/2009 11:35 Page 143

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Como explica Silberschatz (2001), é díficil compartilhar uma pági-


na entre processos se cada processo possuir seu próprio conjunto de
tabelas de páginas, pois cada um possuirá sua própria PTE para o
quadro de página. Quando uma página compartilhada faltante é
carregada na memória física, o endereço físico deverá ser
armazenado nas PTEs pertencentes a cada processo que compartilha
a página. Todos os bits de proteção e de estado da página nessas PTEs
precisam ser consistentemente atualizados. Para evitar esses
problemas, o Windows usa indireções. Para cada página
compartilhada, o processo possui uma PTE que aponta para um
protótipo de entrada na tabela de páginas, em vez do quadro de pági-
na. A PTE protótipo contém o endereço do quadro de página e os bits
de proteção e de estado. Assim, o primeiro acesso por um processo a
uma página compartilhada gera uma falta de página. Após esse
primeiro acesso, os outros acessos adicionais são executados de
maneira normal. Se a página estiver marcada como somente leitura, o
gerente de VM efetiva um copy-on-write e o processo efetivamente
não terá mais uma página compartilhada.

Páginas compartilhadas nunca aparecem no arquivo de paginação,


mas são, em vez disso, encontradas no sistema de arquivos.

O gerente de VM acompanha todas as páginas da memória física


por meio de uma base de dados de quadro de páginas. Há uma
entrada para cada quadro de página. A entrada aponta para a PTE que
aponta para o quadro de página, de modo que o gerente de VM possa
manter o estado da página. Quadros de páginas são encadeados para
formar (por exemplo) a lista de páginas zeradas e a lista de páginas
livres, ver exemplo na figura 7.25.

Quando acontece uma falta de página, o gerente de VM carrega a


página que falta colocando aquela página no primeiro quadro na lista
de páginas livres. Usando o conceito de localidade, quando uma
página é usada, é provável que as páginas adjacentes sejam também
consultadas em um futuro próximo. Devido a essa localidade, quando
o gerente de VM carrega uma página faltante, ele também carrega
algumas páginas adjancentes. Este procedimento de páginas
adjacentes (adjacent faulting) tende a reduzir o número total de
faltas de página.

143
01_SisOps.qxp 11/2/2009 11:35 Page 144

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Caso quadros de página não estejam disponíveis na lista de


quadros livres, o Windows usa uma política de susbstituição FIFO para
o processo para tomar páginas dos processos que estejam usando mais
que o seu tamanho de seu conjunto de trabalho mínimo.

O Windows monitora as faltas de página de cada processo cujo


conjunto de trabalho esteja em seu tamanho mínimo e ajusta esse
tamanho de forma apropriada. Em particular quando um processo é
iniciado, a ele é atribuído um conjunto de trabalho padrão de 30
páginas. O Windows periodicamente testa esse tamanho subtraindo
uma página válida do processo. Caso a execução do processo continue
sem gerar uma falta de página para a página subtraída, o conjunto de
trabalho do processo é reduzido de 1 e a página é adicionada à lista
de páginas livres.

Figura 7.25: Base de Dados de Molduras de Páginas [Tanenbaum, 2008]

144
01_SisOps.qxp 11/2/2009 11:36 Page 145

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A tabela 7.4 mostra as principais funções de API Win32 para geren-


ciamento de memõria virtual no Windows 2000.

Tabela 7.4: Funções usadas pela API Win 32 [Silberschatz, 2001]

7.10 Gerência de Memória no UNIX e Linux

No caso do sistema Linux, há dois componentes na gerência de


memória. O primeiro lida com a alocação e liberação de memória
física: páginas, grupos de páginas e pequenos blocos de memória. O
segundo trata a memória virtual, que conforme foi visto no capítulo,
é a memória mapeada no espaço de endereçamento dos processos em
execução.

O gerente primário da memória física no kernel Linux é o alocador


de páginas, responsável pela alocação e liberação de todas as páginas
físicas.

145
01_SisOps.qxp 11/2/2009 11:36 Page 146

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Ele é capaz de alocar intervalos de páginas fisicamente contíguas


sob demanda. Esse alocador utiliza um algoritmo chamado
buddy-heap para rastrear as páginas físicas disponíveis.

Um alocador do tipo buddy-heap emparelha unidades adjacentes


de memória alocável. Cada região da memória alocável tem uma
parceira adjacente, e sempre que duas regiões parceiras alocadas são
liberadas, são combinadas a fim de formar uma região maior. Essa
região maior também possui sua parceira, com quem pode combinar e
formar umja região livre ainda mais ampla.

Outra alternativa, se uma pequena solicitação de memória não


puder ser satisfeita por meio da alocação de uma pequena região livre
existente, então uma região livre maior será subdividida em duas
parceiras, a fim de satisfazer a solicitação.

Para esse processo se utilizam listas encadeadas independentes


para registrar as regiões de memória livre de cada tamanho
permitido. No linux, o menor tamanho alocável segundo esse
mecanismo é uma página física. O processo é mostrado na Figura 7.26
que usa o algoritmo buddy heap para uma região de 4 KB está sendo
alocada, mas a menor região disponível é de 16 KB, neste caso, a
região é quebrada recursivamente até que seja disponibilizada uma
parte do tamanho desejado (neste caso, 4KB).

Figura 7.26: Divisão da Memória usando o algoritmo Buddy-Heap [ Silberschatz, 2001]

146
01_SisOps.qxp 11/2/2009 11:36 Page 147

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Em última instância, todas as alocações de memória no kernel


Linux dão-se de maneira estática, por drivers que reservam uma área
de memória contígua na inicialização do sistema, ou dinamicamente,
pelo alocador de páginas.

As funções do kernel não necessariamente têm de utilizar o


mesmo alocador básico para reservar memória. Diversos subsistemas
de gerência de memória especializados lançam mão do alocador de
páginas subjacente para gerenciar seu próprio conjunto de memória.
Os mais importantes são o sistema de memória virtual, o alocador de
comprimento variável (kmalloc) e, os dois caches de dados
persistentes do kernel: o cache de buffers e o cache de páginas.

Muitos componentes do sistema Linux precisam alocar páginas


inteiras à vontade, mas freqüentemente são solicitados blocos de
memória menores. O kernel proporciona um alocador adicional para
solicitações de tamanho arbitrário, em que o tamanho do pedido não
necessariamente é conhecido antecipadamente e podem ser de
apenas alguns bytes, em vez de uma página inteira. Analogamente, à
função malloc da linguagem C, esse serviço kmalloc aloca páginas
inteiras sob demanda, mas em seguida, divide-as em pedaços
menores.

O kernel mantém um conjunto de listas de páginas em uso pelo


serviço kmalloc, em que todas as páginas de uma dada lista foram
divididas em pedaços de um tamanho específico. A alocação de
memória envolve determinar a lista apropriada e a tomada do
primeiro pedaço disponível na lista ou a alocação de uma nova página
e sua divisão.

Os dois alocadores, kmalloc e de páginas, são à prova de


interrupções [Silberschatz, 2001].

As regiões de memória reinvidicadas pelo sistema kmalloc são


alocadas permanentemente até receberem uma liberação explícita. O
sistema kmalloc não pode relocar ou reivindicar essas regiões em
resposta a uma eventual escassez de memória.

147
01_SisOps.qxp 11/2/2009 11:36 Page 148

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Os outros 3 subsistemas principais (cache de buffers, cache de


páginas e sistema de memória virtual) que tratam de sua própria
gerência de páginas físicas são intimamente relacionados. O cache de
buffers é o cache principal do kernel para dispositivos orientados a
bloco (ex. Unidades de disco) e é o principal mecanismo por meio do
qual é efetuado o I/O (entrada e saída, ver capítulo seguinte) desses
dispositivos. O cache de páginas mantém em cache páginas inteiras de
conteúdo de arquivo, e não se limita a dispositivos de blocos, pode
também fazer cache de dados da rede, e é utilizado tanto pelos
sistemas de arquivos baseados em disco nativos do Linux quanto pelos
sistemas de arquivos em rede NFS. Os sistema de memória virtual
gerencia o conteúdo do espaço de endereçamento virtual de cada
processo.

Segundo afirmação do Silberschatz, esses 3 sistemas interagem


intimamente entre si. A leitura de uma página de dados para o cache
de páginas requer a passagem temporária pelo cache do buffers, as
páginas no cache de páginas também podem ser mapeadas no sistema
de memória virtual, caso um processo tenha mapeado um arquivo em
seu espaço de endereçamento. O kernal mantém um contador de
referências em cada página de memória física, de modo que páginas
compartilhadas por dois ou mais desses subsistemas possam ser
liberadas quando não se encontrarem mais em uso em lugar algum.

O sistema de memória virtual do Linux é responsável pela


manutenção do espaço do endereçamento visível para cada processo.
Ele cria páginas de memória virtual sob demanda e gerencia a carga
dessas páginas do disco ou sua descarga de volta para o disco
conforme necessário. No linux, o gerente de memória virtual mantém
duas perspectivas do espaço de endereçamento de um processo: como
um conjunto de regiões separadas ecomo um conjunto de páginas.

A primeira visão de um espaço de endereçamento é a visão


lógica, descrevendo as instruções recebidas pelo sistema de memória
virtual referentes ao layout do espaço de endereçamento. Nessa
visão, o espaço de endereçamento consiste em um conjunto de
regiões não super-postas, cada uma das quais representando um
subconjunto contíguo e alinhado por página do espaço de
endereçamento.

148
01_SisOps.qxp 11/2/2009 11:36 Page 149

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Cada região é descrita internamente por uma única estrutura


vm_area_struct, que define as propriedades da região, inclusive, as
permissões de leitura, escrita e execução do processo na região, assim
como mantém informações sobre todos os arquivos associados com
essa região [Silberschatz, 2001].

As regiões para cada espaço de endereçamento são encadeadas


em uma árvore binária balanceada, de modo a possibilitar uma
pesquisa rápida da região correspondente a qualquer endereço
virtual.

O kernel mantém também uma segunda visão, física, de cada


espaço de endereçamento. Essa visão fica armazenada nas tabelas de
páginas do hardware para o processo. As entradas da tabela de
páginas determinam a localização atual exata de cada página de
memória virtual, quer esteja em disco, quer em memória física.
A perspectiva física é gerenciada por um conjunto de rotinas,
invocados a partir dos tratadores de interrupção de software do
kernel sempre que um processo tenta acessar uma página que não se
encontra presente no momento nas tabelas de páginas.

Cada vm_area_struct na descrição do espaço de endereçamento


contém um campo que aponta para uma tabela de funções que
implementam as funções básicas de gerência de página para qualquer
região dada da memória virtual. Todos os pedidos de leitura ou
escrita em uma página não-disponível acabam sendo enviados para o
tratador apropriado na tabela de funções da vm_area_struct, de
modo que as rotinas de gerência de memória centrais não precisam
conhecer os detalhes da gerência de cada tipo possível de região de
memória [Silberschatz, 2001].

Uma região que tem um arquivo como armazenamento de apoio


funciona como visor para um seção do arquivo: sempre que o
processo tenta acessar uma página dentro daquela região, a tabela de
páginas é preenchida com o endereço de uma página dentro do cache
de páginas do kernel que corresponda ao deslocamento apropriado no
arquivo. A mesma página de memória física é utilizada tanto pelo
cache de páginas quanto pelas tabelas de páginas do processo, de
forma que qualquer mudança efetuada no arquivo pelo sistema de
arquivos fica vísivel de imediato para todos os processos que tiverem
mapeado aquele arquivo em seu espaço de endereçamento. Qualquer
149
01_SisOps.qxp 11/2/2009 11:36 Page 150

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

quantidade de processos diferentes pode mapear a mesma região do


mesmo arquivo, e todas acabarão utilizando a mesma página de
memória física para esse fim.

O mapeamento de uma região para o espaço de endereçamento


do processo pode ser privado ou compartilhado. Se um processo
escrever em uma região de mapeamento privado, o paginador
detectará a necessidade de uma operação copy-on-write para manter
as alterações locais com relação ao processo. Por outro lado, as
escritas em uma região compartilhada resultam na atualização do
objeto mapeado para tal região, de modo que a mudança ficará
vísivel de imediato para qualquer outro processo que estiver mapean-
do tal objeto.

Há exatamente duas situações em que o kernel cria um novo


espaço de endereçamento virtual: na execução, por um processo, de
um novo programa por meio da chamada ao sistema exec e na criação
de um novo processo, por meio da chamada ao sistema fork [Ribeiro,
2005].

O primeiro caso é fácil, pois quando um novo programa é


executado, o processo recebe um espaço de endereçamento novo,
completamente vazio. Cabe às rotinas carregar o programa para
ocupar o espaço de endereçamento com regiões de memória virtual.

No segundo caso, a criação de um novo processo via fork implica


na criação de uma cópia integral do espaço de endereçamento virtual
do processo existente. O kernel copia os descritores da
vm_area_struct do processo pai e, em seguida, cria um novo
conjunto de tabelas de páginas para o filho. As tabela de páginas do
pai são copiadas diretamente para as do filho, com o contador de
referências de cada página afetada sendo incrementada; assim sendo,
após o fork, pai e filho compartilham as mesmas páginas físicas de
memória em seus espaços de endereçamento.

Importante salientar que há um mecanismo que garante que as


páginas privadas de dados serão compartilhadas sempre que possível,
e só haverá cópias quando absolutamente necessário.

150
01_SisOps.qxp 11/2/2009 11:36 Page 151

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Uma importante tarefa para um sistema de memória virtual é


relocar as páginas da memória física para o disco quando há
necessidade de memória. As versões modernas dos sistemas UNIX
fazem esse processo usando o mecanismo de paginação, que é a
movimentação de páginas individuais de memória virtual entre a
memória física e o disco. O Linux não implementa o swapping de
processo integral, ao invés disso, ele utiliza exclusivamente o
mecanismo mais recente de paginação.

O processo de paginação pode ser dividido em duas seções: uma


onde atua o algoritmo de políticas (que decide que páginas gravar no
disco e quando fazê-lo), e a outra, o mecanismo de paginação (que
realiza a transferência e pagina os dados de volta para a memória
física quando se tornam necessários novamente).

A política de descarga de páginas no Linux emprega uma versão


modificada do algoritmo do relógio (mais conhecido como segunda
chance). No linux, é utilizado um relógio de passagens múltiplas e
cada página tem uma idade que é ajustada a cada passagem do
relógio. A idade é um indicativo de quanta atividade ela tem visto
recentemente. Páginas com mais uso possuem um valor de idade mais
elevado, mas a idade de páginas que não são acessadas com
freqûencia decresce a cada passagem. Essa atribuição de idade
permite ao paginador selecionar páginas para descarregar com base
em uma política de utilização com menor frequencia (ou melhor
conhecido como LRU – Least Frequently Used) [Tanenbaum, 2003]

O Linux reserva para seu próprio uso interno uma região do espaço
de endereçamento virtual de cada processo constante e dependente
da arquitetura. O núcleo do kernel, bem como todas as páginas
alocadas pelo alocador de páginas normal, reside nessa região.

O kernel proporciona um par de recursos que permitem que os


processos façam uso dessa memória virtual. A função vmalloc aloca
um número arbitrário de páginas físicas de memória, e mapeia-os em
uma única região de memória virtual do kernel, possibilitando a
alocação de grandes pedaços contíguos de memõria, mesmo que não
haja um número suficiente de páginas físicas adjacentes livres para
satisfazer o pedido.

151
01_SisOps.qxp 11/2/2009 11:36 Page 152

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

A função vremap mapeia uma sequência de endereços virtuais


para que apontem para uma área de memória utilizada por um driver
de dispositivo, melhor conhecido como I/O mapeado em memória
[Silberschatz, 2001].

Importante salientar que o carregamento de um arquivo binário


para a memória física, no Linux, não é realizado pelo carregador
binário, ao invés disso, as páginas do arquivo binário são mapeadas em
regiões da memória virtual. Só quando o programa tenta acessar uma
determinada página é que uma falta de página resulta em seu
carregamento na memória física.

É responsabilidade do carregador binário do kernel configurar o


mapeamento inicial de memória. Um arquivo binário e formato ELF é
constituído por um cabeçalho, seguido de várias seções alinhadas por
página. O carregador ELF funciona lendo o cabeçalho e mapeando as
seções do arquivo em regiões separadas da memória virtual.

É também importante lembrar que o kernel situa-se em uma


região de memória que é reservada, em uma das extremidades do
espaço de endereçamento, em sua própria região privilegiada de
memória virtual, inacessível aos programas normais de modo usuário.
O restante da memória virtual encontra-se disponível para as
aplicações, as quais podem utilizar as funções de mapeamento do
kernel para criar regiões que mapeiam uma parte de um arquivo ou
que permanecem disponíveis para dados de aplicações.

Portanto, a tarefa do carregador consiste em configurar o


mapeamento inicial de memória a fim de permitir que a execução do
programa tenha início. As regiões que precisam ser inicializadas
incluem a pilha e as regiões de dados e texto do programa.

A pilha é sempre criada no alto da memória virtual de modo


usuário e cresce para baixo, em direção aos endereços menores. Esta
região inclui cópias dos argumentos e das variáveis de ambiente
atribuídos ao programa na chamada do sistema exec [Ribeiro, 2005].
As demais regiões são criadas perto da extremidade inferior da
memória virtual. As seções do arquivo binário que contêm texto de
programa (instruções executáveis) ou dados de leitura são mapeadas
na memória como região protegida contra escrita. Os dados
152
01_SisOps.qxp 11/2/2009 11:36 Page 153

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

inicializados alteráveis são mapeados em seguida, depois, todos os


dados não inicializados são mapeados como uma região privada de
demanda zero (é uma região sem armazenamento de apoio – quando
um processo procura ler uma página em tal região, tem como retorno,
simplesmente, uma página de memória cheia de zeros).

Imediatamente além dessas regiões de tamanho fixo encontra-se


uma região de tamanho variável que os programas podem expandir
conforme a necessidade, a fim de manter dados alocados em tempo
de execução. Cada processo possui um ponteiro, brk [Silberschatz,
2001], que aponta a extensão da região de dados no momento; assim,
os processos podem estender ou contrair a região do seu brk mediante
uma única chamada ao sistema.

Uma vez configurados esses mapeamentos, o carregador inicializa


o registrador do contador do programa do processo, com o ponto de
partida registrado no cabeçalho ELF, e o processo pode ser
escalonado.

Uma vez carregado o programa e iniciada sua execução, todo o


conteúdo necessário do arquivo binário terá sido carregado no espaço
de endereçamento virtual do processo. Entretanto, a maioria dos
programas também precisa executar funções a partir das bibliotecas
do sistema, e essas funções de biblioteca também têm de ser
carregadas.

No caso mais simples, quando um programador constrói uma


aplicação, as funções de biblioteca necessárias são incorporadas
diretamente no arquivo binário executável do programa. Tal programa
é linkado estaticamente às suas bibliotecas, e a execução dos
executáveis linkados estaticamente pode ter início imediatamente
após sua carga.

Esse método possui como principal desvantagem o fato que todo


programa gerado tem de conter cópias de exatamente as mesmas
funções de biblioteca do sistema comuns. É muito mais eficiente, em
termos tanto de memória física como de uso de espaço em disco,
carregar as bibliotecas do sistema uma única vez. O linking dinâmico
possibilita a ocorrência dessa carga única [Silberschatz, 2001].

153
01_SisOps.qxp 11/2/2009 11:36 Page 154

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

O Linux implementa o linking dinâmico em modo usuário por meio


de uma biblioteca de linkagem especial. Todos os programas linkados
dinamicamente contêm uma pequena função linkada estaticamente,
chamada quando o programa é iniciado. Essa função estática mapeia
a biblioteca de linkagem na memória e executa o código que tal
função contém.

A biblioteca de linkagem determina a lista das bibliotecas


dinâmicas requeridas pelo programa e os nomes das variáveis e
funções necessárias dessas bibliotecas, lendo as informações contidas
em seções do binário ELF. Depois, mapeia as bibliotecas no meio da
memória virtual e resolve as referências aos símbolos nelas contidos.
Não importa exatamente onde na memória essas bibliotecas
compartilhadas vêm a ser mapeadas pois são compiladas em código
independente de posição (no modo PIC – Position Independent Code),
que pode ser executado em qualquer endereço de memória
[Silberschatz, 2001].

154
01_SisOps.qxp 11/2/2009 11:36 Page 155

CAPÍTULO 8

Entrada e Saída

A cada dia a informática está se tornando uma ferramenta de


trabalho essencial à vida das pessoas, facilitando e agilizando as
atividades sejam elas na área profissional ou pessoal, cada vez mais
aumentando a capacidade de processamento e nos permitindo obter
informações com mais rapidez e com grandes vantagens aos usuários.
Para tanto, é necessária a inserção de informações e a execução de
procedimentos pelo computador. Este capítulo ilustra como os
dispositivos de Entrada e Saída (E/S) interagem executando comandos
e realizando a captura de interrupções para realização de suas
tarefas.

O Sistema Operacional é o responsável por exercer a interação e


fornecer as interfaces ideais para os dispositivos de entrada e saída,
que, por ocasião da execução de um programa, necessitará realizar
acesso aos dispositivos desta natureza. Para isso, comunica-se com os
respectivos endereços de cada dispositivo existente e que geralmente
está relacionado ao hardware do computador. Estes dispositivos nos
permitem receber ou enviar informações para o processador e podem
ser da seguinte natureza: controladores de dispositivos de
armazenamento e de comunicação entre computadores, tipo (disco
rígido, CDs, fitas, pen drivers, placas de rede, modem, monitor,
teclado, mouse, etc). Os controladores possuem a função de trans-
portar as solicitações de operações de ler, escrever e reiniciar, para
uma linguagem que permita a emissão de acionamentos eletrônicos,
elétricos e mecânicos para realização das tarefas solicitadas. Como
existem vários dispositivos de entrada e saída, cada um em
específico, possui o seu próprio controlador, estes por sua vez são
compostos de registradores internos com a funcionalidade de
armazenar os dados e sinais de controle enviados através do proces-

155
01_SisOps.qxp 11/2/2009 11:36 Page 156

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

sador e permitindo que sejam realizadas as operações solicitadas


(leitura / escrita) de bits e a programação de suas funções através
desses registradores. Esta comunicação é estabelecida através do
barramento que interliga-o aos periféricos e componentes de um
sistema de computador. Silberschatz (2003).

Figura 8.1: Modelo de interligação, CPU, memória, controladores e dispositivos de entrada e


saída. Fonte. Tanenbaum – 2ª ed (2003).

8.1. Gerenciamento de Entrada/Saída

Com o surgimento dos controladores de entrada e saída o


processador passou a tratar suas tarefas de uma forma mais
independente, pois antigamente, qualquer tipo de comunicação entre
o processador e os periféricos era de forma direta, que o tornava
responsável por todas as operações que envolvia a leitura e a gravação
nos dispositivos. Atualmente, toda e qualquer tarefa é executada
através da comunicação entre o processador e a controladora do
dispositivo de um referido periférico, não sendo mais realizado
diretamente. Para estes procedimentos existem três grupos divididos
da seguinte forma: Entrada e Saída Programada, Interrupção Entrada
e Saída e Acesso Direto à Memória (DMA), que descreveremos a seguir.

156
01_SisOps.qxp 11/2/2009 11:36 Page 157

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.1.1 Entrada e Saída Programada

Segundo Silberschatz (2003), para este procedimento de


comunicação o processador é responsável por iniciar e interromper a
execução de um programa controlando todas as E/S, sejam elas de
execução de comando ao módulo para realização de leituras e ou
escritas, para detectar o estado dos dispositivos ou controlar a
transferência de dados de qualquer operação de entrada e saída que
for solicitado por um programa. Para isso o processador deverá
suspender a tarefa que está executando para atender a esta
solicitação. Um problema observado com este procedimento é o
possível desperdício do desempenho do processador caso o seu
processamento seja mais rápido que o controlador de entrada e saída
do dispositivo que solicitou a operação.

Figura 8.2: Entrada e Saída Programada. Fonte. www.laercio.com.br/artigos/hardware/


hard-010/hard-010.htm (2003).

Neste procedimento o programador é o responsável pelo


sincronismo do processador com a controladora, implementando em
um registrador do processador onde serão encaminhados à
controladora os comandos a serem executados que aguardará os seus
resultados. O processador poderá, por exemplo, encaminhar um
comando para realizar uma operação de escrita em uma determinada
informação e ficar acompanhando o status do registrador de estado
para verificar se o dado já se encontra disponível e para que possa
157
01_SisOps.qxp 11/2/2009 11:36 Page 158

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

executar a tarefa. O fato do processador consultar o registrador de


estado continuamente em busca de uma resposta favorável à
realização de sua tarefa despende um tempo muito grande em
cálculos, haja vista que neste procedimento programado as operações
de entrada e saída em relação aos cálculos são um pouco mais lentas.

Conforme Oliveira, R., et. al. (2004), para atenuar este problema,
utiliza-se um método denominado de Polling, inserindo operações de
cálculos entre cada verificação ao registrador de estado. Com isso
reduziremos os gastos de tempo do processador, mas em
contrapartida estaremos causando outro problema, que seria o fato de
determinar o tempo para realização destas verificações por parte do
processador. Neste caso porém, teríamos duas linhas de ação:

1ª linha de ação
Quando este tempo for muito alto, consequentemente haverá
certo gasto de tempo principalmente se o dispositivo de E/S for muito
lento;

2ª linha de ação
Quando este tempo for baixo, poderemos despender um tempo
desnecessário esperando uma resposta por parte do dispositivo de E/S
e com isso poderá ocorrer perdas de informações por alguns
dispositivos que utilizam buffers com limitação de armazenamento de
dados, que por um determinado espaço de tempo, deixará de ser lido,
ocorrendo uma sobreposição de informações e com isso perderíamos
os dados anteriormente armazenados. Esta ocorrência poderia ser
resolvida se os próprios dispositivos fossem capazes de encaminhar ao
processador uma mensagem avisando sobre a disponibilidade dos
dados a serem utilizados em suas operações.

158
01_SisOps.qxp 11/2/2009 11:36 Page 159

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.1.2 Interrupção de Entrada e Saída

Este mecanismo dispensa a necessidade da implementação do


método polling nas suas operações, pois todas as solicitações serão
tratadas através de interrupções. Neste procedimento o processador
apenas se encarrega de iniciar uma operação de entrada e saída
através de comandos enviados via software ao controlador do
dispositivo. Por ocasião do término desta operação o controlador
encaminhará uma mensagem de interrupção ao processador, ao qual
tratará esta interrupção acionando o driver do dispositivo.

Figura 8.3: Sistema de Interrupção e Exceções. Fonte. Silberschatz (2003).

Sendo assim, nesta comunicação podemos evitar que o


processador desperdice tempo aguardando que a operação de entrada
e saída termine e assim possa continuar com a execução do programa.
O processador se encarregará de encaminhar uma mensagem para a
controladora do dispositivo com a tarefa a ser executada e continuará
a realizar outras atividades que os programas requisitarem. Quando a
controladora concluir a operação solicitada pelo processador, a mesma
emitirá uma mensagem de resposta (interrupção ao processador)
informando a conclusão da operação e o processador neste momento
acessará o módulo de E/S para obter o status da operação. Estas ações
são geradas através do hardware (interrupções) ou através de
software, que sinalizará ao processador que assuma o controle e a
execução das tarefas a serem realizadas. Diante desta situação, o
processador procede a uma parada do programa que está em execução
para realizar uma determinada rotina específica para o tratamento da
interrupção. Ressaltando que há a necessidade que o processador
preserve o estado atual do programa que vinha executando para que
o mesmo possa retomar as informações e continuar o seu trabalho.

159
01_SisOps.qxp 11/2/2009 11:36 Page 160

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Há vários dispositivos periféricos, tais como: terminais, discos,


impressoras, que originam interrupções pelo usuário através das teclas
do console ou ainda pelo relógio do sistema que decrementa
automaticamente o conteúdo de um registrador ou a posição de
memória, mantendo sempre uma frequência constante e
interrompendo o processador quando atingir o valor zero. Uma
interrupção não afeta a instrução que está sendo executada pelo
processador no momento em que ocorre, porém, esta somente é
detectada após o término e, ou antes, da execução de uma instrução.
Existem algumas instruções que desabilitam ou inibem o sistema de
interrupção e com isso o processador não as detectam, nesta situação
permanece em fila aguardando que esta instrução as liberem
novamente e assim possam ser tratadas pelo processador. Estas
instruções são chamadas de mascaramento e desmascaramento. Ainda
existe uma terceira classe de interrupções causadas pelo próprio
processador, elas são geradas quando se detecta algum erro ou
exceção, por exemplo, originadas pela execução de um programa que
apresente erro ao tentar realizar um cálculo de divisão por zero ou ao
tentar acessar uma posição na memória que não é identificada.
Silberschatz (2003).

Vale ressaltar que o processador será sempre o responsável pelas


operações de entrada e saída programada, interrupção de entrada e
saída e por receber e ou armazenar os dados da memória principal,
sejam elas: operação de saída (memória para dispositivo) e operação
de entrada (dispositivo para memória).

160
01_SisOps.qxp 11/2/2009 11:36 Page 161

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.1.3 Acesso Direto à Memória

Com o grande volume de informações a serem transmitidas e para


solucionar a questão do processador de receber interrupções com
frequência para se comunicar com o dispositivo de E/S, e ainda,
minimizar o tempo gasto na verificação do estado e resultado das
operações que ocasionam uma baixa no desempenho do processador
por conta do excesso de interrupções, foi desenvolvido um novo
dispositivo para auxiliar na transferência destas informações,
denominado DMA – Direct Memory Access, Oliveira, R., et. al. (2004).

Como já foi comentado, o processador é o responsável pela leitu-


ra das informações na interface e por sua transferência à memória, ou
ainda, pela leitura na memória e transferência para a interface. Este
procedimento torna-se ineficiente quando o volume de informações é
significativo, pois, além de envolver o processador, essa transferência
representa dois movimentos de dados. Com esta técnica é possível
realizar a transferência de um bloco de informações entre a memória
e os dispositivos de E/S sem que seja necessária a ação do
processador, a não ser por ocasião do início de uma operação
solicitada e ao final da transferência, é que o processador será
informado sobre a finalização da operação.

Segundo Oliveira, R., et. al. (2004), o controlador DMA é uma


técnica empregada por hardware para realizar a transferência de
informações entre um dispositivo e possui a capacidade de acessar
diretamente a memória, pois está conectada ao barramento de
endereços e de dados do equipamento. Este controlador
internamente, é composto de registradores que são utilizados pelo
processador para executar a transferência de informações, servindo
para armazenamento de endereços, fonte e destino da transferência,
para determinar a quantidade de bytes a serem transferidos, para
execução de comando, e para informar o estado do processo. Com a
utilização do controlador DMA, o processador passou a trabalhar com
mais folga, podendo dar atenção a outras tarefas que estejam sendo
requisitadas. Por ocasião da finalização da transferência dos dados
pelo controlador o mesmo emitirá um sinal ao processador, utilizando
para isso, a interrupção de hardware.

161
01_SisOps.qxp 11/2/2009 11:36 Page 162

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 8.4: Entrada e Saída por DMA.


Fonte. www.laercio.com.br/artigos/hardware/hard-010/hard-010.htm (2003).

Este procedimento se torna mais eficaz em relação aos outros


principalmente, em situações em que ocorram operações nas quais
envolvam muitas informações a serem lidas ou escritas, levando em
consideração ainda, que haverá certa competição entre o controlador
de DMA e o processador para acesso à memória, pois o mesmo estará
em atividade realizando as tarefas de outros programas e que
necessitará de acesso a memória. Mas como podemos controlar esta
competição? O barramento não é usado somente pelos controladores
de E/S, mas também pelo processador na busca de informações das
instruções designadas pelos programas em execução, para isso o
barramento prioriza a sequência de informações que são enviadas e
recebidas por seu meio, utilizando um dispositivo denominado árbitro
do barramento, que decidirá de quem é a vez de ter acesso à
memória. Geralmente, os dispositivos de E/S têm a preferência,
colocando assim o processador para segundo lugar, pois os discos e
outros dispositivos cuja operação dependa de movimentos de suas
partes, não podem ter suas tarefas interrompidas na metade. Nesta
situação poderíamos sofrer perdas de informação caso tenhamos que
forçá-los a esperar.

162
01_SisOps.qxp 11/2/2009 11:36 Page 163

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Assim, quando uma operação de E/S estiver em andamento será


garantido o acesso prioritário ao barramento do dispositivo que
estiver realizando a tarefa. Mas mesmo assim, utilizar DMA é mais
vantajoso do que o processador permanecer diretamente realizando
estas transferências de informações através de software. Oliveira, R.,
et. al. (2004).

Figura 8.5: Esquema de funcionamento - DMA.


Fonte: Organização Estruturada de Computadores, Tanenbaum – 4ª ed (2001).

O controlador de DMA quando entra em funcionamento, assume a


responsabilidade pelo barramento. Enquanto o processador está em
operação, a CH1 permanecerá ativada, permitindo o fluxo de
endereços, dados e o controle entre o processador e o barramento,
sendo desativada somente por ocasião do início do funcionamento do
controlador de DMA que passará a ativar a CH2. O controlador DMA por
sua vez, controlará os endereços e ativará os sinais de controle que se
fizerem necessários, permitindo que os periféricos enviem ou recebam
informações diretas da memória principal sem ser preciso a interação
com o processador. Por ocasião da DMA finalizar a transferência das
informações, o controle do barramento retornará ao processador
realizando novamente o procedimento de chaveamento, desativando
a CH2 e ativando a CH1. O fato da CH2 ser desativada não que dizer
que o controlador DMA está desconectado no barramento, mas apenas
não possui privilégio de gerar endereços e certos sinais de controle,
que são emitidos pelo processador.

163
01_SisOps.qxp 11/2/2009 11:36 Page 164

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Conforme já comentado, o controlador DMA possui registradores


que são carregados pelo processador através de software. O primeiro
detém o endereço de memória a ser lido ou escrito. O segundo a
quantidade de bytes (podemos dizer que são palavras) a serem
transferidas.

O terceiro possui o número do dispositivo ou o endereço a ser


usado e o quarto, informa se a informação deve ser lida ou escrita no
dispositivo.

Na Figura 8.5, o dispositivo número 4 precisa escrever em um


bloco de 32 bytes na posição de endereço de memória 100.
O processador logo preenche os primeiros registradores do DMA com
estas informações colocando no último registrador a variável corre-
spondente ao comando de ler ou escrever, que em nosso exemplo será
número 1. O periférico é iniciado com este valor e solicita através de
seu controlador uma requisição ao barramento para que seja executa-
da a leitura do registrador do DMA que armazena a posição da
memória, procedimento este, que até o momento, é similar ao
processador. Tão logo obtenha esta informação, o DMA realiza uma
requisição de E/S ao dispositivo número 4 para que realize a escrita
nesta posição e, ao término desta operação, é incrementado o
registrador de endereço e decrementado o registrador de contagem.
Observando que, se este último, ainda possuir um valor maior do que
0 (zero) deverá ser lido um outro byte da memória e escrito no
dispositivo até que o mesmo chegue ao valor 0 (zero), onde será dado
como finalizado o processo de transferência de informações e gerada
uma interrupção para avisar ao processador. Durante todo este
procedimento o processador apenas participa nas operações de E/S
como responsável por programar a tarefa, preenchendo os
registradores do controlador com os respectivos valores, feito isso,
permanecerá livre para executar outras atividades até que a
transferência seja concluída. Apesar do controlador de DMA
proporcionar certa folga ao processador para realizar estas operações
de E/S, o mesmo ainda não se libera totalmente do processo.

Por exemplo, se um dispositivo de alto desempenho como um


disco, passar a ser gerenciado por DMA, serão necessários vários
ciclos do barramento para controlar as referências à memória bem
como as referências aos dispositivos. Nesta operação o processador
deverá ficar aguardando, haja vista que o controlador de DMA tem

164
01_SisOps.qxp 11/2/2009 11:36 Page 165

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

prioridade mais alta em relação ao processador para acessar o


barramento. Em se tratando de um dispositivo (disco) não serão
tolerados retardos como anteriormente comentado (roubo de ciclos).
Apesar de toda esta situação, é perceptivo um grande ganho por conta
do processador pelo fato de não se preocupar com uma interrupção
por byte (ou palavra) transferida.

8.2 DEADLOCK

Pode ser definido como "Um conjunto de processos está em um


deadlock, se cada processo no conjunto está esperando por um
evento que somente outro processo no conjunto pode causar."
Tanembaum (2002).

Nesta situação os processos estão bloqueados aguardando um


determinado recurso ser liberado, isto é, cada processo do conjunto
está esperando pela liberação de um recurso que está sendo usado por
um processo qualquer e que talvez seja liberado com tanta rapidez,
ocorrendo, desta forma, o deadlock.

De acordo com Tanembaum (2002), para que aconteça um


deadlock é necessário que ocorram 04 (quatro) condições, são elas:
Exclusão Mútua: o recurso ou está associado a um processo ou
está disponível;
Posse e espera: um processo está de posse de um recurso, poden-
do solicitar outros recursos e com isso permanecer aguardando por sua
liberação;
Não existe preempção: um processo possui alguns recursos dados
ao mesmo e não poderão ser tomados de volta, a não ser que sejam
liberados pelo processo; e
Espera Circular: deverá haver uma cadeia circular de processos,
sendo dois ou mais processos organizados em ordem e aguardando o
seu recurso que está de posse do próximo processo desta cadeia
circular.

Sem uma destas situações comentadas acima, não será


considerado que um processo esteja em deadlock. Existem algumas
maneiras de se tratar a ocorrência deste problema, sendo a maneira
mais comum, a de se deixar acontecer, detectando-o e, a partir de
165
01_SisOps.qxp 11/2/2009 11:36 Page 166

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

então eliminá-lo através da destruição do processo e ou da liberação


dos recursos que estão em concorrência.

Por exemplo, existem 03 (três) processos com os seus respectivos


recursos, sendo executados um por vez através do Sistema
Operacional, sempre aguardando a finalização de uma operação para
iniciar a outra, não ocorrendo deadlock.

Figura 8.6: Processos sem Deadlock


Fonte. Sistemas Operacionais Projetos e Implementação, Tanenbaum (2002)

Destarte, para que um determinado processo possa utilizar um


recurso, deverá requisitar, utilizá-lo e logo em seguida, liberá-lo. Se
por ocasião um recurso não estiver disponível quando for requisitado,
o processo é forçado a permanecer aguardando e nesta situação
podem ser tomadas algumas decisões: permanecer bloqueado até que
o recurso seja liberado e então ser acordado, ou ainda, informar ao
processo através de um sinal com uma mensagem de erro indicando
que a solicitação falhou, ficando a cargo do processo a melhor ação a
ser realizada, que poderá ser: solicitar novamente após algum tempo
de espera. Observem que na Figura 8.7 abaixo ocorre uma cadeia
circular de processos e recursos, indicando um deadlock.

166
01_SisOps.qxp 11/2/2009 11:36 Page 167

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 8.7: Processos com Deadlock. Fonte. Sistemas Operacionais Projetos e Implementação,
Tanenbaum (2002)

8.2.1 Prevenção de Deadlock:

Este tópico trata a questão de impor restrições aos processos de


forma que o deadlock não venha a acontecer, negando, para isso uma
das 04 (quatro) condições necessárias para que o mesmo ocorra.
Tanenbaum (2002).

As possibilidades de eliminar estas condições são:

a. Exclusão Mútua:
É proibido o acesso de dois processos ao mesmo recurso de forma
mutuamente exclusiva, bem como, nem sempre poderá ser utilizada a
técnica de spool.

b. Espera por Recursos:


Nesta condição o recomendável seria que todos os recursos
necessários para o processo realizar sua atividade sejam requisitados
167
01_SisOps.qxp 11/2/2009 11:36 Page 168

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

antes de iniciar a sua execução, uma vez que todos estivessem


disponíveis então, ele seria executado, caso contrário, o processo
deverá permanecer aguardando, conseguindo, com isso, negar esta
condição. Nesta situação o problema seria identificar todos os
recursos que os processos iriam necessitar até começar a execução.
Outra tentativa de negar esta condição seria a liberação de todos os
recursos que o processo tivesse, em prol de requisitar um novo
recurso e, quando o conseguisse, poderia resgatar os anteriores de
volta.

c. Não preempção:
Nesta situação não há o que se fazer, pois poderia gerar vários
conflitos por conta de resgatar um recurso que está sendo utilizado
por um processo e disponibilizá-lo para um outro.

d. Espera circular:
Para esta prevenção é necessário apenas impossibilitar que se
fechem ciclos no grafo de recursos. Como seria isto? Fazendo com que
cada processo só possa ter um recurso de cada vez e, caso deseje um
novo, deverá liberar o recurso que esta sendo utilizado para um outro
processo que esteja precisando. Podemos ainda nomear os recursos
em uma ordem padrão a ser seguida ao qual os processos ao
realizarem suas requisições deverão obedecer a esta ordem, o mais
difícil talvez, seja implementar esta ordem padrão a ser seguida e que
atenda as condições de acesso.

8.2.2 Detecção e Recuperação:

O fundamental desta função é o acompanhamento dos processos


através do monitoramento de grafos, de todas as solicitações e
atendimento dos recursos. Para isso temos o Sistema Operacional
como responsável por essa tarefa. Estes grafos são atualizados
frequentemente para observação de possíveis ocorrências de ciclos,
uma vez observada tal ocorrência é necessário que o processo seja
finalizado e assim, sucessivamente, até que o ciclo seja desfeito.

168
01_SisOps.qxp 11/2/2009 11:36 Page 169

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Este procedimento é geralmente implementado em equipamentos


de grande porte para que seja executado em batch, o que permitirá
reiniciar os processos que foram finalizados, sempre tendo o cuidado
de recuperar o arquivo, trazendo-o ao seu estado original. Tanenbaum
(2002).

Mas que providências deverão ser tomadas por ocasião da


detecção de um deadlock? Além de finalizarmos os processos,
precisamos colocá-los novamente em situação de funcionamento
normal, para isso adotando algumas alternativas:

a. Recuperação por meio de preempção:


Trata da retirada de um recurso que está com um processo em
execução e repassá-lo a outro processo que esteja necessitando.

b. Recuperação por meio de reversão de estado:


Prover o armazenamento de imagens dos estados do processo em
execução, para que se possa ter pontos de controle do processo em
suas ações e os recursos que foram utilizados, ressaltando que estas
imagens não sofrem sobreposição pois sempre é criada uma nova
imagem daquele ponto de controle. Isso permite que o processo possa
ser recuperando ao seu estado original após a detecção de um dead-
lock

c. Recuperação por meio de eliminação de processos:


Como o próprio nome sugere, é necessária a eliminação de um
processo envolvido em um deadlock. Mesmo assim, ainda temos a
possibilidade de que alguns processos possam ser capazes de
prosseguir na sua execução, mas poderá acontecer também que haja
a eliminação de processos que não estejam envolvidos no ciclo onde
foi detectado o deadlock. Nesta alternativa precisamos nos ater em
eliminar somente os processos que possam ser reiniciados sem que
ocorram perdas de informações.

169
01_SisOps.qxp 11/2/2009 11:36 Page 170

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.2.3 Evitar Deadlock:

Para se evitar uma ocorrência é necessário fornecer ao Sistema


Operacional todas as informações sobre os possíveis recursos que os
processos irão utilizar em suas execuções, ficando sob sua
responsabilidade o atendimento aos processos sem que para isso
ocorra um deadlock. Com este prévio conhecimento, é possível
analisar e autorizar cada requisição, e definir se o processo poderá
prosseguir ou se deverá permanecer em espera.

Existem alguns algoritmos para ajudar nestes procedimentos, mas


eles necessitam que os processos declarem o máximo de recursos
necessários. Entre estes algoritmos temos o Algoritmo do Banqueiro
que utiliza o preceito de que um processo pode ser executado de
maneira segura ou não. O algoritmo analisará se a soma dos recursos
requisitados é menor que os recursos no momento disponíveis no
sistema e, se caso positivo, o recurso será liberado. Na situação em
que este valor possa levar a um estado não seguro a mesma será nega-
da. A situação de evitar deadlocks é em sua essência impossível, pois
como já comentado, requer informações sobre as solicitações dos
recursos, o que não podemos garantir que serão utilizados.

De acordo com Tanembaum (2002), ainda podemos citar como


procedimento, o Algoritmo da Avestruz como sendo o mais simples a
ser adotado pelo fato de que ao se deparar com uma condição
perigosa, finge que nada está acontecendo, ignorando tal situação.
Apesar do método de ignorar ocorrências não ser uma abordagem
muito viável para o problema destas ocorrências, mesmo assim são
utilizados em vários Sistemas Operacionais por ser uma estratégia de
baixo custo e que oferece baixa probabilidade de ocorrer um
deadlock. Desta forma, é mais viável utilizar métodos mais simples e
“baratos” do que os dispendiosos métodos de prevenir, evitar,
detectar e recuperar estas situações.

170
01_SisOps.qxp 11/2/2009 11:36 Page 171

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.3 DISCOS

Os discos são os dispositivos mais importantes para o Sistema


Operacional, desempenhando um papel fundamental e realizando
tarefas desde o simples armazenamento de informações até mesmo a
implementação de mecanismos complexos, como a memória virtual.

São próprios para o armazenamento de grande quantidade de


informações, tendo com sua composição, um conjunto de lâminas
metálicas produzidas em aço ou alumínio, que se movimentam de
forma circular em torno de um eixo central. Estas lâminas,
atualmente, são em quantidades de até 08 (oito), sobrepostas e
recebem um tratamento com um revestimento de uma camada
magnética que permitirá que as informações sejam gravadas nestas
superfícies, estes locais são chamados de faces dos discos. Para a
realização do procedimento de leitura e gravação nos discos são
utilizados os cabeçotes, sendo um para cada superfície do disco e que
podem se deslocar das bordas até o centro em movimentos de ida e
vinda. Estes discos em conjunto com o eixo central giram a uma
rotação constante, por exemplo, a 5200 rpm (rotações por minuto),
com isso, possibilitando que toda a superfície do disco possa ser
alcançada por seus respectivos cabeçotes. Cada disco possui sua
superfície dividida em trilhas e por consequência radialmente
divididas em unidades denominadas de setores, estes por sua vez
possuem o mesmo tamanho podendo variar entre 512 a 4096 bytes,
sendo considerada a unidade mínima de leitura e gravação em um
disco.

Cada disco é composto ainda por cilindros que nada mais são do
que o conjunto de trilhas de todas as superfícies que estão
devidamente posicionadas à mesma distância do eixo central,
conforme ilustrado na Figura 8.8. Oliveira, R., et. al. (2004).

171
01_SisOps.qxp 11/2/2009 11:36 Page 172

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 8.8: Organização física do disco magnético.


Fonte. Oliveira, R., et. al. (2004).

O controlador do disco é o responsável por proceder ao acesso das


informações nele armazenado, para isso são necessários que sejam
repassados alguns dados que são chamados de CHS - Cylinder, Head,
Sector (cilindro, cabeça, setor), porém, existe outra maneira de
acessar estas informações. Consiste em considerar o disco como um
conjunto de blocos, formados por um ou mais setores, desta forma, é
passado apenas o número do bloco a ser acessado, que será conver-
tido em um endereço físico CHS por um procedimento denominado de
LBA (Linear Block Addressing), numerando os setores de um disco rígi-
do ao invés da tríade cilindro x cabeça x setor.

São observados nos discos os conceitos de formatação lógica e


partições, ambos estão mais relacionados com o sistema de arquivos
do que com o disco propriamente dito. A formatação lógica é a
preparação dos setores para uso pelo Sistema Operacional, além da
inclusão do setor de boot, do diretório raiz e do tipo de sistemas de
arquivo, permitindo que sejam gravadas informações no disco no
formato de arquivos, com permissões para escrever, ler e serem
localizados pelo Sistema Operacional, bem como o particionamento
que nos permite dividir logicamente um disco em vários outros discos
(partes). Oliveira, R., et. al. (2004).

172
01_SisOps.qxp 11/2/2009 11:36 Page 173

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.3.1 Acesso ao Disco

Segundo Oliveira, R., et. al. (2004), para realização desta tarefa
é necessário o posicionamento da cabeça de leitura e escrita no setor
onde se encontram os dados que deverão ser lidos ou escritos. Esse
procedimento do posicionamento do cabeçote demandará certo
tempo, que devererá levar em consideração como o disco está
organizado. Este tempo de acesso é formado por três valores,
conforme exposto abaixo.

Tresposta = Tbusca + Tlatência +Ttransmissão

Para cada um destes valores consideramos que:

a. Tempo de resposta:
É a seleção da trilha (cabeçote) sendo realizada eletronicamente,
perfazendo um tempo zero. Este valor corresponde ao tempo
despendido ao deslocamento dos cabeçotes até o cilindro onde está a
trilha a que será acessada;

b. Tempo latência:
É o tempo despendido pelo cabeçote para se posicionar no início
do setor a ser lido ou escrito. Esse valor também é chamado de
atraso;

c. Tempo de transferência:
É o tempo gasto pela realização da transferência das informações,
sejam, leitura ou escrita, sempre sendo predominante o tempo de
busca. É por este motivo que discos antigos possuem o seu sistema
com cabeçotes fixos, sendo um para cada trilha do disco.

173
01_SisOps.qxp 11/2/2009 11:36 Page 174

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.3.2 Entrelaçamento

Este procedimento está relacionado ao tempo de acesso ao disco,


evitando que os setores sejam numerados de forma contínua e sim
realizando saltos entre eles. Como é muito comum que hajam acessos
a pontos próximos em uma trilha, poderá ocorrer em um determinado
momento a necessidade de leitura de informações em setores que
estejam um ao lado do outro, para isso são encaminhados ao
controlador do disco comandos a serem executados. Após a realização
da busca, por exemplo, setor 1, a cabeça de leitura/escrita passará
sobre o mesmo realizando a sua tarefa e ao sair deste setor as
informações são repassadas do buffer do controlador para a memória.
Esta operação então é considera concluída e é gerada uma mensagem
de interrupção ao processador informando o estado da operação. Este
procedimento é realizado novamente, pois é preciso realizar a leitura
de outro setor, por exemplo, setor 2. O Sistema Operacional deverá
encaminhar um novo comando ao processador, sendo que não será
necessário realizar uma busca, pois a cabeça de impressão já está
sobre o cilindro que se deseja ler. Como o disco permanece em sua
rotação normal, há grande probabilidade da cabeça de leitura/escrita
não está no início do setor, desta forma não sendo possível realizar a
sua tarefa, permanecendo no aguardo que o disco realize a sua
rotação completa para se posicionar no local correto e então começar
a sua leitura ou escrita conforme o comando enviado pelo processador.
Para evitarmos esta situação é comum utilizarmos o entrelaçamento
dos setores, pois nos permite ordenar os setores intercalando-os, con-
forme Figura 8.9. Oliveira, R., et. al. (2004).

Figura 8.9: Trilha com 16 setores e diferentes fatores de entrelaçamento


Fonte. Oliveira, R., et. al. (2004).

174
01_SisOps.qxp 11/2/2009 11:36 Page 175

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Observamos que o disco 1 está ordenado normalmente, sendo o


seu fator de entrelaçamento zero e o disco 2 com o seu fator igual a
dois. Estes fatores não estão relacionados ao numero do disco, mas
sim na quantidade de saltos realizados na seqüência de ordenação dos
setores, isso significa que entre a seqüência normal dos setores são
inseridos dois outros setores.

Esta técnica nos permite que logo após a cabeça de leitura e


escrita, finalizar sua tarefa no setor 1, ele passa sobre os setores 12 e
7 antes de chegar ao início do setor 2. O processador ao mandar o
comando de leitura ou escrita do setor 2, o cabeçote ainda não terá
passado sob o mesmo, permitindo que dois setores contíguos sejam
lidos no mesmo giro do disco.

8.4 RAID (Redundant Array of Independent Disks)

Esta estrutura está relacionada ao armazenamento de grandes


volumes de informação e estas por sua vez, aumentam frequente-
mente com o surgimento de novas tecnologias, o que implica no
aumento da quantidade de discos utilizados. Este aumento nos causa
certa preocupação, pois há probabilidade que um destes discos
apresente problemas físicos e venhamos a perder as informações nele
armazenadas. Caso ocorra esta situação, devemos utilizar um
procedimento para recuperar as informações através de um backup e
que geralmente, apesar de ser realizado periodicamente, não
possuem as versões mais recentes das informações. A função RAID é
gerenciar a combinação de vários discos rígidos em uma estrutura
lógica, de forma a aumentar a confiabilidade e o desempenho dos
discos, bem como uma redundância, permitindo a recuperação de
informações em caso de falha física que possa ocorrer em um disco.
A configuração RAID pode ser realizada através do Hardware, tendo a
capacidade de escrita e acesso, o cálculo de paridade, e a escrita
simultânea em discos. É gerenciada pelo próprio controlador dos
discos, não sendo necessária a ação do Sistema Operacional ou,
através de Software, que há necessidade da ação pelo Sistema
Operacional, sendo as informações a serem escritas particionadas pelo
Sistema Operacional e distribuídas em “partes” entre os vários discos
existentes, provocando uma queda no desempenho e no acesso ao
disco. Silberschatz (2003).
175
01_SisOps.qxp 11/2/2009 11:36 Page 176

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Esta tecnologia consiste em um conjunto de dois ou mais discos


rígidos com duas técnicas que podem ser utilizadas de maneira
isolada ou em conjunto, são elas:

1) Tornar o sistema de disco mais rápido utilizando-se de uma


técnica denominada de divisão de dados. Esta técnica consiste em
fazer com que o computador visualize que dois discos rígidos fazem
parte de um mesmo conjunto, de um só disco maior, e no momento de
gravar um arquivo em disco, o RAID dividirá este arquivo entre os
discos rígidos, sendo esta operação não perceptível ao usuário.
A vantagem desta técnica é que cada parte será gravada nos discos ao
mesmo tempo. Por exemplo: para realizar a gravação de um arquivo
com 500MB em um único disco foi despendido um tempo de 5
segundos; para gravação de um arquivo do mesmo tamanho utilizando
RAID 0 (dois discos rígidos) divido em partes iguais, temos para cada
parte de 250MB um gasto de tempo de 2,5 segundos para realizar a
mesma operação. Como o acesso aos dois discos ocorre de forma
simultânea, o tempo total para acessar o disco passa a ser a metade,
aumentando com isso o desempenho.

A utilização de RAID ajuda bastante, principalmente porque não se


limita a utilização somente dois discos rígidos, mas sim a quantidade
para atender a necessidade prevista. Este procedimento
exemplificado anteriormente, é o mesmo realizado para a utilização
de mais discos, apesar do computador visualizar apenas um disco, o
arquivo será dividido pela quantidade de discos existentes e com isso
o tempo de execução cada vez mais será menor, observando que
quanto mais disco, mais cara será esta solução.

2) Tornar o sistema de disco mais seguro utilizando uma técnica


chamada espelhamento. Esta técnica é conhecida como RAID 1 e
permite que o conteúdo de um disco rígido seja copiado para outro de
forma automática. Caso o disco rígido principal falhe o segundo
entrará em ação automaticamente, isso nos proporcionará certa
redundância. Podemos considerar que o espelhamento é um tipo de
backup que nos fornece segurança, mas que não se pode
descartar o procedimento de backup normal. Por quê? Por uma
fatalidade os dois discos utilizados podem queimar ao mesmo tempo e
com isso perder todas as informações. Embora essa probabilidade seja
muito remota, poderá acontecer. Um dos pontos favoráveis do
espelhamento é o fato de ser implementado por hardware,

176
01_SisOps.qxp 11/2/2009 11:36 Page 177

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

automaticamente pela placa-mãe ou pela placa controladora e o


Sistema Operacional não será necessário para interagir nesta
configuração ou para que o backup seja efetuado.

A divisão de dados e o espelhamento podem ser utilizados em


conjunto, em uma configuração que podemos chamar de RAID 0+1.
Necessitando para isso, de no mínimo quatro discos rígidos.
Esta combinação resultará na divisão de dados sendo usada em dois
discos e aumentando a velocidade, o espelhamento se encarregará de
copiar o conteúdo deste disco para os outros dois discos que servirão
de backup. Silberschatz (2003).

A utilização desta tecnologia se tornou hoje em dia algo mais


simples em virtude das novas placas-mãe que são construídas com o
chip controlador RAID/IDE que permite instalarmos um disco rígido e
configurá-lo através do setup, sem ser preciso um hardware adicional,
coisas que em alguns anos atrás não era possível, sendo necessárias
placas controladoras SCSI e de discos SCSI, que, diga-se de passagem,
são muito caras.

8.4.1 Níveis de RAID

8.4.1.1 RAID nível 0:

Como já comentado, neste nível os arquivos são divididos em


pequenas partes e distribuídos entre os discos existentes. O RAID 0 é
comumente utilizado para melhorar a desempenho de computadores
proporcionando um ganho em velocidade de gravação e de leitura das
informações. Uma vez que o arquivo é distribuído entre os discos,
quão maior quantidade de disco, maior velocidade é alcançada. Mas
como nem tudo é sombra e água fresca, neste nível não é oferecido
tolerância a falhas. Caso venha a acontecer em qualquer um dos
discos rígidos o problema, teremos perda de informações, pois não
existem redundâncias. RAID 0 é também conhecido como "Stripping"
ou "Fracionamento". Silberschatz (2003).

177
01_SisOps.qxp 11/2/2009 11:36 Page 178

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 8.10: RAID 0. Fonte. Próprio Autor

8.4.1.2 RAID nível 1 ou Espalhamento:

Este nível nos fornece a possibilidade de trabalharmos com discos


rígidos em paralelo aos principais existentes no computador e com isso
teremos sempre uma cópia das informações, pois tudo que for
realizado em um disco será espelhado para o outro. Este
procedimento nos garantirá certa segurança em virtude de, se um dos
discos apresentarem problemas o outro imediatamente poderá
assumir a operação e continuar a disponibilizar as informações
solicitadas. O efeito desta técnica é o acesso a leitura de informações
que será bem mais rápido por termos dois locais para serem
acessados, o que não ocorrerá na execução de uma gravação, pois será
realizada sempre duas vezes e com isso se tornando um pouco mais
lenta. RAID 1 é uma aplicação muito comum no uso em servidores de
arquivos. Silberschatz (2003).

Figura 8.11: RAID 1. Fonte. Próprio Autor

178
01_SisOps.qxp 11/2/2009 11:36 Page 179

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.4.1.3 RAID nível 5:

Este nível é também conhecido como faixas de disco com paridade


sendo as informações distribuídas por diversas partes, em três ou mais
discos existentes e estes grupos de partes estarão associadas a uma
paridade. Esta técnica é a mais apropriada para utilização em
sistemas que requerem mais segurança, responsabilidade e que
também necessitem de mais desempenho, devido aos acessos
paralelos nos diversos discos. Quanto mais disco, mais rápido ficará.
A exemplo temos os servidores de banco de dados: o RAID 5 nos
proporciona redundância caso tenhamos uma falha em um dos discos,
onde poderemos utilizar a paridade para recuperação das informações
que estejam faltando.

Este é o nível mais utilizado, pois nos oferece resultados


satisfatórios, sendo sempre necessários, para isso, pelo menos 03
(três) discos rígidos para sua implementação, porque o seu
aproveitamento é observado da seguinte maneira: para cada 03 (três)
discos rígidos, teoricamente se perde 1 (um)

Exemplo: 3 discos de 200GB = 400GB. Silberschatz (2003).

Figura 8.12: RAID 5. Fonte. Próprio Autor

179
01_SisOps.qxp 11/2/2009 11:36 Page 180

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

8.4.1.4 RAIDs 2, 3, 4:

Estes níveis quase nunca são implementados apesar de fazerem


parte dos níveis, tendo em vista, que a projeção e criação no nível 5
foi totalmente baseada no conjunto das técnicas destes 03 (três)
níveis.

O RAID 2 por sua vez se adapta ao procedimento de detecção de


falhas em discos rígidos e, para funcionar em memória, desta forma
monitorando todos os discos da matriz. Esta técnica não está mais
sendo usada pelo fato de todos os discos rígidos atualmente já
possuírem um mecanismo de detecção de falhas implantados.
No RAID nível 3, as informações são divididas entre os discos da
matriz, onde apenas um permanecerá de fora porque será
responsável por armazenar informações de paridade. Cada informação
será possuidora de sua paridade, sendo acrescido de 1 bit, este que
possibilitará a identificação dos erros. Esta técnica nos oferece altos
níveis de transferências de informações e a confiança do seu
processo. E por fim, o RAID nível 4, com certa semelhança ao RAID 3
sendo que, em caso de falha de um dos discos, as informações podem
ser reconstruídas em tempo real através da utilização da paridade
calculada a partir dos outros discos, onde cada um pode ser
acessado de forma independente. O RAID 4 é o mais indicado para o
armazenamento de arquivos grandes, onde é necessário assegurar a
integridade das informações e cada operação de gravação requer um
novo cálculo de paridade, dando maior confiabilidade ao
armazenamento. Silberschatz (2003).

8.4.1.5 RAID 6:

É uma técnica com recursos do RAID 5 e com funções especiais,


mas que não foi previsto no projeto inicial, tendo a característica de
armazenar as paridades por duas vezes em cada disco diferente, isso
nos permite a possibilidade de ocorrer a parada de até dois discos ao
mesmo tempo. É um padrão novo que no momento é suportado
apenas por algumas controladoras e que podemos exemplificar da
seguinte forma: se utilizarmos 05 (cinco) discos rígidos com
capacidade de 250 GB, implementando o RAID 6, teria espaço para
180
01_SisOps.qxp 11/2/2009 11:36 Page 181

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

armazenamento das informações somente 750 GB, pois seria preciso


para as paridades um espaço de 500 GB. Silberschatz (2003).

Figura 8.13: RAID 6. Fonte. Autor desconhecido

8.5. Entrada e Saída no Linux

Neste Sistema Operacional o procedimento de entrada e saída é


implementado através de device drivers, que são comandos de um dis-
positivo ou programa para criação de uma interface de comunicação
do Sistema Operacional com o dispositivo do hardware, no qual cada
dispositivo possui o seu próprio device drivers que é acoplado ao
sistema operacional quando o kernel é gerado e sempre que um novo
dispositivo é adicionado ao sistema. O acesso aos dispositivos é
através de arquivos especiais que são localizados no diretório “/dev”,
conforme tabela abaixo.

181
01_SisOps.qxp 11/2/2009 11:36 Page 182

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Tabela 8.1:Diretórios

Obs. Para os discos é adicionado um número inteiro concatenado


ao dispositivo que indica a partição.

No Linux, todas as operações de entrada e saída são realizadas


como uma sequência de bytes, o que não se exige um conceito de
registro ou métodos de acesso, com isso as system calls de entrada e
saída podem manipular qualquer tipo de dispositivo de maneira
uniforme, o que nos permitem acessá-los da mesma forma que
qualquer outro arquivo, simplesmente através das system calls de
leitura e ou gravação. Este Sistema Operacional utiliza dois tipos de
operações de entrada e saída, sendo elas:

• Orientada a blocos, que estão ligadas aos dispositivos com altas


taxas de transferência, como discos, tendo como objetivo
minimizar o número de transferências entre o dispositivo e a
memória, para isso utilizando buffers.

• Orientada a caractere, que estão interligadas normalmente aos


dispositivos com baixa taxa de transferência, como terminais,
onde esta taxa fica entre o dispositivo e a memória, sendo
realizada de caractere a caractere.

182
01_SisOps.qxp 11/2/2009 11:36 Page 183

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Através de um redirecionamento de entrada e saída o usuário


poderá redefinir o comando ou programa que receberá a entrada, e
para onde será enviada a sua saída; estas informações poderão ser de
um arquivo do próprio Sistema Operacional, de terminal, da saída de
outro comando ou de um arquivo especificado pelo próprio usuário.
Esta saída será o resultado da operação realizada sobre o comando
solicitado na entrada tendo a sua saída impressa na tela do terminal,
enviada a um arquivo, ou ainda, servir como entrada para outro
comando a ser executado.

Os comandos no Linux geralmente requerem uma entrada que


necessitará de um arquivo, e consequentemente de uma saída a fim
de expor os resultados. Quando nenhum arquivo é especificado, a
Shell que é a interface responsável por interpretar os comandos
fornecidos pelo usuário, admitirá que o teclado seja sua entrada, pois
o mesmo é considerado como o dispositivo de entrada padrão e há
necessidade de se exibir um resultado onde a Shell admitirá que o
monitor é a sua saída padrão do sistema.

183
01_SisOps.qxp 11/2/2009 11:36 Page 184

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

184
01_SisOps.qxp 11/2/2009 11:36 Page 185

CAPÍTULO 9

Arquivos

O arquivo é a parte do Sistema Operacional mais perceptível aos


usuários, pois o armazenamento e a recuperação de informações são
atividades essenciais para qualquer tipo de aplicação. Todo processo
deverá ser capaz de ler e gravar grande volume de informações em
dispositivos como, discos rígidos, cd’s, dvd’s, fitas, de forma
contínua permitindo compartilhá-los. Estes arquivos são
frequentemente manuseados pelos usuários e geralmente contêm
informações como textos, planilhas, apresentações, etc. Esse fato
exige que o sistema de arquivos possua estruturas que aperfeiçoem os
acessos ao disco gerados por estes manuseios destes arquivos. O
Sistema Operacional entra nesta tarefa controlando as operações
sobre os arquivos e organizando o armazenamento destas informações
no sistema de arquivos, este por sua vez possui características como:

•O método de acesso com que as informações serão acessadas nos


arquivos;
•O gerenciamento de arquivos, como sendo o conjunto de
procedimentos realizados para o armazenamento, a referência,
o compartilhamento e a segurança dos arquivos;
•O mecanismo de integridade para assegurar que as informações
de um arquivo permanecem completas, sem perdas.

185
01_SisOps.qxp 11/2/2009 11:36 Page 186

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

9.1 Tipos de Arquivos

Os arquivos são utilizados como um local para armazenar


informações, ao qual os usuários poderão, conforme sua necessidade
dispor de várias informações em um só arquivo. Para isso é necessário
que haja uma identificação deste arquivo sendo um nome sugestivo
que faça referência ao conteúdo nele armazenado. Com isso o Sistema
Operacional se encarrega de incorporar vários outros
atributos para que o sistema de arquivo possa gerenciá-lo. Entre estes
atributos podemos citar o tipo de conteúdo armazenado, data e hora
que foi acessado e ou alterado, tamanho do arquivo, etc.

Tabela 9.1: Atributos dos arquivos


Fonte. Tanenbaum 2002

A partir da criação do arquivo poderemos realizar varias operações


desde que o usuário tenha permissões para isso, são elas: leitura,
alteração e ou escritas, apagar o arquivo, execução de algum
programa contido no arquivo, trocar o nome do mesmo, bem como
alterar as permissões dos usuários que podem acessar os arquivos.
A maneira como as informações são organizadas dentro de um arquivo
determina como é sua estrutura interna e com isso existe uma enorme
quantidade de diferentes tipos de arquivos, sendo que cada tipo
possui sua estrutura interna particular.

186
01_SisOps.qxp 11/2/2009 11:36 Page 187

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Para o Sistema Operacional, cada arquivo corresponde a um con-


junto de bytes agrupados que podem ser armazenados e recuperados,
podendo ser texto ou programas executáveis, cuja estrutura interna é
definida pelo Sistema Operacional.

Todo arquivo recebe um nome e é gerenciado através dele e,


dependendo do Sistema Operacional, as letras maiúsculas e
minúsculas podem ser interpretadas de maneira diferente e os
procedimentos para o manuseio dos arquivos também podem variar.
Os Sistemas Operacionais visualizam os arquivos como duas partes,
nome e extensão, que são separadas por um ponto (“.”). A extensão é
que usualmente indica o propósito ou o tipo do arquivo:

Tabela 9.2: Tipos de arquivos. Fonte. Tanenbaum 2002

187
01_SisOps.qxp 11/2/2009 11:36 Page 188

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

9.2 Sistemas de Arquivo

Podemos perceber a existência de um padrão de organização e


controle do armazenamento dos arquivos em um sistema
computacional. O Sistema Operacional pode suportar diversos sis-
temas de arquivos, podendo utilizar diferentes maneiras de
administrar os arquivos, sejam elas no sentido de armazenamento e
de recuperação. Abaixo ilustramos os diversos sistemas de arquivo e
os respectivos Sistemas Operacionais que os suportam.

Tabela 9.3: Tipos de Sistemas Operacionais e Sistemas de Arquivos.


Fonte. Tanenbaum 2002

Como foi observado, existem diversos tipos de sistemas de


arquivos, e descreveremos alguns a seguir:

188
01_SisOps.qxp 11/2/2009 11:36 Page 189

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

FAT (FILE ALOCATION TABLE)

É o sistema de arquivos usado pelo MS-DOS e em Windows para


organizar e gerenciar arquivos, sendo uma estrutura de dados que o
Windows cria por ocasião de uma formatação de um volume usando os
sistemas de arquivos com FAT16 ou FAT32. As informações são
armazenadas na FAT para que possam ser recuperadas posteriormente.

FAT 32 (FILE ALOCATION TABLE – 32 BITS)

Este padrão é utilizado pelos Sistemas Operacionais Windows 98 e


Windows 2000, pois possuem 32 bits para endereçamento, permitindo
clusters de até 4 KB para partições maiores que 2 GB. O FAT 32
suporta uma partição de até 2 Terabytes, sendo que partições que
apresentem o seu tamanho superior à 16 GB, apresentam problemas
de desperdício de espaço.

Os nomes de arquivos podem ter mais do que 8 e chegando até 255


caracteres e suas extensões poderão ter até 255 caracteres de
tamanho.

Para este padrão de sistemas de arquivo, podemos ter alguns


problemas como já citado a questão de desperdício de espaço, sendo
um sistema que não oferece muita segurança por causa de sua
instabilidade e pelo fato de termos clusters perdidos, os arquivos
podem ser facilmente corrompidos, o que implicariam em perda na
continuidade do arquivo.

NTFS (NEW TECHNOLOGY FILE SYSTEM)

Este sistema de arquivos é utilizado em todas as versões do


Windows NT, sendo que no seu primeiro momento era mais utilizado
na implementação de servidores. As principais características do NTFS
são:

189
01_SisOps.qxp 11/2/2009 11:36 Page 190

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

1– Journaling é um recurso que ajuda a manter a integridade dos


dados em caso de erros no sistema causados por desligamento
incorreto ou determinadas falhas de hardware e ainda permitir
que o sistema possa se recuperar rapidamente sem precisar veri-
ficar a integridade do sistema de arquivos.
2– O controle de acesso dos arquivos pelos seus usuários, utilizan-
do permissões para que isso ocorra.
3– A compressão de arquivos.
4- Encriptação transparente de arquivos.
5- Quotas que permitem aos administradores definirem a quanti-
dade de espaço em disco que cada usuário pode utilizar.
6– Permitir que o tamanho dos clusters sejam do mesmo
tamanho de um setor, por exemplo 512 bytes, permitindo, com
isso, um bom uso do espaço para Discos Rígidos pequenos e uma
boa performance para os maiores.
Neste sistema podemos utilizar o endereçamento 64 bits,
transformando cada cluster do disco rígido em partes de 512 bytes e
com isso, podendo ter até 255 caracteres de nome, e até 255
caracteres de tamanho para a extensão.

O NTFS em relação ao FAT não apresenta problemas de


desperdício de espaço, é mais seguro por ser estável e mais
performático.

EXT2 (SECOND EXTENDED FILE SYSTEM)

É um sistema de arquivos de disco de alto desempenho usado pelo


Linux para dispositivos de armazenamento, como discos rígidos e
mídias removíveis. Este sistema foi elaborado como uma extensão de
EXT, para oferecer o melhor desempenho entre todos os sistemas de
arquivos suportados pelo Linux, para isso tendo certo ganho com a
velocidade e uso da CPU e se tornando um sistema de arquivos muito
rápido. É utilizado pela maioria das distribuições Linux, suportando
até 4 Terabytes de partições e até 255 caracteres de nomes de
arquivos.

190
01_SisOps.qxp 11/2/2009 11:36 Page 191

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

EXT3 (THIRD EXTENDED FILE SYSTEM)

Este sistema é uma nova geração para gestão de arquivos do


Linux, tendo como sua maior vantagem o suporte de journaling. Esta
função se dá por um arquivo denominado “.journal” que atua oculta-
mente na partição através do código do EXT3 e com isso não poderá
ser deletado, pois se isto acontecesse comprometeria o
funcionamento do Sistema. O Journaling possui três modos de
trabalho. São eles:

Journal: permite a gravação de todas as alterações ocorridas no


sistema de arquivos e possui uma maior capacidade de evitar possíveis
perdas de informações, sendo o modo mais seguro, porém, entre os
outros modos é considerado o mais lento de todos;

Writeback: armazena apenas informações referentes à estrutura


do sistema de arquivos (metadata) e não em relação aos arquivos
propriamente ditos, e é gravado de forma mais ocasional,
aproveitando os momentos de inatividade. Este modo é o mais rápido,
mas em compensação, oferece uma segurança muito menor contra
perda e corrompimento de arquivos causados pelos desligamentos
incorretos.

Ordered: se parece com o writeback, porém força que a escrita


do conteúdo dos arquivos seja realizada após a marcação de seus
metadados como escritos no modo journal. Este modo é considerado
como padrão a ser utilizado pelo EXT3, por ser aceitável entre
confiabilidade e performance em relação aos demais. Mas é possível
especificar qual o modo que o usuário deseja utilizar. Através da
atualização de um arquivo denominado “fstab”, este arquivo
armazena as configurações de quais dispositivos devem ser montados
e qual o ponto de montagem de cada um na inicialização do sistema
operacional, contendo a descrição dos vários sistemas de arquivos.

O EXT3 possui uma estrutura parecida com a EXT2, o que o torna


mais fácil no momento de realizar manutenções no sistema, pois todas
as ferramentas para recuperação EXT2 funcionarão perfeitamente sem
problemas, o que nos permite montar uma partição EXT3 como se
fosse uma partição EXT2.

191
01_SisOps.qxp 11/2/2009 11:36 Page 192

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Estes dois últimos sistemas descritos fazem um grupo de outros


sistemas utilizados no Linux, como por exemplo: o ReiserFS, XFS, JFS
entre outros. Mesmo assim o EXT3 continua sendo o sistema de
arquivos mais utilizado pelo Linux, pois atende bem as necessidades.
As suas funcionalidades foram bem avaliadas e testadas, colocando-o
em um estado bastante estável em relação aos outros sistemas. Como
a tecnologia avança com certa velocidade, aprimorando cada vez mais
as já existentes, baseando nos seus erros e falhas, bem como, nas
necessidades surgidas e que não foram possíveis solucionar, já está em
teste a versão EXT4 que irá substituir o EXT3.

9.3 Acesso a Arquivos

A forma com que os arquivos são acessados para visualização de


seu conteúdo é chamada de Método de Acesso. Este procedimento é
realizado pelo usuário para executar procedimentos de
leitura/escrita em um arquivo. Dentro deste método de acesso
podemos utilizar o acesso sequencial, que permite que o conteúdo do
arquivo possa ser lido em uma ordem sequencial tendo suas
informações processadas, um registro após o outro, ou utilizar o
acesso relativo, que permite adicionar a uma chamada ao sistema a
localização a ser lida/escrita em um arquivo. Esta localização é uma
seqüência numérica, contada a partir de 0 (zero) ou 01(um),
dependendo do sistema e, sendo que esta posição no arquivo, corre-
sponde a um byte. Podemos observar ainda, que em alguns Sistemas
Operacionais é utilizado o conceito de localização corrente no
arquivo, que trata a execução de uma tarefa de leitura/escrita em
arquivo sem que seja necessário informar a posição. Nesta situação a
operação sempre acontecerá a partir da sua posição corrente.
Tanembaum (2002).

O controle de acesso são os procedimentos utilizados para


garantir a integridade e a segurança dos arquivos a serem acessados
pelos usuários. Nada mais são do que listas de controle que constem
as relações de usuário com os seus respectivos perfis de direito e as
operações específicas que poderão ser realizadas sobre um
determinado arquivo. Tais direitos são as permissões para leitura,
escrita ou execução. Podemos citar como exemplo, o Linux que utiliza
uma lista de acesso baseada no conceito de grupos que possuem
192
01_SisOps.qxp 11/2/2009 11:36 Page 193

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

determinadas permissões e estas estão associadas a todos os arquivos.


Estas permissões estão diferenciadas em 03 (três) níveis, que são as do
dono do arquivo, do grupo ao qual pertence o seu dono e dos demais
usuários. Estes níveis por sua vez podem individualmente receber
especificações como permissões para leitura, escrita e execução,
desta forma, podemos observar que o resultado deste procedimento é
que, quando combinadas, nos proporcionam diferentes modos de
acessar os arquivos. Silberschatz (2003).

Os arquivos armazenam diversos tipos de informações e estes por


sua vez poderão ser entendidos como de um determinado tipo, como
por exemplo: textos, executáveis e etc. Os arquivos possuem uma
referência ao conteúdo que o identifica junto ao determinado
aplicativo, esta é chamada de extensão. Essa associação é
normalmente utilizada pelos Sistemas Operacionais para facilitar a
vida do usuário por ocasião de acesso a um determinado arquivo.
Existem dois grupos ao quais os arquivos podem ser divididos e que são
classificados como do tipo alfanuméricos, por serem arquivos que
possuem apenas caracteres definidos por um código ASCII.
A interpretação destes arquivos alfanuméricos é realizada por
intermédio de editores de programas, pois nestes arquivos os bytes
são interpretados como letras ou números; um arquivo gerado pelo
Bloco de Notas é um exemplo de um arquivo alfanumérico. Já o
arquivo do tipo binário tem em seu conteúdo, informações não tão
facilmente reconhecidas quando aberto por um editor de texto, pois
ele precisará ser interpretado por uma aplicação para poder ser
visualizado. Estes arquivos podem conter qualquer tipo de caractere
onde os seus bytes são interpretados como códigos ou instruções pelo
Sistema ou por um determinado Aplicativo. Neste grupo de arquivos
estão enquadrados como executáveis, que é realizada diretamente
pelo Sistema Operacional. Silberschatz (2003).

Em sistemas de arquivo o fator segurança é uma preocupação


constante que devemos ter em prover mecanismos para proteção do
sistema e ao acesso a seus serviços, pois um acesso indevido ao seu
núcleo poderia ocasionar danos, comprometendo todo o sistema e
tornando-o inoperante. Para evitar estes tipos de problemas, o sis-
tema de arquivos disponibiliza um conjunto de procedimentos a serem
utilizados pelos aplicativos quando desejarem solicitar algum serviço
ao Sistema Operacional, para isso utilizará chamadas as suas rotinas
através dos procedimentos denominados de System Calls que
permitem às aplicações realizarem operações de E/S, como tradução
193
01_SisOps.qxp 11/2/2009 11:36 Page 194

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

de nomes em endereços, leitura e gravação de dados e


criação/eliminação de arquivos. A tabela abaixo apresenta algumas
System Calls encontradas na maioria dos sistemas de gerenciamento
de arquivos. Silberschatz (2003).

Tabela 9.4: Funções – System Calls. Fonte. Silberschatz (2003).

Por intermédio das informações fornecidos na system call, é


realizada uma chamada a qual é processada e ao seu término é
gerada uma resposta que será encaminhada a quem solicitou e, junto
a esta resposta, irá um estado de conclusão que informará o
resultado da operação realizada com sucesso ou não. Estes conjuntos
de procedimento estão associados aos serviços disponibilizados pelo
Sistema Operacional através de suas bibliotecas e, para cada serviço
existe um System Call que nada mais é do que a porta de entrada para
acesso ao núcleo do Sistema Operacional.

Figura 9.1: Esquema - System Call


Fonte. Silberschatz (2003).

194
01_SisOps.qxp 11/2/2009 11:36 Page 195

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

9.4 Operações com Arquivos

Existem várias maneiras de realizar operações com arquivos, como


já comentado, os arquivos armazenam conteúdos e nos permitem
recuperá-los sempre que necessário através de diversos sistemas que
nos oferecem tais procedimentos. Tanembaum (2002). Como ilustrado
na Figura 9.6 Funções – System Calls, iremos descrever algumas dessas
operações.

Criação de arquivo - Realização de uma chamada ao sistema


comunicando a criação de um arquivo e a definição de seus atributos
e controles de acesso, que por sua vez não possui qualquer informação
neste momento inicial.

Abrir arquivo - Antes de acessar o conteúdo do arquivo é


realizada uma chamada ao sistema permitindo que os dados do
arquivo (atributos, controle de acesso e endereços) sejam repassados
à memória principal e com isso permitindo em solicitações futuras que
este arquivo possa ser aberto com mais rapidez. A abertura deste
arquivo se dará sempre por um processo.

Ler um arquivo - “Os dados são lidos do arquivo. Normalmente,


os bytes provêm da posição atual. O chamador deve especificar
quantos dados são necessários e também deve oferecer um buffer
onde colocá-los.” Tanembaum (2002).

Escrever em um arquivo - Todas as alterações realizadas no


arquivo serão gravadas partir da posição atual onde foi acessado. Caso
as alterações estejam sendo feitas no final do arquivo, este poderá
aumentar de tamanho, caso contrário estas alterações poderão estar
sobrescrevendo o conteúdo existente.

Fechar um arquivo - Por ocasião do encerramento das alterações


de arquivo, o processo deverá liberar todos os recursos utilizados
(atributos, controle de acesso e endereço), com isso criando espaços.
Para alguns sistemas existem algumas restrições quanto à quantidade
de arquivos abertos por processos, o que ocorrerá o fechamento de
determinados arquivos e então a gravação do mesmo será conforme o
procedimento em disco que é em blocos, acontecendo em algumas
situações que estes blocos não estarão totalmente cheios.
195
01_SisOps.qxp 11/2/2009 11:36 Page 196

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Renomeação de arquivos - Este procedimento permite a


alteração do nome do arquivo conforme as necessidades do usuário.
Há momentos que, ao invés de renomear o arquivo, o usuário poderá
fazer um cópia deste arquivo dando um novo nome a ele e apagar o
anterior.

Apagar um arquivo - Esta chamada ao sistema se enquadra ao que


foi dito anteriormente, caso o arquivo não tenha mais serventia ao
usuário, o mesmo poderá apagá-lo do sistema e com isso estará
liberando espaço em disco.

9.5 Implementando o Sistema de Arquivos

Segundo Tanenbaum (2002), o fator primordial para o Sistema de


Arquivos em sua implementação e armazenamento é o controle dos
blocos do disco que estarão associados ao arquivo. Os Sistemas
Operacionais utilizam vários métodos e iremos descrever sobre alguns
como: Alocação Contígua, Alocação Encadeada e Alocação Indexada.

Alocação contígua é o armazenamento de arquivo em blocos em


uma forma sequencialmente disposta no disco, o que nos facilita
identificar a localização do arquivo por intermédio do endereço do
primeiro bloco e suas continuações sequenciais. As vantagens deste
procedimento é o fato de podemos monitorar sua implementação,
localizando os blocos em seus endereços iniciais e como estão em uma
sequência, temos um grande desempenho na leitura do arquivo em
uma só execução. As desvantagens seria o fator do desconhecimento
do tamanho do arquivo, o que tornaria este método inadequado, pois
não teríamos como proceder à reserva de espaço livre em disco para
novos arquivos, que deve ser contígua. E também a questão da
fragmentação do disco que desperdiça um espaço desnecessário que
poderia ser utilizado de outra forma, sem contar que o procedimento
de compactação é um tanto dispendioso e demanda certo tempo,
mesmo que este possa ser realizado em um período em que não haja
atividades, como por exemplo, à noite. Tanenbaum (2002).

196
01_SisOps.qxp 11/2/2009 11:36 Page 197

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Alocação encadeada é a organização dos arquivos como um


conjunto de blocos que estão ligados ao disco independente de sua
localização física. Esta ligação é realizada através de ponteiros onde
cada palavra inicial do bloco servirá como ponto de interligação para
o bloco seguinte. Não há problemas com relação ao processo de
fragmentação neste método, pois os blocos não precisam estar em
uma ordem contígua. Os arquivos são divididos em várias partes e esta
divisão aumenta o tempo de acesso, pois este tipo de alocação só se
permite acesso sequencial aos blocos do arquivo, sendo esta uma das
principais desvantagens desta técnica. Outra desvantagem é a perda
de espaço nos blocos com o armazenamento dos ponteiros.
Tanenbaum (2002).

Figura 9.2: Lista Encadeada de bloco em disco


Fonte: Tanenbaum (2002).

Alocação indexada é a técnica responsável por solucionar a


questão da limitação da alocação encadeada em relação ao acesso.
Isto é possível colocando todos os ponteiros de todos os blocos do
arquivo em uma estrutura única, que podemos chamar de tabela de
índice. Este procedimento para alocação, além de permitir acesso
direto aos blocos, não utiliza informações de controle nos blocos de
dados, o que nos permite ter mais espaço para informações.
Tanenbaum (2002).

197
01_SisOps.qxp 11/2/2009 11:36 Page 198

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 9.3: Lista Encadeada utilizando tabela na memória principal


Fonte. Tanenbaum (2002).

Nó-I é o último método utilizado para controlar os blocos de cada


arquivo, onde é adicionado em cada arquivo uma pequena tabela que
podemos chamá-la de nós - índice, esta contém os atributos e os
endereços dos blocos físicos alocados ao arquivo da seguinte forma: Os
endereços iniciais de cada disco são armazenados no próprio nó-i, esta
informação é transferida do disco para a memória quando o arquivo é
aberto, no caso de arquivos que tenham tamanhos maiores, é
necessário que o nó-i seja expandido, passando a ser chamado de
bloco indireto simples e assim sucessivamente. Conforme a
necessidade de aumento desta tabela de informação, sendo esta
denominada de bloco indireto duplo e bloco indireto triplo, pois
possuirão dentro de sua estrutura as informações dos outros níveis de
blocos. Esta estrutura nos permite ramificações em até o terceiro
nível, conforme ilustra a figura a seguir. Tanenbaum (2002).

198
01_SisOps.qxp 11/2/2009 11:36 Page 199

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 9.4: Lista – Nó-I


Fonte. Tanenbaum (2002).

199
01_SisOps.qxp 11/2/2009 11:36 Page 200

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

9.6 Diretórios

São pastas criadas no sistema para guardar determinados


arquivos. Sendo uma estrutura que armazena as entradas associadas
aos arquivos, estas pastas contêm informações sobre nome, atributos,
localização dos arquivos. Sempre o Sistema Operacional verifica uma
entrada na estrutura de diretórios quando um arquivo é aberto e
procederá ao armazenamento das informações dos atributos e da
localização do arquivo na memória principal. Estas informações ficam
em uma tabela que controla todos os arquivos abertos. O diretório é
a forma com que o usuário organiza seus documentos, separando-os
conforme as suas necessidades e conforme o tipo de arquivo.
Silberschatz (2003).

Os diretórios podem ter vários níveis e o mais simples deles, o


Nível Único é onde ficam armazenados todos os arquivos. Este nível se
torna um pouco restrito, pois não é permitida a criação de mais de um
arquivo com o mesmo nome e ainda, desta estrutura única poderá
ocorrer um estado de inoperância do sistema em virtude de usuários
terem solicitado arquivos iguais ao mesmo tempo, porém,
atualmente, esta situação quase não ocorre mais, pois o usuário que
acessá-lo por primeiro é que terá os direitos de alteração deste
arquivo, já o segundo usuário apenas poderá visualizá-lo.

Para a solução deste problema de restrições para os usuários em


relação aos arquivos em um mesmo diretório, foi implementado um
nível onde além do diretório principal com todos os arquivos do
sistema, também existiria um diretório para cada usuário, o que
permitiria a manipulação dos arquivos sem que houvesse algum tipo
de conflito. Silberschatz (2003).

200
01_SisOps.qxp 11/2/2009 11:36 Page 201

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

9.6.1 Estrutura de Diretórios

Com tantos arquivos em um sistema e a criação de diretórios e


subdiretórios, é necessário que exista um procedimento que organize
de forma lógica toda esta estrutura com entradas que estejam
relacionadas aos arquivos e desta forma nos informando quanto ao seu
nome, atributos, organização e localização. Tanenbaum 2002.

Esta estrutura está dividida basicamente em níveis que iremos


descrever a seguir:

Como já comentado anteriormente, o Nível Único contempla


todos os arquivos de um disco. Esta sua estrutura o torna limitado não
permitindo a criação de arquivos com o mesmo nome.

Figura 9.5: Único diretório compartilhado por todos os usuários.


Fonte. Tanenbaum 2002

Diretório pessoal é uma evolução do Nível Único. Este nível serve


como um diretório principal que contém todos os outros arquivos do
sistema, bem como, os diretórios individuais de cada usuário.
Podemos citar como vantagem deste nível, o fato de que o usuário
possui o total controle sobre os seus arquivos, não tendo restrições e
nem preocupações quanto ao nome do arquivo a ser criado em relação
aos já existentes no sistema.

201
01_SisOps.qxp 11/2/2009 11:36 Page 202

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Figura 9.6: Um diretório por usuário. Fonte. Tanenbaum 2002

E por último o Método de Árvore, que nos permite ter vários


níveis. São frequentemente utilizados nos Sistemas Operacionais, pois
os usuários conseguem criar vários níveis de diretórios ou até mesmo
subdiretórios. Neste nível o usuário poderá criar os diretórios que
necessitar, dividindo-os nos níveis que deseja, pois um diretório
poderá além de ter arquivos, ter outros diretórios (subdiretórios),
sendo estes todos identificados e localizados em sua estrutura através
de um caminho único. A Figura 9.7 ilustra esta organização.

Figura 9.7: Árvore Arbitrária por usuário. Fonte. Tanenbaum 2002

202
01_SisOps.qxp 11/2/2009 11:36 Page 203

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

9.7 NFS - Network File System

A Empresa Sun Microsystems desenvolveu este sistema para, em


um primeiro momento, ser utilizado em suas plataformas baseadas no
Unix, mas atualmente ele é utilizado em implementações em quase
todos os Sistemas Operacionais. Este procedimento permite que um
conjunto de clientes e servidores possa de uma maneira simples
compartilhar um sistema de arquivos entre vários usuários em comum
e com isso, permitindo que o acesso seja ao mesmo tempo por um
cliente com acessos a arquivos remotos ou um servidor que esteja
realizando uma exportação de arquivos. O NFS nos permite montar
partições ou diretórios remotos, garantindo que sejam especificadas
diferentes permissões a cada cliente de acesso ao compartilhamento
dos arquivos. Tanenbaum (2002).

9.7.1 Funcionamento

O NFS é implementado para disponibilizar o acesso remoto a


diretórios e seus arquivos através de redes, sejam elas locais ou
metropolitanas. Este procedimento permite que usuários e ou
programas possam ter acesso ao conteúdo de um servidor de arquivo,
como se estivesse acessando-o em sua própria máquina, sem que haja
certa preocupação quanto ao armazenamento e backup dos seus
arquivos. Silberschatz (2003).

Segundo Silberschatz (2003), o NFS nos proporciona o


compartilhamento entre esses sistemas de arquivos de forma
transparente, onde teremos equipamentos com sistemas de arquivos
independentes conectados, dando uma visão de ser um só sistema e
esta facilidade se dá pelo fato do mesmo ser projetado para executar
em ambientes de diferentes máquinas, sendo que esta possibilidade se
dá pelo uso de RPC, que são primitivas baseadas sobre o protocolo XDR
(External Data Representation) utilizadas entre interfaces
independentes.

Esta sua independência é quanto ao Sistema Operacional, aos


protocolos de rede, possibilitando que usuários do Sistema
Operacional Windows possam tem acesso a servidores Unix/Linux. Nos
203
01_SisOps.qxp 11/2/2009 11:36 Page 204

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Sistemas Operacionais baseados em Unix/Linux, é utilizado para esta


comunicação o VFS (Virtual File System), que justamente ocultará
todas as diferenças entre os sistemas de arquivos por ocasião de uma
operação de acesso aos arquivos. Quando esta solicitação é
direcionada à interface VFS são automaticamente encaminhadas ao
sistema de arquivos local ou para o cliente NFS que se encarregará
pelo acesso aos arquivos dos servidores através das chamadas de
procedimentos remotos, conforme ilustra a Figura 9.8. Tanenbaum
(2002).

Figura 9.8: Funcionamento - NFS – Ambiente Linux.


Fonte. Silberschatz, Galvin and Gagne – 2005.

Este sistema trabalha em sua versão simples com o protocolo de


transporte UDP, apesar de ambos não tratarem a questão de segurança
e controle, mesmo assim o NFS faz a sua própria seqüência de
montagem e desmontagem do sistema, bem como a sua verificação de
erros. Atualmente empresas trabalham disponibilizando versões que
contemplam o NFS utilizando o protocolo TCP, permitindo certa
segurança e controle em suas execuções. Apesar disto existem vários
benefícios que podem ser utilizados como:

• A redução de armazenamento de conteúdo em um ambiente


local, sendo realizadas cópias deste conteúdo em um servidor na
rede e sem comprometer o funcionamento do sistema;

204
01_SisOps.qxp 11/2/2009 11:36 Page 205

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

• A manutenção do sistema, pois a atualização do conteúdo é


realizada de forma centralizada, sem atividades e em locais diver-
sos. E com isso o usuários sempre terão o arquivo atualizado e
disponível na rede e em várias máquinas;

• Para toda a operação realizada pelo usuário - seja para copiar,


ler, mover ou apagar arquivos dentro de um diretório - não é
necessário o usuário ter conhecimentos em comandos específicos,
desde que tenha permissões para tal. O sistema NFS fornece um
conjunto de protocolos de chamadas para operações de acesso a
arquivos remotos, estas operações tratam dos seguintes procedi-
mentos: Realizar busca de determinado arquivo em um diretório,
realizar a leitura de entradas em um determinado diretório, tra-
balhar os links e diretórios, realizar o acesso, verificar os atribu-
tos dos arquivos e realizar as tarefas de ler e escrever arquivos.
Silberschatz (2003).

O NFS em suas versões anteriores não ofereciam o serviço de


armazenar os estados de transações. Assim, os usuários realizavam
suas operações nos arquivos e se caso ocorresse uma falha não teriam
como recuperar as informações, voltando ao seu estado de
comunicação anterior. Porém, o NFS em sua versão 4 já disponibiliza
este serviço, garantindo que não se perca nenhuma informação sobre
o estado da comunicação com os usuários, caso ocorra uma falha o
usuário apenas deverá repetir a chamada ao serviço até que o mesmo
responda. Esta característica, mesmo sendo útil por uma parte,
impede que o servidor possa gerenciar a concorrência ao acesso de
arquivos e com isso o NFS não assumirá a responsabilidade pela
consistência de seu sistema de arquivos. Poderá ocorrer que
diferentes usuários possuam cópias diferentes do mesmo arquivo ou
diretórios, armazenadas no cache de seus equipamentos. Tanenbaum
(2002).

205
01_SisOps.qxp 11/2/2009 11:36 Page 206

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

9.7.2 Serviço de Nomes

O serviço de nome em um sistema de NFS é primordial, pois


oferece ao usuário uma visão clara da estrutura do servidor de
arquivo quando é implementado. Este serviço demonstra que cada
usuário tem a sua própria estrutura e que não compartilha o mesmo
conjunto de nomes. Tanenbaum (2002).

Figura 9.9: Estrutura NFS – Serviços de Nome. Fonte. Tanenbaum (2002)

A Figura 9.9 ilustra claramente que usuários possuem a mesma


estrutura mas não compartilham dos mesmos nomes. Pois o mesmo
diretório do servidor está compartilhado em locais diferentes. A
desvantagem deste procedimento está no processo de comunicação
entre os usuários, que terão dificuldades em referenciar um mesmo
arquivo porque o caminho de acesso ao mesmo será diferente entre os
usuários. Tanenbaum (2002).

206
01_SisOps.qxp 11/2/2009 11:36 Page 207

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

9.8 Sistema de Arquivo no Linux

No Sistema Operacional Linux o conceito de um diretório equivale


as pastas do Sistema Operacional Windows, podemos dizer que um
diretório é filho quando ele faz parte de um outro diretório. E
chamando de diretório pai aquele que esta um nível acima.

No Linux o diretório raiz ou ( / ), é o diretório principal dentro da


hierarquia entre os outros do sistema e independente do tipo de
distribuição utilizada, sempre teremos os seguintes diretórios a seguir
[Equipe Conectiva (2004)]:

bin - com os arquivos binários de comandos disponíveis para todos


os usuários;
boot - com os arquivos do boot de inicialização;
dev - com as definições dos dispositivos de entrada/saída;
etc - com os arquivos de configuração do sistema;
home - com os diretórios dos usuários do sistema;
lib - com as bibliotecas e módulos (carregáveis) do sistema;
mnt - é utilizado como local para montagem de partições;
opt - é utilizado para instalar pacotes opcionais que não fazem
parte da distribuição Linux;
proc - com informações sobre os processos do sistema;
root - é home do administrador do sistema;
sbin - com os arquivos binários de comandos disponíveis para
administrar o sistema;
tmp - com arquivos temporários;
usr - com arquivos binários, páginas de manual e outros arquivos
imutáveis utilizados pelos usuários do sistema, mas que não são
essenciais para o uso do sistema como, por exemplo, o sistema de
janelas X, jogos, bibliotecas compartilhadas e programas de
usuários e de administração;
var - com arquivos de dados variáveis (spool, logs, etc).

207
01_SisOps.qxp 11/2/2009 11:36 Page 208

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Cada usuário tem o seu diretório e é chamado de diretório home,


diretório raiz do usuário ou ainda de diretório principal do usuário.
Este por sua vez é o de maior hierarquia dentro do conjunto de
diretórios do usuário, onde são armazenados todos os documentos do
usuário e que o mesmo, tem total controle sobre todos os arquivos e
diretórios que estão abaixo dele. O usuário tem os privilégios, poden-
do criar, apagar e modificar tudo que está abaixo do seu diretório
principal. Bem como, poderá definir as permissões de acesso para o
seu conteúdo (leitura, gravação e execução) pelos outros usuários que
acessarem a sua pasta, caso tenham permissão. [Equipe Conectiva
(2004)].

O diretório principal do usuário está localizado em “/home” e


possui o mesmo nome do login de acesso do usuário que ficará a
critério do administrador (root) de alterar este padrão no momento da
criação da conta do usuário. Equipe Conectiva (2004).

Exemplo: diretório principal do usuário é Paulo, por padrão ficará


/home/paulo.

Vale ressaltar que é possível disponibilizar os subdiretórios do


diretório principal em partições separadas, tendo como ponto
principal facilitar a realização das manutenções do sistema e prover
uma maior segurança das informações. Este procedimento de
separação do diretório principal em várias partições é uma escolha
particular do administrador do sistema, que geralmente sugere que
estes diretórios /home, /opt, /tmp, /usr e /usr/local, possuam uma
partição própria. Equipe Conectiva (2004).

Segundo a Equipe Conectiva (2004), os diretórios no linux


possuem uma estrutura com alguns arquivos especiais que servem para
a configuração do sistema, pois os dispositivos físicos são tratados
como um arquivo e estes estão dentro do diretório “/dev”. Em cada
arquivo, no seu começo, sempre são colocados os comentários sobre a
funcionalidade de cada um, bem como, explicações de como
configurá-los e em alguns casos, os mesmos somente servem como um
link para direcionar a outros arquivos. Estes links servem para duas
finalidades, a primeira como hard link que é o nome de um arquivo,
este podendo ter vários nomes e só poderá ser removido do disco
rígido quando o último nome for removido. E o soft link que é um
pequeno arquivo que contém o caminho para onde está apontando,
208
01_SisOps.qxp 11/2/2009 11:36 Page 209

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

sendo que este link aponta para um outro arquivo e que poderá
também ser direcionado até mesmo a um outro tipo de sistema de
arquivo.

Para criação de arquivo com um soft link, dependendo da


distribuição, basta acessar como superusuário e digitar o seguinte
comando: ln -s [arquivo_original] [link_para_arquivo].

As distribuições Linux possuem algumas diferenças, mas


mantendo sempre a sua estrutura básica. Apesar de já ter comentado
anteriormente, a seguir listamos mais alguns diretórios com alguns de
seus arquivos importantes. Equipe Conectiva (2004).

Diretório /etc

init.d - é o diretório que contém scripts de inicialização de


serviços da máquina e é um soft link para o diretório
/etc/rc.d/init.d.;
exports - é o arquivo que controla o acesso ao sistema de
arquivos que estão sendo exportados para os clientes NFS;
X11 - configurações relacionadas ao sistema de janelas X,
configuração do teclado e comportamento de alguns programas no
ambiente gráfico;
passwd - é um arquivo que contém informações sobre os usuários
da máquina;
group - é um arquivo um pouco parecido com o arquivo passwd,
mas que trabalha com os grupos de usuários;

Diretório /usr

bin - possui os comandos de usuários;


sbin - possui os comandos de administração do sistema;
local - é usado para armazenar os programas instalados local-
mente, não se enquadram neste os pacotes RPM;

209
01_SisOps.qxp 11/2/2009 11:36 Page 210

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Diretório /var

log - é um arquivo que possui os registros (históricos de


programas). É importante dar uma atenção a este arquivo, pois o
mesmo tem o seu tamanho aumentado indefinidamente;
spool - serve para armazenar as filas de processos em execução,
e-mail, impressão, entre outros.

Segurança de Arquivos

A segurança dos arquivos em ambiente Linux tem os mesmos


preceitos em relação ao Windows, sendo primordial e importantíssimo
prover recursos e procedimentos que garantam a segurança do sistema
contra violação do sistema por usuários mal intencionados e acessos a
arquivos importantes. Por isso os arquivos de um sistema devem
pertencer a um grupo de usuários ou somente a um usuário. Estas duas
restrições é que determinarão como serão as permissões para uso
deste arquivo. [Equipe Conectiva (2004)].

As configurações destas permissões são realizadas em três níveis


de usuários, que são: o dono do arquivo, o grupo ao qual este arquivo
pertence e os demais usuários que não se encaixam nos dois níveis
citados. Estas permissões não se restringem somente à manipulação
de arquivos, pois dispositivos são referenciados por arquivos e desta
forma seria considerado como uma falta de proteção caso um usuário
qualquer tiver acesso a um recurso específico do equipamento e
realizasse alterações sem a devida permissão do proprietário, isso
poderia ser uma catástrofe em um sistema de grande porte. Por isso
somente os usuários com permissões de superusuários poderão fazer
tais alterações. [Equipe Conectiva (2004)].

Por ocasião da criação de um determinado arquivo, ele recebe


algumas propriedades, como por exemplo: Identificação do dono
(UID), uma numeração do grupo (GID) e valores de permissão de
acesso. [Equipe Conectiva (2004)].

210
01_SisOps.qxp 11/2/2009 11:36 Page 211

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

Exemplo de permissões de arquivos:

- $ ls -l joao
-rw-rw-r-- 1 professor escola 71815 2004-04-02 10:00 joao.

Conforme ilustrado no exemplo, o arquivo recebe alguns


parâmetros que o identificam no sistema, como (-rw-rw-r--) este
parâmetro identifica qual é o tipo do arquivo, fazendo referência que
em ambiente Linux, diretórios também são considerados como
arquivo. Equipe Conectiva (2004). A seguir segue descrição breve de
alguns destes parâmetros para arquivos:

Identificação:
(-) atributo de arquivo;
(d) quando se trata de um diretório;
(l) arquivo é um link simbólico;
(b) dispositivos de bloco.

Permissões:
Letra r significa leitura (copiar, imprimir, visualizar);
Letra w significa escrita (mover, apagar, modificar);
Letra x significa execução (programas, scripts, diretórios);
Símbolo ( - ) o usuário não tem permissão.

E para os diretórios:
Letra r permite que o usuário possa listar o conteúdo;
Letra w permite a criação, apagar e alterar arquivos no diretório;
Letra x permite a realização de buscas no diretório;
Símbolo ( - ) o usuário não tem permissão.

As demais informações são: o número 1 identifica se é um arqui-


vo ou um diretório, no caso de ser um arquivo indicará que está sendo
apontado por um hard link e corresponde a quantidade, e em caso de
ser diretório indicará a quantidade de seus subdiretórios seguidos de
(. e ..). O nome “professor” corresponde ao usuário e o nome
“escola” ao grupo, na ausência no sistema destas informações,
211
01_SisOps.qxp 11/2/2009 11:36 Page 212

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

aparecerá somente os números de identificação do usuário (UID) e a


identificação do grupo (GID). As informações seguintes são para
especificar o tamanho do arquivo e datas / hora da última
modificação. Equipe Conectiva (2004).

Todos estes parâmetros servem para restringir as ações por parte


do usuário e podem ser aplicadas, no dono do arquivo, no grupo ou em
todos os usuários que não fazem parte e podem ser modificadas
através dos seguintes comandos chown e chgrp. Equipe Conectiva
(2004).

212
01_SisOps.qxp 11/2/2009 11:36 Page 213

Bibliografia

SILBERSCHATZ, Avi. GALVIN, Peter Baer. GAGNE, Greg.


Fundamentos de Sistemas Operacionais: conceitos e aplicações. 6ª
Edição. LTC, 2004.

SILBERSCHATZ, A. et. al. Operating Systems Concepts (7th


Edition), Ed. Wiley & Sons, 2005.

TANENBAUM, A. Sistemas Operacionais Modernos. 2 ª Edição.


Pearson-Prentice Hall, 2003.

TANENBAUM, A. Sistemas Operacionais Projetos e Implementação.


2 ª Edição. Bookman, 2002.

TANENBAUM, Andrew S.; STEEN, Maarten van. Distributed


Systems: Principles and Paradigms. New Jersey: Prentice Hall,
2002.

OLIVEIRA, R., CARISSIMI, A. e TOSCANI, S., Sistemas Operacionais,


Ed. Sagra-Luzzatto, 2004.

EQUIPE CONECTIVA, Guia do Servidor Conectiva Linux,


Conectiva S.A. acesso em 01/12/2008
(http://www.conectiva.com/doc/livros/online/10.0/servidor/pt_BR/index.html.

213
01_SisOps.qxp 11/2/2009 11:36 Page 214

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

TANENBAUM, Andrew S. Organização Estruturada de


Computadores. Editora Pearson Education do Brasil & Prentice
Hall, 5ª. Edição, ISBN: 85-7605-067-6, 2007.

RIBEIRO, Uirá. Sistemas Distribuídos – Desenvolvendo Aplicações


de Alta Performance no LINUX. Editora AXCEL, ISBN: 85-7323-228-
5, 2005.

DEITEL, H.M, DEITEL, P.J., CHOFFNES, D.R. Sistemas Operacionais.


Editora Pearson Education do Brasil & Prentice Hall, 3ª. Edição,
ISBN: 85-7605-011-0, 2005.

SEMENTILLE, Antonio Carlos. Material Didático da disciplina –


Sistemas Operacionais. Centro Universitário Eurípides de Marilia,
2006.

MACHADO, Francis Berenger. MAIA, Luiz Paulo. Arquitetura de


Sistemas Operacionais. Editora LTC, 4ª. Edição, ISBN: , 2007.

PINTO, Renan. Material didático da disciplina – Arquitetura de


Sistemas Operacionais – Capítulo 9 (Gerência de Memória), 2008.

PINTO, Renan. Material didático da disciplina – Arquitetura de


Sistemas Operacionais – Capítulo 10 (Gerência de Memória
Virtual), 2008.

PINTO, Renan. Material didático da disciplina – Arquitetura de


Sistemas Operacionais – Capítulo 7 (Sincronização e Comunicação
de Processos), 2008.

SILBERSCHATZ, Avi. GALVIN, Peter Baer. GAGNE, Greg. Sistemas


Operacionais com JAVA. Editora Campus & Elsevier, 6ª. Edição,
ISBN: 85-352-1485-2, 2004.

SILBERSCHATZ, Avi. GALVIN, Peter Baer. GAGNE, Greg. Sistemas


Operacionais Conceitos e Aplicações. Editora Campus & Elsevier,
2ª. Edição, ISBN: 85-352-0719-8, 2001.

214
01_SisOps.qxp 11/2/2009 11:36 Page 215

Tecnologia em Análise e
Sistemas Operacionais
Desenvolvimento de Sistemas

DENNING, P.J. The Working Set Model for Program Behavior. In


Communications of the ACM, vol. 11, p. 323-333, Maio, 1968.

KNUTH, D.E. The Art of Programming: Fundamentals and


Algorithms. Editora Addison-Wesley, 3 ª Edição, 1997.

FOTHERINGHAM, J. Dynamic Storage Allocation in the Atlas


Computer Including na Automatic use of Backing Store. In
Communications of the ACM, v. 4, p. 435-436, Out. 1961.

STALLINGS, W. Arquitetura e Organização de Computadores.


Editora Pearson Education do Brasil & Prentice Hall, 2ª. Edição,
ISBN:, 2007.

215