SlideShare una empresa de Scribd logo
1 de 87
UNIVERSIDADE FEDERAL DE PELOTAS
INSTITUTO DE FÍSICA E MATEMÁTICA
DEPARTAMENTO DE INFORMÁTICA
BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO
ESTUDO DE CASO: WINDOWS NT
Jerônimo Medina Madruga
Leonardo Lobo da Luz
Mauro Sérgio Cardoso Kade
Trabalho de pesquisa apresentado na disciplina de
Sistemas operacionais 2 do Curso de Bacharelado em
Ciência da Computação, Instituto de Física e
Matemática, Universidade Federal de Pelotas. Professor:
Prof. Gil Medeiros
2007
Lista de Figuras
Figura 1: Componentes do Sistema de E/S...........................................................................14
Figura 2: Rotinas primárias de drivers de dispositivos.........................................................16
Figura 3: Abrindo um objeto de arquivo...............................................................................21
Figura 4: Enfileirando e completando uma requisição de E/S..............................................25
Figura 5: Mapeando Páginas Virtuais para estruturas de página físicas...............................33
Figura 6: Mapeando Visões em uma Seção..........................................................................38
Figura 7: Section Object........................................................................................................39
Figura 8: Antes do copy-on-write.........................................................................................42
Figura 9: Depois do copy-on-write.......................................................................................43
Figura 10: Espaço de Endereçamento Virtual.......................................................................45
Figura 11: Tabela de Páginas Conceitual..............................................................................47
Figura 12: Esquema de tradução de endereço virtual para endereço físico em arquiteturas
Intel.......................................................................................................................................54
Figura 13: Principais funções API Win32 para gerenciamento da memória virtual.............59
Figura 14: Representação de um processo como objeto.......................................................61
Figura 15: Representação de uma Thread como um objeto..................................................62
Figura 16: Tabela de prioridades do Windows 2000............................................................67
Figura 17: Principais funções API Win32 para funções de arquivos....................................70
Figura 18: Tabela Mestre de Arquivos NTFS.......................................................................73
Figura 19: Registro da MFT para um arquivo......................................................................75
Figura 20: Registro da MFT para um pequeno diretório......................................................79
Figura 21: Visão geral de um FSD local...............................................................................80
Figura 22: Operação de FSD remoto....................................................................................81
Figura 23: Criptografia de Arquivos.....................................................................................84
Sumário
APRESENTAÇÃO.................................................................................................................5
1. HISTÓRICO.......................................................................................................................6
1.1 MS-DOS........................................................................................................................6
1.2 Windows.......................................................................................................................6
1.3 Windows NT.................................................................................................................7
1.4 Windows 2000..............................................................................................................8
2. GERENCIAMENTO DE E/S...........................................................................................11
2.1 Principais objetivos do sistema de E/S .......................................................................11
2.2 Componentes do Sistema de E/S.................................................................................12
2.2.1 Gerenciador de E/S..................................................................................................15
2.2.2 Drivers de Dispositivo..............................................................................................15
2.2.2.1 Estrutura de um Driver..........................................................................................16
2.2.3 Gerenciador de PnP (Plug-and-Play).......................................................................17
2.2.4 Gerenciador de Cache..............................................................................................18
2.3 Estruturas de Dados de E/S.........................................................................................19
2.3.1 Objetos de Arquivo..................................................................................................19
2.3.2 Objetos de Driver e Objetos de Dispositivo.............................................................22
2.3.3 Pacotes de Requisição de E/S..................................................................................22
2.4 Processamento de E/S.................................................................................................23
2.4.1 Tipos de E/S.............................................................................................................23
2.5 Suporte a RAID...........................................................................................................26
2.6 Plug-and-play..............................................................................................................26
2.7 Suporte a multiprocessamento....................................................................................27
2.8 Recuperação de falha de energia.................................................................................27
3. GERENCIAMENTO DE MEMÓRIA..............................................................................29
3.1 Memória Virtual..........................................................................................................30
3.2 Gerenciando a Memória..............................................................................................34
3.2.1 Estados de uma página virtual..................................................................................35
3.2.2 Memória Compartilhada..........................................................................................36
3.2.2.1 Section Object.......................................................................................................39
3.2.3 Proteção de Memória...............................................................................................41
3.3 Implementação............................................................................................................44
3.3.1 Mecanismos de Paginação.......................................................................................46
3.3.2 Políticas de Paginação..............................................................................................49
3.3.3 Gerenciamento da memória física............................................................................51
3.3.4 Tradução de Endereços............................................................................................53
3.3.5 Tratamento de Falta de Página.................................................................................55
3.3.6 Descritores de Endereço Virtual..............................................................................56
3.4 Chamadas ao Sistema..................................................................................................58
4. GERÊNCIA DE PROCESSOS.........................................................................................60
4.1 Caracterização de Jobs, Processos, Threads e Fibers..................................................60
4.2 Técnicas de comunicação............................................................................................63
4.3 Técnicas de sincronização...........................................................................................64
4.4 Criação de Processos e Threads..................................................................................65
4.5 Escalonamento............................................................................................................66
5. SISTEMA DE ARQUIVOS..............................................................................................68
5.1 Conceitos Fundamentais do NTFS..............................................................................68
5.2 Chamadas de API........................................................................................................70
5.3 Estrutura do Sistema de Arquivos...............................................................................71
5.4 Arquitetura do Driver de Sistema de Arquivos...........................................................79
5.5 Compressão de Arquivos............................................................................................82
5.6 Criptografia de Arquivos.............................................................................................83
REFERÊNCIAS BIBLIOGRÁFICAS..................................................................................87
APRESENTAÇÃO
Este trabalho tem como objetivo realizar uma análise em um dos sistemas
operacionais mais difundidos no mundo, o Windows NT. Em um primeiro
momento, faremos uma abordagem da história do desenvolvimento desse
sistema, revelando suas raízes e mostrando sua evolução ao longo dos anos.
Após, abordaremos os componentes mais relevantes na estrutura do sistema
operacional em estudo: o gerenciamento de entrada e saída, gerenciamento de
memória, gerenciamento de processos, e gerenciamento de arquivos, comparado
com os elementos previamente estudados na disciplina.
1. HISTÓRICO
Este capítulo tem como objetivo representar os avanços em sistemas
operacionais e o contexto histórico que levaram ao desenvolvimento da
arquitetura do desenvolvimento do Windows NT. Daremos enfoque aos
predecessores do Windows NT, o MS-DOS e Windows, citando suas
características, vantagens e desvantagens. Após, entraremos mais afundo no
projeto do Windows 2000, um dos representantes mais recentes do Windows NT,
mostrando suas inovações tecnológicas e os princípios de desenvolvimento do
mesmo.
1.1 MS-DOS
Em 1981, a IBM produzia o IBM PC utilizando o processador 8088. Esse
computador vinha com sistema operacional de 16 bits monousuário chamado MS-
DOS (Microsoft Disk Operational System). Esse sistema operacional consistia em
8 KB de código residente na memória e foi modelado de forma similar ao CP/M,
um sistema operacional pequeno para os processadores de 8 bits 8080 e Z80.
Dois anos depois, uma nova versão, o MS-DOS 2.0, foi lançada, contendo um
processador de linha de comando e com diversas características semelhantes ao
UNIX. Com o passar do tempo foram sendo lançada novas versões de acordo
com a evolução dos computadores, que agregavam novas características, mas
continuava basicamente sendo um sistema orientado a linha de comando
[TANENBAUM, 2001].
1.2 Windows
Tendo como inspiração a interface de usuário do Apple Lisa, a Microsoft
decidiu dar ao MS-DOS uma interface gráfica, a qual foi chamada de Windows. O
Windows 1.0 foi lançado em 1985, mas não chegou a ter sucesso, assim como
seu sucessor Windows 2.0. A popularização começou com o Windows 3.0 e seus
derivados, mas é importante salientar que nenhuma dessas versões iniciais do
Windows eram realmente sistemas operacionais, eles eram interfaces gráficas
para o usuário trabalhar em cima do MS-DOS, que ainda gerenciava a máquina e
o sistema de arquivos. Todos os programas rodavam no mesmo espaço de
endereçamento e um defeito em qualquer um deles poderia causar uma pane
geral no sistema.
Esse cenário começa a mudar com o Windows 95, onde apesar do MS-
DOS ainda estar intrínseco no sistema, grande parte do sistema operacional já era
gerenciado pelo sistema, além de já contar com características de um sistema
mais maduro, como memória virtual, gerenciamento de processos e
multiprogramação. Como herança do MS-DOS, o Windows 95 ainda continha
partes do código sendo composta por código assembly de 16 bits e ainda usava o
sistema de arquivos do MS-DOS.
O sucessor do Windows 95, o Windows 98, ainda continha o MS-DOS,
agora na versão 7.1, mas já tinha um sistema de arquivos novo. Ele também tinha
uma maior integração entre a Internet e o desktop do sistema. O Windows 98 tinha
ainda dois problemas crônicos, fora a presença do legado do MS-DOS: o código
do kernel não era reentrante, o que ocasionava problemas na execução de
diversos processos que utilizassem estruturas de dados do kernel e o fato que
havia uma parte do espaço de endereçamento virtual que era compartilhada por
todos os processos, além do kernel, assim um defeito em um programa poderia
afetar todo o sistema.
Após veio o Windows Me (Windows Millenium Edition), que era
essencialmente o Windows 98, com a correção de alguns dos defeitos e com
alguns novos recursos relativos aos dispositivos que despontavam na época e a
aplicativos multimídia.
1.3 Windows NT
Em 1988, a Microsoft decidiu desenvolver um sistema operacional para a
década de 1990. O MS-DOS tinha sido desenvolvido para hardware antigo, e
assim os modos de utilização do mesmo começaram a ficar rapidamente
restritivos e obsoletos, como o suporte a modo monousuário unicamente,
arquitetura de 8 e 16 bits com um suporte rústico para múltiplos processos, sem
proteção de memória entre eles. A alternativa da época, o OS/2, foi uma tentativa
de aumentar o escopo de uso, mas continha grandes fragmentos de código em
assembly para arquitetura CISC monoprocessada, e assim não poderia evoluir
para usufruir das vantagens dos novos processadores RISC e das ferramentas de
proteção à memória presentes nos processadores subseqüentes da Intel.
Também durante esse tempo, várias pesquisas acadêmicas sobre sistemas
operacionais começaram a ser divulgadas [BACON, 2003].
Para desenvolver esse novo sistema, Dave Cutler, que foi um importante
desenvolvedor do sistema operacional VMS, foi contratado pela Microsoft, com o
intuito de liderar a equipe que iria desenvolver o sistema que seria chamado
posteriormente de Windows NT (Windows New Technology), que seria o primeiro
Windows a funcionar totalmente 32 bits, tendo foco tanto para o mercado
empresarial quanto para os computadores domésticos. . A primeira versão foi
batizada Windows NT 3.1, que apesar de ser superior tecnicamente à versão do
Windows baseada no MS-DOS que existia no momento, não chegou a ter muito
sucesso devido ao fato que o sistema era mais pesado e ainda não havia grande
gama de aplicativos 32 bits.
Após, foram lançadas sucessivas atualizações para o sistema NT, até ser
lançada uma nova versão em 1996, o Windows NT 4.0, que tinha a mesma
interface que consagrou o Windows 95, em conjunto com poder, segurança e
confiabilidade, e assim esse sistema teve uma aceitação muito maior que seu
predecessor. Sendo quase totalmente escrito em C, o Windows NT era
extremamente portável, e com isso ele rodava em diversas outras plataformas, em
contraste ao Windows 95 e seus descendentes, que rodavam somente na
Arquitetura X86 da Intel [TANENBAUM, 2001].
1.4 Windows 2000
O Windows 2000 foi o nome do sucessor do Windows NT 4.0, e tinha como
objetivo ter a confiabilidade da família NT com a interface do Windows 98. O
Windows 2000 manteve diversas características do Windows NT, sendo um
sistema totalmente 32 bits (mas mantendo compatibilidade com aplicativos 16 bits)
focado para quase todo o mercado de computadores: de laptops a estações
multiprocessadas.
O Windows 2000 teve diversos princípios utilizados para seu
desenvolvimento, entre eles podemos citar:
• Extensibilidade: para encarar as constantes mudanças na demanda
do mercado, o Windows 2000 foi desenvolvido numa estrutura
modular baseada em objetos, o que permitiu que funções comuns,
como controle de acesso a recursos, fossem separadas das funções
especificas. Assim drivers de dispositivos pode ser carregados e
descarregados dinamicamente.
• Portabilidade: tendo como objetivo poder ser portado para outras
arquiteturas com o menor numero de mudanças possível, o Windows
2000 foi quase totalmente escrito em C e C++, sendo assim a
linguagem assembly se restringe às camadas dependentes de
hardware.
• Escalabilidade: o Windows 2000 permite que as aplicações explorem
todo o potencial do hardware, tendo suporte para
multiprocessamento e grande espaço de endereçamento físico.
• Robustez: o sistema deve ser capaz de proteger-se contra erros
internos, defeitos e ataques externos. O sistema de proteção previne
que nenhum programa corrompa o sistema operacional ou outra
aplicação.
• Compatibilidade: o Windows 2000 mantém compatibilidade com os
aplicativos desenvolvidos para as versões mais antigas de sistemas
operacionais da Microsoft.
• Segurança: O Windows 2000 tem segurança classe C2 para multi-
usuário e sistemas comerciais, que consiste em um sistema de login
protegido por senha, o sistema operacional rodando em modo
protegido, espaços de endereçamentos protegidos e cotas de
recursos.
• Performance: O sistema tem de ser rápido ao responder para o
usuário [BACON, 2003].
2. GERENCIAMENTO DE E/S
Este capítulo tem por objetivo descrever as funcionalidades, os componentes e
o funcionamento básico do sistema de gerência de E/S do Windows NT, assim
como a interação entre esses diversos componentes que compõe o sistema de
E/S.
2.1 Principais objetivos do sistema de E/S
Alguns dos objetivos principais do sistema de gerência de E/S do Windows NT
são:
• Tornar o processamento de E/S rápido tanto para arquiteturas mono
quanto multiprocessadas.
• Utilizar mecanismos de segurança para proteger recursos
compartilhados.
• Prover serviços de E/S para as interfaces Win32, POSIX e OS/2.
• Permitir que drivers de dispositivo sejam instalados e desinstalados de
forma dinâmica, garantindo sua configuração automática, assim como
do hardware a ser adicionado ou removido do sistema.
• Provê suporte a vários sistemas de arquivo, entre eles a tabela de
alocação de arquivos (FAT), o sistema de arquivo de CD-ROM (CDFS),
o formato de disco universal (UFS), e o sistema de arquivos do Windows
NT (NTFS).
A seguir, uma descrição detalhada dos componentes do sistema de gerência
de E/S e a maneira pela qual eles atuam para atingir tais objetivos.
2.2 Componentes do Sistema de E/S
O Windows NT consiste em uma série de componentes que, em conjunto,
oferecem diversos serviços de E/S periféricos atuantes em um sistema de
computador. Tais componentes fazem parte da camada executiva do Windows
NT. A figura 1 a seguir ilustra todos esses componentes.
• O gerenciador de E/S é responsável pelos acessos ao sistema de
arquivos, gerenciamento de cache, drivers de dispositivo e drivers de
rede. Ele determina quais sistemas de arquivo instaláveis são
carregados, e gerencia os buffers para as requisições de E/S. Ele
trabalha com o gerenciador de MV (Máquina Virtual) para prover um
sistema de E/S mapeado em memória, e controla o gerenciador de
cache do NT. O gerenciador de E/S suporta operações síncronas e
assíncronas, provê timeouts para os drivers, e possui mecanismos para
um driver chamar outro.
• O gerenciador de cache oferece serviços de cache para todos os
componentes em controle do gerenciador de E/S, e trabalha próximo ao
gerenciador de MV (Máquina Virtual). O tamanho da cache muda
dinamicamente, de acordo com a quantidade de memória livre
disponível no sistema.
• Um driver de dispositivo tipicamente oferece uma interface de E/S para
um tipo de dispositivo em particular. Drivers de dispositivo recebem
comandos roteados para eles pelo gerenciador de E/S, sendo enviados
para os dispositivos que eles gerenciam, informando ao gerenciador de
E/S quando esses comandos terminarem.
• O gerenciador PnP (Plug-and-Play) atua em conjunto com o gerenciador
de E/S e com um driver de dispositivo chamado driver de barramento
para guiar a alocação dos recursos do hardware de forma segura e
responder satisfatoriamente às adições e/ou remoções de componentes
de hardware. O gerenciador PnP e os drivers de barramento são
responsáveis por carregar um driver de dispositivo quando um
determinado componente é detectado.
• O gerenciador de força atua em conjunto com o gerenciador de E/S para
guiar o sistema, assim como os drivers de dispositivo, através de
transições de estados de força ou de energia.
• O registro serve como uma base de dados que armazena uma
descrição básica dos dispositivos de hardware presentes no sistema,
assim como inicialização e configuração de um driver.
• Arquivos INF, designados pela extensão .inf, que são arquivos de
instalação de drivers. Esses arquivos são a ligação entre um dispositivo
de hardware particular e o driver que assume o controle do dispositivo.
• A camada de abstração de hardware (HAL – Hardware Abstraction
Layer) oferece API’s que escondem as diferenças entre as plataformas
dos drivers. Na prática, o HAL é um driver de barramento para todos os
dispositivos da placa-mãe do computador que não são controlados por
outros dispositivos.
Figura 1: Componentes do Sistema de E/S
Muitas operações de E/S não envolvem todos os componentes descritos
acima. Uma típica requisição de E/S começa com uma aplicação executando uma
determinada função de E/S (por exemplo, ler dados de um disco rígido) que é
processada por um gerenciador de E/S, um ou mais drivers de dispositivo, e o
HAL.
No Windows NT, diferentes threads realizam E/S em arquivos virtuais. O
sistema operacional abstrai todas as requisições de E/S como se fossem
operações em um arquivo virtual, escondendo o fato de que o objetivo de uma
operação de E/S pode não ser um dispositivo estruturado de arquivo. Essa
abstração generaliza uma interface de aplicação para os dispositivos. Um arquivo
virtual, por sua vez, refere-se a qualquer fonte ou destino para a E/S que é tratada
como se fosse um arquivo comum. Todos os dados que são lidos ou gravados são
considerados como um simples fluxo de bytes dirigidos para esses arquivos
virtuais. Aplicações em modo usuário chamam funções específicas, que por sua
vez chamam funções internas do sistema de E/S para ler de um arquivo, escrever
em um arquivo, e/ou realizar outras operações. O gerenciador de E/S envia
dinamicamente essas requisições dos arquivos virtuais para o driver de dispositivo
apropriado.
Nas seções seguintes, os componentes serão descritos com mais
profundidade. Primeiramente será visto o gerenciador de E/S e, logo após, os
drivers de dispositivo, assim como as estruturas de dados do sistema de E/S.
2.2.1 Gerenciador de E/S
O gerenciador de E/S é responsável pelos acessos ao sistema de arquivos,
gerenciamento de cache, drivers de dispositivo e drivers de rede. Ele determina
quais sistemas de arquivo instaláveis são carregados, e gerencia os buffers para
as requisições de E/S. Ele trabalha com o gerenciador de MV (Máquina Virtual)
para prover um sistema de E/S mapeado em memória, e controla o gerenciador de
cache do NT. O gerenciador de E/S suporta operações síncronas e assíncronas,
provê timeouts para os drivers, e possui mecanismos para um driver chamar outro
[SILBERSCHATZ, 1998].
O gerenciador de E/S converte as requisições que recebe em um formato
padrão chamado IRP (I/O Request Packet). Ele então encaminha o IRP para o
driver correto para processamento. Quando a operação termina, o gerenciador de
E/S recebe o IRP do driver que recentemente executou uma operação, e completa
a requisição.
2.2.2 Drivers de Dispositivo
Um driver de dispositivo funciona como a ponte necessária entre o gerenciador
de E/S e os componentes do sistema de E/S.
Entre alguns dos tipos de drivers de dispositivo encontram-se:
• Drivers de sistema de arquivo: aceitam requisições para arquivos.
• Drivers do Windows NT: atuam em conjunto com os gerenciadores de
força e PnP do Windows NT, quando requisitados.
• Drivers de dispositivo virtuais: utilizados para emular aplicações de 16
bits do MS-DOS.
2.2.2.1 Estrutura de um Driver
O sistema de E/S controla a execução dos drivers de dispositivo. Os drivers de
dispositivo consistem em uma série de rotinas que são chamadas para processar
os vários estágios de uma requisição de E/S. A figura abaixo (Figura 2) ilustra
algumas dessas rotinas.
Figura 2: Rotinas primárias de drivers de dispositivos
O gerenciador de E/S executa uma rotina de inicialização do driver
(initialization routine), que é denominada DriverEntry, quando carrega o driver no
sistema operacional.
Um driver que suporta Plug-and-Play implementa uma rotina de adição de
dispositivo (add-device routine). O gerenciador de PnP manda uma notificação a
um driver através dessa rotina. Ela também permite que um driver aloque um
objeto de dispositivo para representar o dispositivo.
Rotinas de envio (Set of dispatch routines) são funções vitais que um driver
de dispositivo oferece. Alguns exemplos são abertura (open), fechamento (close),
leitura (read), escrita (write) e outras capacidades relacionadas a dispositivos,
sistema de arquivos ou suporte a rede. Quando chamado para realizar uma
operação de E/S, o gerenciador de E/S gera um IRP e chama um driver através de
uma rotina de envio de driver.
Um driver pode usar uma rotina de início de E/S (start I/O routine) para iniciar
uma transferência de dados para ou de um dispositivo. Essa rotina é definida
somente em drivers que contam com o gerenciador de E/S para uma serialização
IRP. O gerenciador de E/S serializa IRP’s para um driver garantindo que o driver
processe somente um IRP por vez.
Quando um dispositivo causa uma interrupção, o despachador de interrupção
do kernel transfere o controle para uma rotina chamada serviço de interrupção
(interrupt service routine – ISR).
Uma rotina de serviço de interrupção DPC (interrupt-servicing DPC routine)
realiza muito do trabalho envolvido no tratamento de uma interrupção de
dispositivo após a ISR executar. A rotina DPC executa a nível de dispositivo, para
evitar bloqueio de outras interrupções desnecessariamente.
2.2.3 Gerenciador de PnP (Plug-and-Play)
O gerenciador de PnP é o componente principal envolvido no suporte às
habilidades do Windows NT de reconhecimento e adaptação às mudanças de
configuração de hardware. Desta forma, o usuário não precisa entender as
particularidades do hardware para instalar ou remover dispositivos.
O suporte a Plug-and-Play requer uma cooperação entre o hardware, os
drivers de dispositivo e os diferentes níveis do sistema operacional. Algumas
capacidades do suporte a esse sistema são:
• O gerenciador PnP reconhece automaticamente dispositivos instalados,
um processo que inclui enumerar dispositivos acoplados ao sistema
durante uma operação de boot e detectar a adição ou remoção de
dispositivos enquanto o sistema encontra-se em execução.
• A alocação de recursos de hardware é um papel que o gerenciador de
PnP desempenha juntando as exigências dos recursos dos dispositivos
conectados ao sistema e, em um processo chamado arbitragem de
recursos, designar recursos para que os dispositivos conheçam as
exigências necessárias para suas operações. Esse processo também
deve ser feito de forma dinâmica pelo gerenciador de PnP.
• O gerenciador de PnP também é responsável por carregar os drivers
apropriados.
• O gerenciador de PnP implementa aplicações e mecanismos de driver
para detecção das mudanças nas configurações de hardware.
Aplicações ou drivers às vezes requerem um dispositivo de hardware
específico para a função, então o Windows NT oferece os meios para
que sejam conhecidos notificações da presença, adição ou remoção de
dispositivos.
2.2.4 Gerenciador de Cache
Geralmente, a cache é dividida em blocos de 256 KB. Cada bloco de cache é
descrito por um VACB (Virtual-Address Control Block) que armazena os
endereços virtuais e também um offset de arquivo para a região mapeada em
memória, juntamente com o número de processos que estão usando a região
especificada. O VACB reside em um vetor que é mantido pelo gerenciador de
cache.
Para cada arquivo aberto, o gerenciador de cache mantém um índice separado
no vetor VACB. Esse vetor possui um elemento para cada pedaço de 256 KB do
arquivo. Dessa forma, um arquivo de 2 MB teria 8 entradas no vetor de índices
VACB. Uma entrada nesse vetor de índices aponta para o VACB se aquela parte
do arquivo encontra-se na cache. Em caso contrário, ela tem um valor nulo.
2.3 Estruturas de Dados de E/S
Quatro estruturas de dados estão associadas com as requisições de E/S:
objetos de arquivo, objetos de driver, objetos de dispositivo e pacotes de
requisição de E/S ( I/O Request Packets - IRP ). Cada uma dessas estruturas é
definida em um cabeçalho de arquivo DDK denominado Ntddk.h.
2.3.1 Objetos de Arquivo
Objetos de arquivo são construções em modo kernel para lidar com arquivos
ou dispositivos. Eles estabelecem critérios para os objetos no Windows NT: eles
são recursos de sistema em que dois ou mais processos em modo-usuário podem
compartilhar, eles podem ter nomes, são protegidos por um tipo de segurança
baseada em objeto e suportam sincronização. Recursos compartilhados no
sistema de E/S são manipulados como se fossem objetos.
Objetos de arquivo provêem uma representação baseada em memória dos
recursos que obedecem a uma interface centrada em E/S, a qual eles podem ser
lidos de ou escritos para.
A seguir, serão descritos alguns atributos dos objetos de arquivo:
• Nome de arquivo (Filename): identifica o arquivo físico a que o objeto de
arquivo se refere.
• Byte corrente de offset (Current byte offset): identifica a localização atual
no arquivo (válido apenas para operações de E/S sincronizadas).
• Modos de compartilhamento(Share modoes): indica onde outros
chamadores podem abrir os arquivos para ler, escrever ou deletar
operações enquanto o chamador atual está em funcionamento.
• Ponteiro para objeto de dispositivo (Pointer to device object): indica o
tipo de dispositivo onde o arquivo reside.
• Ponteiro para o bloco de parâmetro de volume (Pointer to the volume
parameter block - VPB): indica o volume ou a partição em que o arquivo
reside.
Quando um chamador abre um arquivo para um dispositivo simples, o
gerenciador de E/S retorna um handle para um objeto de arquivo. A figura abaixo
ilustra o que acontece quando um arquivo é aberto.
Figura 3: Abrindo um objeto de arquivo
Nesse exemplo, (1) um programa em C chama uma rotina chamada fopen, a
qual (2) chama uma função da API Win32 chamada CreateFile. A DLL do
subsistema Win32 chamada kernel32.dll então (3) chama uma função nativa
denominada NtCreateFile que se encontra no arquivo Ntdll.dll. A rotina presente
nesse arquivo contém a instrução apropriada para causar uma transição do modo
kernel para o sistema de despachador de serviço (system service dispatcher), o
qual (4) chama a rotina real NtCreateFile no arquivo Ntoskrnl.exe.
Assim como outros objetos do executivo, arquivos de objeto são protegidos por
um descritor de segurança que contém uma lista de controle de acesso (acess-
control list – ACL).
2.3.2 Objetos de Driver e Objetos de Dispositivo
Quando uma thread abre um handle para um objeto de arquivo, o gerenciador
de E/S deve determinar qual driver ou drivers do objeto de arquivo deve ser
chamado para processar a requisição. O gerenciador de E/S deve ser capaz de
localizar essa informação da próxima vez que uma thread usar o mesmo handle
de arquivo.
Um objeto de driver representa um driver individual no sistema. O gerenciador
de E/S obtém o endereço de cada rotina de envio dos drivers do objeto de driver.
Já os objetos de dispositivo representam um dispositivo lógico ou físico no sistema
e descrevem suas características. O gerenciador de E/S cria um objeto de driver
enquanto um driver é carregado no sistema, e então chama uma rotina de
inicialização do driver denominada DriverEntry, a qual encaixa os atributos do
objeto com os pontos de entrada do driver. Após ser carregado, um driver pode
criar objetos de dispositivo para representar dispositivos, ou até mesmo uma
interface para o driver, através de uma chamada a rotina IoCreateDevice.
2.3.3 Pacotes de Requisição de E/S
O pacote de requisição de E/S (I/O Request Packet - IRP) é onde o sistema de
E/S armazena informações necessárias para processar uma requisição de E/S.
Quando uma thread chama um serviço de E/S, o gerenciador de E/S constrói um
IRP para representar a operação enquanto ele atravessa o sistema de E/S.
Um IRP consiste de duas partes: um cabeçalho fixo, e um ou mais pilhas de
localização. A parte fixa contém informações acerca do tipo e tamanho da
requisição, se a requisição é síncrona ou assíncrona, um ponteiro para um buffer e
informações a respeito do estado de operação da requisição.
2.4 Processamento de E/S
As requisições de E/S passam por diversos estágios de processamento. Os
estágios variam dependendo se a requisição se destina a um dispositivo operado
por um driver de camada única ou por um driver de múltiplas camadas, e também
em relação a operações síncronas ou assíncronas.
2.4.1 Tipos de E/S
As aplicações possuem diversas opções para as requisições de E/S que elas
geram. Elas podem especificar E/S síncrona ou assíncrona, E/S que mapeia um
dado de dispositivo em um espaço de endereço da aplicação.
Muitas operações de E/S das aplicações são síncronas, ou seja, a aplicação
espera enquanto o dispositivo realiza a transferência de dados e retorna um
código de estado quando a operação de E/S termina. O programa pode continuar
e acessar os dados transferidos imediatamente. Quando usados em sua forma
mais simples, as rotinas da API Win32 ReadFile e WriteFile são executadas de
forma síncrona. Elas completam uma operação de E/S antes de retornar o
controle ao chamador.
Operações de E/S assíncronas permitem que uma aplicação faça uma
requisição de E/S e continue executando enquanto o dispositivo transfere os
dados. Esse tipo de E/S pode melhorar o tempo de resposta de uma aplicação por
permitir que a mesma continue a realizar outro tipo de trabalho enquanto espera
pelo término de uma operação de E/S. Para usar uma operação assíncrona de
E/S, deve-se especificar um flag denominado FILE_FLAG_OVERLAPPED quando
for chamado a função CreateFile da API Win32. Após emitir a operação
assíncrona de E/S, a thread deve ter cuidado para não acessar nenhum dado da
operação de E/S até o driver de dispositivo terminar a transferência de dados. A
thread deve sincronizar sua execução com o término da requisição de E/S
monitorando um handle de um objeto de sincronização.
Internamente, as operações de E/S são representadas por IRP’s que são
realizados de forma assíncrona, ou seja, uma vez iniciada a requisição de E/S, o
driver de dispositivo retorna ao sistema de E/S. O fato de o sistema de E/S
retornar imediatamente ao chamador depende se o arquivo foi aberto de forma
síncrona ou assíncrona.
Por outro lado, a E/S rápida é um mecanismo especial que permite que o
sistema de E/S vá diretamente ao driver de sistema de arquivo ou ao gerenciador
de cache para completar uma requisição de E/S.
A E/S mapeada em arquivo é um importante esquema do sistema de E/S, o
qual é produzido pelo sistema de E/S e pelo gerenciador de memória. A E/S
mapeada em arquivo refere-se a habilidade de visualizar um arquivo residente em
disco como parte de um processo da memória virtual. Um programa pode acessar
o arquivo como um vetor sem bufferizar os dados ou realizar E/S em disco. A E/S
mapeada em arquivo está disponível em modo usuário através das funções do
subsistema Win32 CreateFileMapping e MapViewOfFile e é rotineiramente usada
para operações importantes como caching um arquivo e ativação de imagem
(carregar e rodar programas executáveis). O gerenciador de cache é um
consumidor importante desse esquema.
Uma operação de requisição de E/S síncrona para um driver de dispositivo
com camada única em modo kernel é descrito a seguir. Tal operação consiste de
sete passos:
1. A requisição de E/S passa pelo subsistema DLL.
2. O subsistema DLL chama o serviço do gerenciador de E/S denominado
NtWriteFile.
3. O gerenciador de E/S aloca um IRP descrevendo a requisição e o envia
para o driver de dispositivo através de uma chamada para a função
IoCallDriver.
4. O driver transfere os dados do IRP para o dispositivo e inicia a operação
de E/S.
5. O driver sinaliza o término da E/S através de uma interrupção da CPU.
6. Quando o dispositivo completa a operação e interrompe a CPU, o driver
de dispositivo dá assistência à interrupção.
7. O driver chama uma função do gerenciador de E/S chamado
IoCompleteRequest, que informa o término do processamento da
requisição de IRP, e o gerenciador de E/S completa a requisição de E/S.
Esses sete passos são descritos na figura a seguir.
Figura 4: Enfileirando e completando uma requisição de E/S
Após um dispositivo de E/S completar uma transferência de dados, ocorre uma
interrupção e o kernel do Windows NT, o gerenciador de E/S e o driver de
dispositivo são chamados. Quando uma interrupção de dispositivo ocorre, o
processador transfere o controle para o “trap handler” do kernel, o qual indexa na
tabela de despache de interrupção a localização de uma rotina para tratamento de
interrupção (ISR) para o dispositivo em questão.
2.5 Suporte a RAID
O Windows NT oferece também suporte a RAID, tanto por hardware como por
software. No suporte a RAID por hardware são oferecidos drivers de disco com
capacidade de gerenciar controladoras RAID. Desta forma, diferentes discos
podem trabalhar em conjunto para compor um ou mais discos lógicos. No RAID
por hardware, a própria controladora gerencia a criação e a manutenção da
informação de redundância necessária à recuperação dos dados [OLIVEIRA,
2004].
O suporte a RAID por software é disponível apenas nas versões server do
Windows NT. Ele emula a partir de serviços do sistema operacional o
funcionamento de uma controladora com suporte RAID. Um driver de dispositivo
denominado FTDISK é responsável por essa tarefa. Esse driver oferece RAID 1 e
RAID 5.
2.6 Plug-and-play
Outro detalhe importante a respeito do NT são as melhorias introduzidas na
funcionalidade plug-and-play, ou seja, a capacidade de um sistema de reconhecer
e adaptar-se dinamicamente a alterações ou modificações em sua forma ou
configuração inicial de hardware. Tal melhora traduz-se em um modelo genérico
para implementação e gerência de drivers de dispositivo denominado WDM
(Win32 Driver Model). Este modelo permite fácil portabilidade de drivers de
dispositivos de um sistema operacional para outro. Os drivers de dispositivo que
seguem o WDM permitem compatibilidade a nível de código binário entre todas as
plataformas baseadas em processadores x86 executando Windows NT e Windows
98, e são portáveis a nível do código fonte para qualquer outra arquitetura.
2.7 Suporte a multiprocessamento
O Windows NT oferece suporte a multiprocessamento. Um ambiente
multiprocessado é aquele em que o mesmo código pode rodar simultaneamente
em mais de um processador. Embora todo o sistema operacional precise estar
envolvido com tal característica, é no sistema de E/S que o multiprocessamento
fica mais evidente, mais especificamente nos drivers de dispositivo.
Um driver pode ser executado em dois ou mais processadores
simultaneamente, necessitando de uma sincronização aos dados do mesmo.
Técnicas de exclusão mútua para proteção a recursos compartilhados devem ser
utilizadas, já que, em um ambiente multiprocessado, podem ocorrer erros por
inconsistência de dados.
2.8 Recuperação de falha de energia
Cada driver de dispositivo tem de saber quando efetivamente ocorreu uma
falha de energia, reajustando posteriormente o dispositivo por ele operado.
Qualquer operação de E/S que tenha sido interrompida deve ser reinicializada,
mas se isso não for possível, pelo menos o gerenciador de E/S deve ser notificado
da falha em uma operação de E/S a fim de retornar uma condição de erro.
O gerenciador de E/S, juntamente com o kernel, oferece um recurso que
permite aos drivers de dispositivo lidar de forma razoavelmente tranqüila com
interrupções no fornecimento de energia elétrica. Quando a energia acaba, ocorre
uma interrupção de falha de energia e o sistema operacional tem um breve
período de tempo para preparar-se para o blecaute. O kernel copia rapidamente
para a memória todos os registros importantes do sistema, incluindo o contador de
programa. Se a memória do computador estiver equipada com uma bateria
reserva, estas informações são gravadas e, quando a energia voltar, o kernel e o
sistema de E/S podem usá-las para reiniciar ou encerrar as operações de E/S que
foram interrompidas. O sistema de E/S pode reiniciar ou encerrar as operações de
E/S que foram interrompidas.
No Windows NT, cada driver de dispositivo pode executar várias tarefas para
ajudar na recuperação de falha de energia elétrica. Primeiro, cada driver de
dispositivo pode criar e registrar uma rotina de recuperação de energia que
reajusta o dispositivo para um estado conhecido após o blecaute. Depois de
restaurado o fornecimento, o kernel localiza e executa a rotina de cada driver.
Segundo, cada driver assegura que não será possível ocorrer uma interrupção
de falha de energia enquanto o driver estiver gravando seqüências de dados
críticos em seu dispositivo. Isto é importante porque, quando o fornecimento
elétrico for restaurado, o processador dará continuidade a sua execução no
contador de programa em que foi interrompido.
3. GERENCIAMENTO DE MEMÓRIA
A arquitetura de memória do Windows NT é um sistema de memória virtual
paginada por demanda. É baseada em um espaço de endereçamento contínuo e
linear de 32 bits, que permite a cada processo do Windows NT acessar até 4 GB
de memória. O Windows NT mapeia os endereços da memória virtual para a
memória física em blocos de 4 KB, denominados páginas. Utilizando a memória
virtual do Windows NT, parte do código e algumas informações dos aplicativos são
mantidas na RAM, enquanto outras informações podem ser paginadas
temporariamente na memória virtual. Quando as informações paginadas são
requisitadas, o Windows NT as carrega de volta para a RAM, paginando outras
informações para a memória virtual, se necessário. Este modelo de memória
permite que os usuários executem aplicativos que utilizam mais memória do que a
que o hardware suporta.
Neste trabalho, apresentaremos como funciona o Gerenciamento de
Memória no Windows NT, como o Windows NT implementa a memória virtual e
como ele gerencia o subconjunto mantido na memória física. Estas atividades
envolvem duas tarefas principais:
• Traduzir ou mapear o espaço de endereços virtuais de um processo para a
memória física.
• Paginar parte do conteúdo da memória para o disco quando ela se tornar
insuficiente e trazer o conteúdo de volta para a memória física quando for
necessário.
Além de fornecer o gerenciamento de memória virtual de 32 bits, o
gerenciador de memória fornece um conjunto básico de serviços em que os vários
subsistemas de ambiente do Windows NT são montados. Esses serviços incluem
arquivos mapeados na memória (internamente chamados section object), memória
de copy-on-write e suporte para aplicações usando espaços de endereços
grandes e esparsos. Neste trabalho, mostraremos esses serviços básicos e
explicaremos os conceitos pertinentes, como memória reservada versus
comprometida, memória compartilhada e também a estrutura interna e os
elementos que compõem o gerenciador de memória.
3.1 Memória Virtual
A memória virtual do Windows NT foi implementada por Lou Perazzoli. Lou
estabeleceu as seguintes metas para o gerenciador de memória virtual:
• Torná-lo o mais portátil possível.
• Ser confiável e eficiente em aplicações de todos os tamanhos, sem exigir
adaptações do sistema por um usuário ou administrador.
• Proporcionar recursos modernos de gerenciamento de memória, como
arquivos mapeados, memória do tipo copy-on-write e suporte a aplicações
que usam espaços de endereçamento grandes e possivelmente escassos.
• Permitir aos processos alocar e gerenciar a memória privativa.
• Proporcionar mecanismos que suportam os subsistemas de ambiente,
como permitir a um subsistema (com os direitos apropriados de acesso)
gerenciar a memória virtual de um processo cliente.
• Equilibrar as necessidades de multiprocessamento com velocidade de
acesso à memória. (Por exemplo, proteger as estruturas de dados usando
vários níveis de bloqueio pode aumentar o paralelismo no gerenciador de
memória virtual, mas cada bloqueio pode criar improdutividade adicional).
O espaço de endereçamento virtual é o conjunto de endereços de memória
disponíveis para uso pelas threads de um processo. Todo processo tem um
espaço de endereçamento virtual exclusivo que normalmente é muito maior do
que a memória física.
Apesar de o número de endereços físicos de um determinado computador
ser limitado pela quantidade de memória que o mesmo possui, o número de
endereços de memória virtual só é limitado pelo número de bits de um endereço
virtual.
A discrepância entre um espaço de endereçamento físico e um espaço de
endereçamento virtual torna inevitável as duas tarefas de um sistema de memória
virtual:
• Traduzir, ou mapear um subconjunto dos endereços virtuais de cada
processo para localizações de memória física. Quando uma thread lê ou
escreve em seu espaço de endereçamento virtual, o sistema de memória
virtual usa o endereço virtual para encontrar o endereço físico correto antes
de transferir os dados.
• Gravar parte do conteúdo de memória para o disco quando as threads do
sistema tentam usar mais memória do que há fisicamente disponível.
A movimentação de dados da memória para o disco (e vice-versa) seria
absurdamente lenta se o gerenciador de memória virtual movesse um byte de
cada vez. É por isto que o espaço de endereçamento virtual é dividido em blocos
de tamanho igual, chamados páginas. Já a memória física é dividida em blocos
chamados de estruturas de página, que são usados para conter páginas. Cada
processo tem um conjunto de páginas de seu espaço de endereçamento virtual
presente na memória física em um dado momento. As páginas que estão na
memória física e estão disponíveis são chamadas de páginas válidas. As páginas
que estão armazenadas em disco (ou que estão na memória, mas não
disponíveis) são chamadas de páginas inválidas, conforme ilustra a Figura 5.
Figura 5: Mapeando Páginas Virtuais para estruturas de página físicas
Quando uma thread em execução acessa um endereço virtual em uma
página marcada como inválida, o processador emite uma trap de sistema
chamada de falta de página. O sistema de memória virtual localiza a página
solicitada no disco e carrega-a para uma estrutura de página livre na memória
física. Quando o número de estruturas de página disponíveis fica baixo, o sistema
de memória virtual seleciona estruturas de página para serem liberadas e copia
seu conteúdo para o disco. Esta atividade, conhecida como paginação, é
imperceptível ao programador.
Apesar do mapeamento de endereços virtuais para endereços físicos e a
transferência de dados de (ou para o) armazenamento swap serem as principais
tarefas de um sistema de memória virtual, ele precisa cumprir outras obrigações
também:
• Permitir que dois processadores compartilhem a memória com facilidade e
eficiência.
• Proteger tanto a memória compartilhada quanto a memória privativa contra
acesso desautorizado.
• Se for executado em computadores multiprocessados, precisa responder a
faltas de página de mais de uma thread de cada vez.
3.2 Gerenciando a Memória
O gerenciador de Memória Virtual fornece um conjunto de serviços nativos
que um processo pode usar para gerenciar diretamente sua memória virtual. Estes
serviços permitem que um processo faça o seguinte:
• Aloque memória em um processo de dois estágios.
• Leia e escreva na memória virtual.
• Bloqueie páginas virtuais na memória física.
• Obtenha informações sobre páginas virtuais.
• Proteja páginas virtuais.
• Execute a operação de swapping.
3.2.1 Estados de uma página virtual
Cada página virtual pode estar em um destes três estados: livre, reservado,
ou commited.
O gerenciador de memória virtual estabelece uma abordagem de duas
fases para alocar memória: reservado e commited, através da função VirtualAlloc.
Essas duas fases podem ser chamadas na mesma chamada de função através da
função VirtualAllocEx.
Uma página livre não está em uso atual e uma referência para ela causará
uma falta.
Quando um processo inicia, todas suas páginas estão no estado de livre até
o programa e seus dados iniciais serem mapeados para o espaço de
endereçamento. Uma vez que dados ou códigos são mapeados numa página,
está página é dita como commited. Uma referência para uma página commited é
mapeada usando o hardware de memória virtual, e é considerado um sucesso se
a página está na memória principal. Se a página não estiver na memória principal,
uma falta de página ocorre e o sistema operacional faz uma busca no disco para
encontrar essa página e traze-la para a memória principal.
Uma página virtual pode também estar no estado de reservada, significando
que ela não está disponível para ser mapeada até a reserva ser removida
explicitamente. Uma referência a uma página reservada causará uma falta, pois
ela não está mapeada. Pode-se ver a vantagem de possuir página reservada
quando, por exemplo, uma nova thread é criada, 1 MB de espaço de pilha é
reservada no espaço de endereçamento virtual do processo, mas apenas uma
página é alocada. Essa técnica significa que a pilha pode crescer eventualmente
até 1 MB sem o receio de que alguma outra thread aloque o pedaço de espaço de
endereçamento virtual contíguo necessário.
Em adição aos atributos livre, reservado e alocado, as páginas possuem
outros atributos, tais como passível de leitura, passível de escrita e executável.
Por questão de desempenho, o Windows NT permite que um processo, com
privilégios necessários, possa bloquear páginas em memória, fazendo com que
essas páginas nunca sofram procedimento swapping.
Finalmente, quando é reservada uma região do espaço de endereços, o
Windows NT assegura que o tamanho da região seja um múltiplo do tamanho da
página do sistema, qualquer que seja. Por exemplo, como os sistemas x86 usam
páginas de 4 KB, se se tentasse reservar uma região da memória com 18 KB, a
quantidade real reservada em um sistema x86 seria 20 KB.
3.2.2 Memória Compartilhada
Assim como todos os outros componentes do Windows NT, o gerenciador
de memória virtual é totalmente paralelo. Ele roda simultaneamente em todos os
processadores de um computador multiprocessado e tem de compartilhar suas
estruturas de dados com as threads que estão sendo executadas em
processadores diferentes. Portanto, era importante criar uma solução segura e
eficiente para o compartilhamento de memória no Windows NT.
Memória compartilhada pode ser definida como a memória que é visível a
partir de mais de um processo ou que está presente em mais de um espaço de
endereçamento virtual. A abordagem do Windows NT ao compartilhamento de
recursos é implementá-los como objetos protegidos e a memória não é nenhuma
exceção. Dois processos podem compartilhar um mesmo espaço de
endereçamento de memória, ver Figura 6. O Windows NT chama um bloco de
memória compartilhada de section object, e oferece uma abstração de visão para
os processos. Essa abstração consiste em um processo de mapear uma porção
de seu espaço de endereçamento a um objeto, o qual é utilizado por outros
processos para acessos compartilhados a essa porção. O mecanismo de
abstração de visão também permite que em caso de swapping de uma região
compartilhada de memória, as páginas correspondentes a essa região sejam
transferidas ou para a área de swap ou para um arquivo especial chamado
mapped file. Também é possível fixar um endereço virtual para essa região,
permitindo que ela resida sempre em um mesmo endereço virtual em todos os
processos que a utilizam.
Figura 6: Mapeando Visões em uma Seção
O executivo do NT usa os arquivos mapeados para carregar imagens
executáveis para a memória e o gerenciador de cache do sistema usa os arquivos
mapeados para ler e gravar em páginas da cache. O sistema de E/S do NT usa os
arquivos mapeados para executar solicitações de entrada e saída, permitindo ao
gerenciador de memória virtual paginar para o disco qualquer mudança ocorrida,
como parte de suas operações normais de paginação.
3.2.2.1 Section Object
Os objetos de seção, assim como outros objetos, são alocados e
desalocados pelo gerenciador de objetos. Este cria e inicializa um cabeçalho de
objeto, o qual é utilizado para gerenciar os objetos; o gerenciador de memória
virtual define o corpo do section object. O gerenciador de memória virtual também
implementa serviços que as threads do modo usuário podem chamar para
recuperar e alterar os atributos armazenados no corpo dos section object. O
section object pode ser visto na Figura 7.
Figura 7: Section Object
Mapear a visão de um section object torna visível uma parte da seção no
espaço de endereçamento virtual de um processo. Igualmente, desmapear a visão
de um section object remove-a do espaço de endereçamento virtual do processo.
O compartilhamento ocorre quando dois processos mapeiam partes do
mesmo objeto de seção em seus espaços de endereçamento. Quando dois
processos compartilham memória desta maneira, eles precisam sincronizar seus
acessos a ela para evitar a alteração de dados ao mesmo tempo. Eventos,
semáforos ou mesmo bloqueios dependentes do hardware podem ser usados
para sincronizar o acesso a uma seção compartilhada. Os section objects
propriamente ditos não são definidos como objetos de sincronização; ou seja, uma
thread não pode sincronizar sua execução aguardando um handle para um
section object. As aplicações do Win32 podem usar mutexes, eventos, seções
críticas ou semáforos para sincronizar seu acesso ao objeto de mapeamento de
arquivo - equivalente a um section object.
Para mapear a visão de uma seção, o processo precisa primeiro adquirir
um handle para ela. O processo que cria o section object sempre tem um handle.
Outros processos (aqueles com direito de acesso apropriado) podem abrir
handles para o section object se a seção tiver nome. Alternativamente, o processo
pode receber um handle para um section object através de herança ou quando um
outro processo duplica seu handle de seção e passa o handle duplicado para o
processo receptor. O compartilhamento de memória ocorre em todos estes casos.
Se uma seção compartilhada é criada como objeto temporário, o gerenciador de
objetos elimina a memória compartilhada quando a última referência ao section
object é emitida.
3.2.3 Proteção de Memória
O Windows NT oferece proteção de memória para os processos e para o
sistema operacional.
O objetivo dessa proteção é que nenhum processo do usuário possa
inadvertidamente corromper o espaço de endereço de outro processo (ou do
próprio sistema operacional). Essa proteção é fornecida de quatro formas:
• Todas as estruturas de dados e memory pools em nível de sistema usados
pelos componentes do modo kernel do sistema só podem ser acessados
estando no modo kernel. Se houver uma tentativa de violação dessa
condição, o hardware gerará uma falta, que por sua vez o gerenciador de
memória informa a thread como uma violação de acesso.
• Cada processo possui um espaço de endereçamento separado e privado,
protegido contra acesso por qualquer thread que pertença a outro processo
(exceto quando a memória compartilhada está sendo usada, nesse caso,
apenas as páginas compartilhadas podem ser vistas por mais de um
processo).
• Todos os processadores aceitos pelo Windows NT oferecem alguma forma
de proteção de memória controlada pelo hardware (como leitura/escrita,
apenas leitura e assim por diante).
• Os section object da memória compartilhada possuem listas de controle de
acesso (ALCs) padrão do Windows NT, que são verificadas quando os
processos tentam abri-los, limitando assim o acesso da memória
compartilhada aos processos com os devidos direitos.
Essa ultima forma é chamada de cópia-na-escrita (Copy-on-Write). A
proteção de página por cópia-na-escrita é uma otimização que o gerenciador de
memória usa para economizar a memória física. Quando um processo mapeia
uma visão de cópia-na-escrita de um section object que contém páginas de
leitura/escrita, em vez de criar um processo de cópia privada quando a visão for
mapeada, o gerenciador de memória adia a criação de uma cópia das páginas até
que a página seja modificada. Por exemplo, como vemos na Figura 8, dois
processos estão compartilhando três páginas, cada uma marcada como cópia-na-
escrita.
Figura 8: Antes do copy-on-write
Se um thread em qualquer processo escreve na página, uma falta de
gerenciamento de memória é gerada. O gerenciador de memória vê que a escrita
é para uma página de cópia-na-escrita e, em vez de informar a falta como uma
violação de acesso, ele reserva uma nova página de leitura/escrita na memória
física (copiando a página no arquivo de paginação), copia o conteúdo da página
original para a nova página, atualiza a informação de mapeamento de página
correspondente nesse processo apenas para apontar para o novo local e dispensa
a exceção, fazendo assim com que a instrução que gerou a falta seja novamente
executada. Dessa vez, a operação de escrita tem sucesso, mas, como vemos na
Figura 9 a seguir, a página recém copiada agora é privada ao processo que fez a
escrita, e não é visível aos outros processos que ainda compartilham a página de
cópia-na-escrita. Cada novo processo que escreve nessa mesma página
compartilhada também receberá sua própria cópia privada.
Figura 9: Depois do copy-on-write
A cópia-na-escrita é usada para implementar o suporte para ponto de
interrupção (breakpoint) nos depuradores.
A proteção de página cópia-na-escrita é um exemplo de uma técnica de
otimização chamada Avaliação Preguiçosa (lazy evaluation), que o gerenciador de
memória virtual utiliza sempre que possível. Os algoritmos de avaliação
preguiçosa evitam efetuar uma operação dispendiosa até que ela seja
absolutamente necessária. Se a operação nunca foi solicitada, então não se perde
tempo com ela.
3.3 Implementação
A maioria dos sistemas operacionais de 32 bits utilizam um espaço de
endereçamento virtual de até 4 GB de memória virtual, separando metade dessa
memória virtual para o sistema operacional e a outra metade para dados e códigos
dos usuários. O Windows NT também utiliza esse método e podemos observar
essa distribuição na Figura 10. O NT também oferece uma opção para modificar a
alocação de memória para um processo, de forma que esse possa ter 3 GB para
usuário e apenas 1 GB ao sistema operacional. Essa modificação é muito útil para
algumas aplicações, tais como banco de dados, que passaram a poder armazenar
uma parcela maior de dados dentro do espaço endereçado da própria aplicação.
O Windows NT ainda prevê uma extensão denominada VLM(Very Large Memory),
para arquiteturas de 64 bits, que permite um processo usuário alocar até 28 GB de
memória virtual suplementar.
Figura 10: Espaço de Endereçamento Virtual
Os primeiros e os últimos 64KB do espaço de endereçamento virtual de
cada processo normalmente não são mapeados. Esta escolha foi feita
intencionalmente para ajudar na captura de erros dos programas. Ponteiros
inválidos freqüentemente possuem os valores 0 ou -1 e tentativas de usá-los no
Windows NT causariam uma parada imediata, ou pior, escreveriam em um local
incorreto da memória. Em contra partida, quando está sendo rodado em modo de
emulação programas do antigo MS-DOS, esses 64 + 64 KB podem ser mapeados.
A partir do kilobyte 64, temos os códigos e dados privados do usuário, isto
extende-se até quase 2 GB. Os últimos pedaços dos primeiros 2 GB contém
alguns contadores do sistema e temporizadores que são compartilhados para
todos os usuários dando-lhes permissão de leitura, somente. Isso permite aos
processos acessá-los sem um overhead de chamada de sistema. Os outros 2 GB
são compartilhados entre todos os processos, exceto a tabela de páginas, o qual
cada processo utiliza a sua. Esses 2 GB não são passiveis de escrita e também
não podem ser lidos por processos de modo usuário.
3.3.1 Mecanismos de Paginação
Todo processador que suporta a memória virtual o faz de maneira diferente.
Conseqüentemente, o código que tem interface direta com o hardware de
memória virtual não é portátil e tem de ser modificado para cada plataforma.
Os endereços virtuais freqüentemente usados provavelmente têm inserções
na TLB (Translation Look-aside Buffer), que propicia traduções extremamente
rápidas de endereço físico para virtual. Se um endereço virtual não está presente
na TLB, ele poderá estar na memória, mas o software de memória virtual terá de
encontrá-lo, caso em que o tempo de acesso é ligeiramente mais lento. Se uma
página virtual foi paginada fora da memória, o sistema de memória virtual invalida
sua entrada na TLB. Se um processo a acessa novamente, ocorre uma falta de
página e o gerenciador de memória virtual traz a página novamente para a
memória e recria uma entrada para ele na TLB.
O kernel e o gerenciador de memória virtual usam tabelas de páginas
criadas por software para encontrar páginas que não estão presentes na TLB. As
tabelas de páginas estão disponíveis na maioria dos sistemas de memória virtual:
às vezes, elas são implementadas pelo hardware, e às vezes, pelo software. Em
termos conceituais, a tabela de páginas assemelha-se à estrutura de dados
mostrada na Figura 11.
Figura 11: Tabela de Páginas Conceitual
Uma entrada na tabela de páginas (PTE - page table entry) contém todas
as informações necessárias para o sistema de memória virtual localizar uma
página quando uma thread usa um endereço. Em um sistema de memória virtual
simples, uma entrada inválida em uma tabela de páginas significa que a página
não está na memória física e tem de ser carregada do disco. Ocorre uma exceção
de falta de página e o software de paginação carrega a página solicitada para a
memória e atualiza a tabela. O processador reemite a instrução que gerou a falta
de página. Desta vez, porém, a inserção da tabela de páginas é válida e os dados
são recuperados da memória com sucesso.
No momento de localizar uma entrada na tabela de páginas, o gerenciador
de memória virtual (e o kernel do NT) traduz o endereço virtual do formato MIPS
para o endereço no formato Intel, usando partes diferentes dele como
deslocamentos na estrutura da tabela de páginas. Além disso, uma inserção na
TLB sempre contém o endereço virtual base do diretório de página do processo
atualmente em execução (É este o motivo pelo qual um processo usuário não
pode “ver” o espaço de endereçamento do outro. Eles têm diretórios de página
diferentes, que apontam para tabelas de páginas diferentes).
As entradas da tabela de páginas nestas tabelas definidas pelo NT
representam um aperfeiçoamento sobre a tabela conceitual mostrada
anteriormente. Cada entrada da tabela de páginas (e cada entrada do diretório de
página) tem um sinalizador de transição. Se a entrada da tabela de páginas está
marcada como inválida e o sinalizador de transmissão está ativado, a página é
escolhida para ser reutilizada, mas seu conteúdo ainda é válido. Validar uma
página transicional é uma operação muito rápida porque o gerenciador de
memória virtual não precisa ler a página do disco para a memória. As entradas da
tabela de páginas também contêm sinalizadores que registram as proteções a
nível de página que o gerenciador de memória virtual aplica a cada página.
Quando uma estrutura de página é compartilhada por dois processos, o
gerenciador de memória virtual insere um artifício nas suas tabelas de páginas. A
estrutura de dados que ele insere é chamada de protótipo de entrada na tabela de
páginas (protótipo PTE).
O protótipo PTE, uma estrutura de 32 bits que parece com uma entrada de
tabela de páginas normal, permite ao gerenciador de memória virtual gerenciar as
páginas compartilhadas sem precisar atualizar as tabelas de páginas de cada
processo que compartilha a página. Por exemplo, uma página de código ou de
dados compartilhada pode ser paginada para o disco em um determinado
momento. Quando o gerenciador de memória virtual recupera a página do disco,
ele só precisa atualizar o ponteiro armazenado no prótipo PTE para a nova
localização física, e as tabelas de páginas permanecem as mesmas. Os protótipos
de PTE são alocados no espaço paginado do sistema, portanto, como as entradas
na tabela de páginas, podem sofrer swapout, se necessário.
3.3.2 Políticas de Paginação
Os sistemas de memória virtual geralmente definem três políticas que ditam
como (ou quando) a paginação é efetuada: uma política de busca, uma política de
colocação e uma política de substituição.
A política de busca determina quando o paginador deve trazer a página do
disco para a memória. Um tipo de política de busca tenta carregar as páginas que
um processo irá precisar antes que ele as solicite. Outras políticas de busca,
chamadas de políticas de paginação por demanda, carregam uma página para a
memória física apenas quando ocorre uma falta de página. Em um sistema de
paginação por demanda, o processo incorre em muitas faltas de página quando
suas threads são executadas pela primeira vez, porque elas fazem referência ao
conjunto inicial de páginas que lhes são necessárias. Depois que este conjunto de
páginas é carregado para a memória, a atividade de paginação do processo
diminui.
Quando uma thread recebe uma falta de página, o sistema de gerencia-
mento de memória também tem de determinar onde colocar a página virtual na
memória física. O conjunto de regras que ele usa chama-se política de colocação.
As políticas de colocação, embora normalmente complicadas para arquiteturas de
memória segmentada, em geral são simples para arquiteturas lineares, que
requerem que apenas uma estrutura de página livre seja encontrada. No NT, se a
memória não está esgotada, o gerenciador de memória virtual simplesmente
seleciona a primeira estrutura de página em uma lista de estruturas de página
livres. Se a lista está vazia, ele cruza uma série de outras listas por ele mantidas;
a ordem dependerá do tipo de falta de página ocorrido.
Se a memória física estiver repleta quando ocorrer uma falta de página,
uma política de substituição é usada para determinar que página virtual deve ser
removida da memória para liberar espaço para a página nova. As políticas de
substituição de página no Windows NT variam de acordo com a arquitetura ou
processador. Para arquiteturas do tipo multiprocessador baseadas em
processadores da família Intel, e em todas as máquinas baseadas em
processadores da família Alpha, a estratégia utilizada é essencialmente FIFO
(First In, First Out) local. Nessa estratégia, considera-se para fins de seleção da
página a ser substituída em memória, apenas as páginas pertencentes ao
processo. Nas arquiteturas de monoprocessadores Intel, o algoritmo de seleção
de página a ser substituída é LRU (least recently used). Implementado através do
algoritmo do relógio, o algoritmo LRU exige que o sistema de memória virtual
registre quando uma página de memória é usada. Quando uma nova estrutura de
página é solicitada, a página que não foi usada há mais tempo é paginada para o
disco e sua estrutura é liberada para satisfazer a falta de página.
3.3.3 Gerenciamento da memória física
O número de páginas que um processo ocupa na memória é armazenado
através do mecanismo de working set. Para cada processo, é definido um valor
mínimo e um valor máximo para o tamanho desse working set, a partir do tamanho
da memória física. Quando há uma elevada ocorrência de falta de página, o
gerenciador da memória inicia uma verificação do working set de todos os
processos residentes na memória. Os processos que tiverem mais páginas na
memória que o valor mínimo terão seus working sets reduzidos, e suas áreas de
memórias liberadas serão disponibilizadas para serem alocadas por outros
processos.
O gerenciador da memória física armazena a movimentação das páginas
na memória através de listas
. Cada página contida na memória está presente dentro do working set de algum
processo ou em algumas dessas listas. Essas listas são apresentadas a seguir:
• Listas de páginas disponíveis (limpas): contêm as páginas que foram
recentemente removidas do working set de algum processo, mas ainda
estão associadas a ele. Essas páginas possuem uma cópia no disco,
podendo assim, serem descartadas pelo processo.
• Listas de páginas modificadas (sujas): contêm as páginas que também
foram recentemente removidas do working set de algum processo, mas
ainda estão associadas a ele. Essas páginas porém não possuem uma
cópia atualizada no disco.
• Listas de páginas livres: contém as páginas que não estão associadas a
nenhum processo.
• Listas de páginas zeradas: contém as páginas que também não estão
associadas a nenhum processo, mas estão preenchidas com zero.
• Listas de páginas com defeito físico: contém as páginas que estão
relacionadas com alguma porção de memória RAM que apresenta defeito.
• Essa lista garante que tais páginas não serão mais acessadas.
3.3.4 Tradução de Endereços
A tradução de um endereço virtual em um endereço físico é realizada da
seguinte forma. Inicialmente, utilizando a parte mais significativa do endereço
virtual (índice de diretório de páginas), o diretório de páginas é acessado para
determinar qual tabela de páginas está associada ao endereço virtual que se
deseja traduzir. Uma vez definida a tabela de páginas, o índice de tabela de
páginas é empregado para determinar a página correspondente a esse endereço
virtual. A entrada da tabela de páginas fornece informações de controle e a
localização em memória da página a ser acessada (se presente). Finalmente, o
índice de byte é somado ao endereço inicial da página em memória, resultando no
endereço físico correspondente ao endereço virtual desejado. A Figura 12
apresenta a relação entre esses três valores e a forma pela qual eles são
utilizados para mapear um endereço virtual em endereço físico.
Figura 12: Esquema de tradução de endereço virtual para endereço físico em arquiteturas Intel
Cada processo possui um único diretório de página para mapear a
localização das tabelas de paginas pertencentes a esse processo. O diretório de
páginas possui 1024 entradas o que limita o numero máximo de tabelas de
páginas de um processo. As tabelas de paginas são criadas sob demanda; por
conseqüência, normalmente, muitas das entradas do diretório de paginas não são
válidas. Cada tabela de página possui, por sua vez, também 1024 entradas, o que,
de forma análoga, limita a quantidade de páginas por tabela de páginas. O
tamanho de cada entrada, tanto do diretório de paginas quanto da tabela de
paginas, é de 4 bytes. Isso implica que cada uma dessas estruturas ocupem 4 KB
de memória, ou seja, exatamente uma página. Essas tabelas são armazenadas no
espaço de endereçamento virtual do processo, na área destinada ao sistema
operacional, e sua localização exata é mantida no descritor de processo.
3.3.5 Tratamento de Falta de Página
Uma referência a uma página inválida é chamada falta de página. O
manipulador de trap do kernel despacha esse tipo de falta para o manipulador de
falta do gerenciador de memória (MmAccessFault) resolver. Essa rotina é
executada no contexto da thread que incorreu na falta e é responsável por tentar
resolver a falta (se possível) ou levantar uma exceção apropriada.
Páginas no Windows NT variam de 4 KB à 64 KB, dependendo da
arquitetura. O Pentium, por exemplo, utiliza 4 KB. O algoritmo de paginação do
Windows NT é baseado por demanda com clustering (em grupos). Quando ocorre
uma falta de página, o gerenciador de memória carrega na memória a página que
faltava e mais um pequeno número de páginas ao seu redor. Essa estratégia visa
minimizar a taxa de faltas, explorando o princípio de localidade.
Quando um processo é iniciado, são trazidas páginas para a memória a
medida que ocorrem faltas de páginas. Essas faltas ocorrem quando:
• A página referenciada não está commited.
• A página está commited, mas não está mapeada.
• Uma página compartilhada foi escrita.
• Ocorreu uma violação de proteção.
• A pilha precisa crescer.
3.3.6 Descritores de Endereço Virtual
Anteriormente nós descrevemos as políticas de paginação que o
gerenciador de memória virtual usa para determinar quando uma página deve ser
trazida para a memória, onde colocá-la e que páginas remover quando a memória
se esgota.
O gerenciador de memória virtual usa um algoritmo de paginação por
demanda para saber quando carregar páginas para a memória. Ele espera até
que alguma thread use um endereço e incorra em uma falta de página para depois
recuperar uma página do disco. Este tipo de paginação por demanda é uma forma
de avaliação preguiçosa. Os algoritmos de avaliação preguiçosa evitam executar
uma operação dispendiosa, como a paginação, até que ela seja absolutamente
necessária.
O gerenciador de memória virtual usa a avaliação preguiçosa em uma outra
área, aquela da construção de tabelas de páginas. Por exemplo, quando uma
thread aloca uma grande região de memória virtual, o gerenciador de memória
virtual poderia construir imediatamente as tabelas de páginas necessárias para
acessar toda a faixa de memória alocada. Entretanto, se a aplicação não usa toda
a memória alocada, a construção das tabelas de páginas é um esforço inútil.
Conseqüentemente, o gerenciador de memória virtual espera para construí-las
somente quando uma thread incorre em uma falta de página. O uso da avaliação
preguiçosa desta maneira resulta em ganho significativo de desempenho para as
aplicações que reservam muita memória, mas raramente a usam.
Alocar memória, mesmo grandes blocos de memória, é extremamente
rápido com o algoritmo de avaliação preguiçosa. No entanto, o ganho de
desempenho também tem suas desvantagens. Quando uma thread aloca
memória, o gerenciador de memória virtual tem de responder com uma faixa de
endereços virtuais que a thread poderá usar. Contudo, como o gerenciador de
memória virtual só carrega a tabela de páginas do processo quando a thread
acessa a memória, ele não tem condições de examinar a tabela de páginas para
determinar que endereços virtuais estão livres. Portanto, o gerenciador de
memória virtual precisa manter um outro grupo de estruturas de dados para
registrar que endereços virtuais já foram alocados no espaço de endereçamento
do processo e quais ainda não foram. Os descritores de endereço virtual atendem
esta necessidade.
Para cada processo, o gerenciador de memória virtual mantém um conjunto
de descritores de endereço virtual que descrevem o status do espaço de
endereçamento virtual do processo.
Quando um processo aloca memória (ou mapeia uma visão de memória
compartilhada), o gerenciador de memória virtual cria um descritor de endereço
virtual para armazenar qualquer informação fornecida na solicitação de alocação,
como a faixa de endereços que está sendo alocada, se a faixa será memória
compartilhada ou privativa, se um processo filho pode herdar o conteúdo da faixa,
e a proteção aplicada às páginas daquela faixa. Depois ele insere o descritor de
endereço virtual em uma árvore específica do processo (uma árvore binária
equilibrada) para acelerar sua localização.
Quando uma thread acessa um endereço pela primeira vez, o gerenciador
de memória virtual precisa criar uma entrada na tabela de páginas para a página
que contém o endereço. Para tanto, ele localiza o descritor de endereço virtual
cuja faixa de endereço também contém o endereço acessado e usa a informação
encontrada para preencher a entrada na tabela de páginas. Se o endereço estiver
fora da faixa coberta pelo descritor de endereço virtual, o gerenciador de memória
virtual saberá que a thread não alocou este endereço de memória antes de usá-lo.
Ocorre então, uma violação de acesso.
3.4 Chamadas ao Sistema
O Win32 API contém um numero de funções que permitem que um processo
gerencie sua própria memória virtual. Essas funções operam sobre uma seqüência
de duas ou mais páginas consecutivas no espaço de endereçamento virtual. A
Figura 13 mostra algumas dessas funções.
Função API Win 32 Descrição
VirtualAlloc Reserva ou commit uma região
VirtualFree Libera ou uncommit uma região
VirtualProtect Altera a proteção de leitura/escrita/execução de uma região
VirtualQuery Pergunta sobre o estado de uma região
VirtualLock Torna uma região residente em memória
VirtualUnlock Torna a região paginável, da maneira usual
CreateFile
Mapping
Cria um objeto de mapeamento de arquivo e (opcionalmente)
atribui um nome a ele
MapViewOfFile Mapeia um arquivo, ou parte dele, no espaço de
endereçamento
UnmapViewOfFile Remove um arquivo mapeado do espaço de endereçamento
OpenFileMapping Abre um objeto de mapeamento de arquivo criado
anteriormente
Figura 13: Principais funções API Win32 para gerenciamento da memória virtual
4. GERÊNCIA DE PROCESSOS
4.1 Caracterização de Jobs, Processos, Threads e Fibers
Um Job pode ser considerado como uma coleção de um ou mais processos
que irão ser gerenciados como uma única unidade, compartilhando certos
atributos, além de prover restrições de segurança nos processos que estão no
Job.
Como no Unix, um processo pode ser considerado uma instância em
execução de um programa. Ele tem um espaço de endereçamento privado
contendo seu código e dados. Enquanto ele é executado, o sistema operacional
pode alocar recursos do sistema como semáforos e portas de comunicação. Um
processo tem de ter no mínimo uma Thread, pois a Thread é a unidade a ser
escalonada pelo kernel.
Um processo executando no modo usuário invoca o sistema operacional
através das chamadas de sistema. Através do sistema de traps, o seu modo de
execução passa a ser o modo do sistema (privilegiado) e então ele entra e
executa no sistema operacional e após a execução ele retorna ao modo usuário.
Processos também são representados como objetos, então eles são
manipulados através do serviço de gerenciamento de processos, como mostra a
figura 14. O processo tem uma prioridade base usada para o escalonamento das
Threads e uma afinidade com um processador padrão, que indica o conjunto de
processadores no qual as Threads desse processo irão rodar. O quota limit
especifica a quantidade máxima de memória paginada e não-paginada e tempo de
processador. O tempo total de CPU e os recursos utilizados pelo processo são
contados em tempo de execução, assim como os contadores de E/S e os
contadores de operação da máquina virtual.
Figura 14: Representação de um processo como objeto
Um processo pode criar múltiplas Threads para executar no seu espaço de
endereçamento e ambos os objetos do processo e objetos das Threads possuem
capacidade de sincronização embutida. Threads são executadas no modo usuário
durante grande parte do tempo, mas ao realizar uma chamada ao sistema, elas
rodam no modo kernel, retendo suas características anteriores. Para administrar a
mudança de modo de execução, cada Thread possui duas pilhas, uma usada no
modo usuário e outra usada no modo kernel. Uma vez que uma Thread tenha sido
criada ela é gerenciada de forma independente a seu processo pai, pois não
existe nenhuma forma de hierarquia entre os processos no Windows NT. A figura
15 mostra o objeto que representa uma Thread. O ID do cliente identifica uma
Thread de forma única. O contexto da Thread inclui o estado de memória da
Thread e o seu estado de execução. Outro fato importante de salientar é que
somente a Thread tem um indicador do estado da execução, visto que ela é a
unidade básica a ser escalonada.
Figura 15: Representação de uma Thread como um objeto
Também existe uma forma de Thread leve, que é chamada de Fiber. Ao
contrário de Threads, Fibers são totalmente gerenciadas no modo usuário e são
invisíveis para o kernel. O Kernel gerencia as Threads e uma Thread em execução
pode cooperativamente mudar de uma Fiber para outra através da diretiva
SwitchToFiber. Cada Fiber tem um registro de estado associado, uma pilha,
informação de tratamento de exceções e o valor de dado da Fiber. Esse
gerenciamento de escalonamento no nível de usuário significa que para o
funcionamento das Fibers é necessário cuidado. Se um bloco de uma Fiber em
execução é bloqueado, toda a Thread é bloqueada. Uma aplicação utilizando
fibers só pode aproveitar o poder de multiprocessamento caso exista mais de uma
Thread no processo, e precisará ter controle de concorrência, pois pode ocorrer de
diversas threads tentarem ceder a execução para uma Fiber. Uma aplicação que
deseja usar Fibers deve utilizá-la explicitamente através do comando
ConvertThreadToFiber.
4.2 Técnicas de comunicação
Existem diversas técnicas para a comunicação entre threads, sendo alguma
delas as pipes, pipes nomeados, mailsots, sockets, chamadas remotas de
procedimento e arquivos compartilhados.
Pipes tem dois modos de operação, byte e mensagem, selecionados em
tempo de criação. O modo de byte funciona de forma análoga ao Unix, e o modo
de mensagem preserva os limites de cada uma das mensagens. Pipes nomeados
funcionam como pipes comuns, mas com suporte a uso na rede.
Mailslots tem funcionamento similar ao de pipes, mas com algumas
diferenças, como é uma técnica de comunicação unidirecional, enquanto pipes
são bidirecionais. Mailslots tem suporte a transmissão via rede, mas sem garantia
de entrega da mensagem. Outra característica importante é que mailslots
permitem a transmissão de uma mensagem para diversos destinatários.
Sockets tem principal utilização na conexão de processos em máquinas
diferentes (remotas). Sockets podem até ser utilizados para conectar processos
na mesma máquina, mas devido a ter um overhead mais alto que pipes, sua
utilização fica mais restrita ao contexto de uma rede.
A chamada de procedimentos remotos é uma maneira de comunicação que
permite que um processo tenha acesso ao espaço de endereçamento de outro
processo. Esta técnica tem restrições nos parâmetros, visto que seria inútil
repassar um ponteiro para um processo diferente.
Arquivos compartilhados são simplesmente áreas de memória
compartilhada entre processos, possibilitando que um processo altere e outro leia
as informações em uma área de memória especificada.
4.3 Técnicas de sincronização
Assim como as técnicas de comunicação entre os processos, existem
diversas técnicas de sincronização, para prover uma alternativa viável para cada
tipo de situação. Algumas das técnicas de sincronização são semáforos, mutex,
regiões criticas e eventos. Todas essas ferramentas são aplicáveis a threads, não
a processos, visto que somente processos são escalonáveis.
Semáforos são criados pela função CreateSemphore da API, que o inicia
com um valor e também determina o valor máximo. Semáforos são objetos do
kernel e tem descritores de segurança e handles. O handle para um semáforo
pode ser duplicado utilizando DuplicateHandle e então o semáforo pode ser
repassado para outros processos, permitindo sua utilização em múltiplos
processos.
Mutex são objetos do kernel utilizados para sincronização, mas com uma
estrutura mais simples do que semáforos devido a ausência de contadores.
Funcionam essencialmente com duas operações da API, WaitForSingleObject
(responsável pelo bloqueio) e ReleaseMutex (responsável pela liberação). Os
handles do mutex também podem ser duplicados, possibilitando o uso de um
mutex para controle de threads em processos diferentes.
Seções críticas são similares a mutex, mas são locais em relação a thread
que as criou, ou seja, não são objetos do kernel, não tendo descritores de
segurança ou handles, logo só são vistas por um processo. O bloqueio e a
liberação são realizadas pelas funções EnterCrticalSection e LeaveCriticalSection,
respectivamente. Devido a essas funções da API serem executadas no espaço do
usuário e somente realizarem chamadas ao kernel quando é necessário realizar o
bloqueio, essa técnica é mais rápida que mutex.
O último tipo de sincronização são os eventos, que podem ser de dois tipos,
eventos de reset manual ou eventos de reset automático. Um evento pode estar
em dois estados, setado ou livre. Uma thread pode esperar por um evento através
da função WaitForSingleObject. Se outra thread sinalizar um evento com
SetEvent. O que ocorre após o evento ser setado depende do tipo de evento: em
um evento de reset manual todos os threads na espera são liberados, o evento
permanece setado até que seja usado o comando ResetEvent; no caso com reset
automático, se uma ou mais threads estão esperando, somente uma thread é
liberada, e o evento fica livre.
4.4 Criação de Processos e Threads
A criação de novos processos é realizada pela função CreateProcess,
sendo uma forma mais complexa do que a criação de processos em Unix, devido
ao fato dessa função levar dez parâmetros, que são citados a seguir:
1. Um ponteiro para o nome do arquivo executável.
2. A própria linha de comando.
3. Um ponteiro para o descritor de segurança do processo.
4. Um ponteiro para o descritor de segurança da thread inicial.
5. Um bit que define se o processo herda o handle do criador.
6. Diversos flags.
7. Um ponteiro para strings do ambiente.
8. Um ponteiro para o nome do diretório atual do novo processo.
9. Um ponteiro para a estrutura que descreve a janela inicial na tela.
10. Um ponteiro para a estrutura que retorna 18 valores para o
realizador da chamada.
Apesar de não haver hierarquia entre os processos, um dos valores
retornados ao realizador da chamada é o handle do novo processo, assim é
possível uma hierarquia implícita entre os processos.
A criação de threads por sua vez é relativamente menos complexa que a
criação de processos, utilizando a função CreatThread e tendo somente 6
parâmetros, descritos a seguir:
1. O descritor de segurança opcional.
2. O tamanho inicial da pilha.
3. O endereço inicial.
4. Um parâmetro definido pelo usuário.
5. O estado inicial da Thread (pronta ou bloqueada).
6. O ID da Thread.
4.5 Escalonamento
O escalonamento não é realizado por uma thread de escalonamento
central. O sistema de escalonamento consiste em quando uma thread deixa de ser
apta à execução, ela entre no modo do kernel e executa o escalonador para
decidir qual a thread que será executada. Existem três situações que podem
ocorrer para uma thread deixar de ser apta a execução:
1. A thread é bloqueada por uma ferramenta de sincronização.
2. A thread interage com outro objeto.
3. O quantum da thread em questão expira.
No primeiro caso, a thread já estará rodando no modo do kernel, logo ela só
deve salvar seu contexto, acionar o escalonador e escolher o seu sucessor que
será carregado.
No segundo caso, a thread também já estará executando no modo do
kernel, mas sua interação poderá não resultar no seu bloqueio, logo a thread deve
executar o escalonador para descobrir se sua ação não causou a liberação de
uma thread com prioridade maior, pois se isso ocorrer ela deverá ceder a vez.
No terceiro caso, um trap para o modo do kernel ocorre, e então a thread
executará o escalonador, mas dependo do estados das outras threads, a mesma
thread poderá ser selecionada para ser executada, recebendo um novo quantum,
caso contrário será escolhida outra thread.
O escalonador também poder ser chamado em duas outras ocasiões:
1. Quando uma operação de E/S é terminada.
2. Quando um tempo de espera termina.
Quando uma operação de E/S é terminada, uma thread poderá ser liberada,
logo é necessário a execução do escalonador para determinar se essa thread que
será liberada poderá ser executada.
Na segunda situação, uma thread que estava bloqueada tem seu tempo de
espera esgotado, tornando-se apta para a execução novamente e assim é
necessária a execução do escalonador.
O sistema de escalonamento leva em conta um sistema de prioridades com
32 níveis, que variam de 0 a 31, sendo que existe a prioridade base, que é
determinada de acordo com a Figura 16. E também existe a prioridade atual do
processo, que nunca poderá ser menor do que o valor da prioridade base, mas
poderá ser maior de acordo com as situações ocorridas no sistema.
Figura 16: Tabela de prioridades do Windows 2000
5. SISTEMA DE ARQUIVOS
Este capítulo tem por objetivo apresentar o sistema de arquivos do Windows
NT e os formatos que são suportados pelo mesmo. Serão descritos os tipos de
sistemas de arquivo e como eles interagem com os demais componentes do
sistema operacional, como o gerenciador de memória e o gerenciador de cache,
por exemplo. Também será analisado o formato padrão do sistema de arquivos do
NT, denominado NTFS. Tendo sido projetado do zero, não é um aperfeiçoamento
de sistemas de arquivos antigos, e portanto não é sobrecarregado pela
necessidade de ser totalmente compatível com os sistemas de arquivos do MS-
DOS.
5.1 Conceitos Fundamentais do NTFS
O Windows NT suporta vários sistemas de arquivos, entre eles a FAT-16 (File
Allocation Table - 16), FAT-32 (File Allocation Table - 32), NTFS (New Technology
File System), CDFS (CD-Rom File System), UDF (Universal Disk Format). A FAT-
16 é um sistema de arquivos que usa endereços de 16 bits, limitando as partições
de disco em tamanhos de no máximo 2 GB. A FAT-32 é um sistema similar a FAT-
16 que usa endereços de 32 bits, podendo ter uma partição de até 2 TB
(Terabytes). Por sua vez, o NTFS utiliza endereços de 64 bits, podendo assim
suportar partições de até 16 EB (Exabytes), embora outros fatores a limitem a um
tamanho menor.
Tendo sido projetado do zero, o sistema de arquivos NTFS não é um
aperfeiçoamento de sistemas de arquivos antigos, e portanto não é
sobrecarregado pela necessidade de ser totalmente compatível com os sistemas
de arquivos do MS-DOS.
Os nomes de arquivos no NTFS são limitados a 255 caracteres; os caminhos
desde a raiz são limitados a 32767 caracteres. Esses nomes estão em Unicode, o
que permite que pessoas de países que não usam o alfabeto latino utilizem nomes
de arquivos em seu idioma nativo. O NTFS diferencia totalmente letras maiúsculas
de minúsculas, mas a API Win32 não, nem para nomes de arquivos nem para
nomes de diretórios, fazendo com que programas que se restrinjam a usar o
Win32, para compatibilizar com o Windows 98, percam esta vantagem.
Os arquivos NTFS não são apenas seqüências lineares de bytes, como o que
acontece com os arquivos no Unix e no FAT-32. Eles são formados por vários
atributos, representados por fluxos (streams) de bytes. A maioria dos arquivos é
formada por alguns fluxos curtos, como nome de arquivo, ID de objeto de 64 bits,
e mais um fluxo longo, sem nome, com os dados. Entretanto, um arquivo pode ter
dois ou mais fluxos de dados. Cada fluxo tem um nome formado pelo nome do
arquivo, seguido de dois pontos e o nome do fluxo, como nomeDoArquivo:fluxo1.
Cada fluxo tem seu próprio tamanho e pode ser impedido independentemente dos
outros fluxos. Essa idéia de múltiplos fluxos foi importada do Apple Macintosh, no
qual os arquivos têm dois fluxos, os dados e os recursos. Esse conceito foi
incorporado ao NTFS para permitir que um servidor utilizando esse tipo de sistema
de arquivo seja capaz de servir clientes Macintosh.
Os fluxos de arquivos servem para outros propósitos além da compatibilidade
com o Macintosh. Por exemplo, um programa de edição de fotos poderia usar o
fluxo sem nome para a imagem principal e um fluxo com nome para a versão
menor, apenas para visualização. Outro uso dos fluxos dá-se no processamento
de textos. Esses programas freqüentemente fazem duas versões de um
documento; uma temporária, para usar durante a edição e outra final para quando
o usuário terminar de editar. Com a temporária em um fluxo com nome e a final
em fluxos sem nome, ambas as versões compartilham automaticamente o mesmo
nome de arquivo, a mesma informação de segurança, os mesmos indicadores de
tempo, etc., sem trabalho adicional.
Ponteiros de arquivos são usados para acompanhar onde um processo está
em cada fluxo. Esses ponteiros têm 64 bits de largura para tratar o tamanho
máximo de um fluxo, que é cerca de 18,4 Exabytes.
O NTFS é um sistema hierárquico de arquivos, semelhante ao Unix. O
separador entre os nomes dos componentes é '', característica herdada do MS-
DOS. Há o conceito de diretório de trabalho atual e os nomes de caminhos podem
ser tanto relativos quanto absolutos. Também são suportadas ligações rígidas e
simbólicas; as primeiras são implementadas por entradas múltiplas de diretório,
como no Unix; as últimas são implementadas usando pontos de reanálise. Além
disso, compressão, criptografia e tolerância a falhas também são suportados.
5.2 Chamadas de API
As principais funções da API Win32 para gerenciamento de arquivos estão
listadas na Figura 17. Na verdade existem muito mais funções, mas essas são
suficientes para que se compreenda a base do sistema.
Função API Win 32 UNIX Descrição
CreateFile open Cria um arquivo ou abre um arquivo
existente; retorna um handle
DeleteFile unlink Deleta um arquivo existente
CloseHandle close Fecha um arquivo
ReadFile read Lê dados de um arquivo
WriteFile write Escreve dados em um arquivo
SetFilePointer Iseek Seta o ponteiro de arquivo em um lugar
específico no arquivo
GetFileAttributes stat Devolve as propriedades do arquivo
LockFile fcntl Tranca uma região do arquivo para
providenciar exclusão mútua
UnlockFile fcntl Destrava uma região do arquivo previamente
travada
Figura 17: Principais funções API Win32 para funções de arquivos
Não é explicado os parâmetros de todas as funções por serem muitos, por
exemplo, os parâmetros para criação de um arquivo(CreateFile) são os seguintes:
• Um ponteiro para o nome do arquivo a ser criado ou aberto.
• Flags indicando se o arquivo pode ser lido, escrito ou ambos.
• Flags indicando se múltiplos processos podem abrir o arquivo ao mesmo
tempo.
• Um ponteiro para o descritor de segurança dizendo quem pode acessar o
arquivo.
• Flags indicando o que fazer se o arquivo existir ou não existir.
• Flags lidando com atributos como: compressão, arquivamento, etc.
• A manipulação de um arquivo cujos atributos devem ser copiados para um
novo arquivo.
5.3 Estrutura do Sistema de Arquivos
Cada volume (ou partição) do NTFS contém arquivos, diretórios, mapas de bits
e outras estruturas de dados. Cada volume é organizado como uma seqüência
linear de blocos (clusters), com o tamanho do bloco sendo determinado para cada
volume, e indo de 512 bytes a 64 KB, dependendo do tamanho do volume. A
maioria dos discos NTFS utiliza blocos de 4 KB como um tamanho que serve
como ponto de equilíbrio entre blocos grandes e blocos pequenos, gerando tanto
transferências eficientes quanto baixa fragmentação interna. Os blocos são
referenciados por seus deslocamentos a partir do início do volume, usando-se
números de 64 bits.
A principal estrutura de dados de cada volume é a MFT (Master File Table),
que é uma seqüência linear de registros com tamanho de 1 KB. Cada registro da
MFT descreve somente um arquivo ou diretório. O registro contém atributos do
arquivo, como seu nome, a lista de endereços de disco onde seus blocos estão
localizados, indicadores de tempo, etc. Caso um arquivo seja muito grande, será
necessário utilizar dois ou mais registros da MFT para abrigar a lista de todos os
blocos. Nesse caso, o primeiro registro da MFT, chamado de registro-base, aponta
para os outros registros da MFT. Um mapa de bits faz o acompanhamento de
quais entradas da MFT estão livres.
A MFT é, em si, um arquivo, e como tal pode ser colocada em qualquer lugar
de um volume, eliminando assim o problema com os setores defeituosos na
primeira trilha. Além disso, o arquivo pode crescer o quanto for preciso, até um
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos
Windows NT: Gerenciamento de E/S, Memória e Processos

Más contenido relacionado

La actualidad más candente

Instalowanie systemów operacyjnych i oprogramowania użytkowego
Instalowanie systemów operacyjnych i oprogramowania użytkowegoInstalowanie systemów operacyjnych i oprogramowania użytkowego
Instalowanie systemów operacyjnych i oprogramowania użytkowegoSzymon Konkol - Publikacje Cyfrowe
 
Funções e caracteristicas de um so
Funções e caracteristicas de um soFunções e caracteristicas de um so
Funções e caracteristicas de um soMiriamMiguel
 
Aula 3 - Sistemas operacionais - Linux
Aula 3 - Sistemas operacionais - LinuxAula 3 - Sistemas operacionais - Linux
Aula 3 - Sistemas operacionais - LinuxLucasMansueto
 
Introdução ao Linux Ubuntu
Introdução ao Linux UbuntuIntrodução ao Linux Ubuntu
Introdução ao Linux UbuntuFilipe Kulinski
 
Урок № 8 Тема. Поняття операційної системи, її призначення. Графічний інтер...
Урок № 8   Тема. Поняття операційної системи, її призначення. Графічний інтер...Урок № 8   Тема. Поняття операційної системи, її призначення. Графічний інтер...
Урок № 8 Тема. Поняття операційної системи, її призначення. Графічний інтер...Валентина Кодола
 
Ubuntu Linux
Ubuntu LinuxUbuntu Linux
Ubuntu Linuxisraeljrs
 
Apresentação Sistemas Operativos TUDO.pdf
Apresentação Sistemas Operativos TUDO.pdfApresentação Sistemas Operativos TUDO.pdf
Apresentação Sistemas Operativos TUDO.pdfHelderRangel
 
Sistemas Operacionais - Aula 02 (Visão geral de sistemas operacionais)
Sistemas Operacionais - Aula 02 (Visão geral de sistemas operacionais)Sistemas Operacionais - Aula 02 (Visão geral de sistemas operacionais)
Sistemas Operacionais - Aula 02 (Visão geral de sistemas operacionais)Leinylson Fontinele
 

La actualidad más candente (20)

Dokumentacja techniczna stanowiska komputerowego
Dokumentacja techniczna stanowiska komputerowegoDokumentacja techniczna stanowiska komputerowego
Dokumentacja techniczna stanowiska komputerowego
 
Curso basico de informtica
Curso basico de informticaCurso basico de informtica
Curso basico de informtica
 
Usługi serwisowe i ich wycena
Usługi serwisowe i ich wycenaUsługi serwisowe i ich wycena
Usługi serwisowe i ich wycena
 
Instalowanie systemów operacyjnych i oprogramowania użytkowego
Instalowanie systemów operacyjnych i oprogramowania użytkowegoInstalowanie systemów operacyjnych i oprogramowania użytkowego
Instalowanie systemów operacyjnych i oprogramowania użytkowego
 
Tworzenie kopii bezpieczeństwa danych
Tworzenie kopii bezpieczeństwa danychTworzenie kopii bezpieczeństwa danych
Tworzenie kopii bezpieczeństwa danych
 
Lokalizowanie i usuwanie uszkodzeń systemu operacyjnego
Lokalizowanie i usuwanie uszkodzeń systemu operacyjnegoLokalizowanie i usuwanie uszkodzeń systemu operacyjnego
Lokalizowanie i usuwanie uszkodzeń systemu operacyjnego
 
Modernizacja i rekonfiguracja komputera osobistego
Modernizacja i rekonfiguracja komputera osobistegoModernizacja i rekonfiguracja komputera osobistego
Modernizacja i rekonfiguracja komputera osobistego
 
Metody odzyskiwania danych
Metody odzyskiwania danychMetody odzyskiwania danych
Metody odzyskiwania danych
 
So-mod-1
So-mod-1So-mod-1
So-mod-1
 
Funções e caracteristicas de um so
Funções e caracteristicas de um soFunções e caracteristicas de um so
Funções e caracteristicas de um so
 
Aula 3 - Sistemas operacionais - Linux
Aula 3 - Sistemas operacionais - LinuxAula 3 - Sistemas operacionais - Linux
Aula 3 - Sistemas operacionais - Linux
 
Introdução ao Linux Ubuntu
Introdução ao Linux UbuntuIntrodução ao Linux Ubuntu
Introdução ao Linux Ubuntu
 
Урок № 8 Тема. Поняття операційної системи, її призначення. Графічний інтер...
Урок № 8   Тема. Поняття операційної системи, її призначення. Графічний інтер...Урок № 8   Тема. Поняття операційної системи, її призначення. Графічний інтер...
Урок № 8 Тема. Поняття операційної системи, її призначення. Графічний інтер...
 
Ubuntu Linux
Ubuntu LinuxUbuntu Linux
Ubuntu Linux
 
Sistema windows 10
Sistema windows 10Sistema windows 10
Sistema windows 10
 
Windows x Linux
Windows x LinuxWindows x Linux
Windows x Linux
 
Sistemas Operacionais
Sistemas OperacionaisSistemas Operacionais
Sistemas Operacionais
 
8
88
8
 
Apresentação Sistemas Operativos TUDO.pdf
Apresentação Sistemas Operativos TUDO.pdfApresentação Sistemas Operativos TUDO.pdf
Apresentação Sistemas Operativos TUDO.pdf
 
Sistemas Operacionais - Aula 02 (Visão geral de sistemas operacionais)
Sistemas Operacionais - Aula 02 (Visão geral de sistemas operacionais)Sistemas Operacionais - Aula 02 (Visão geral de sistemas operacionais)
Sistemas Operacionais - Aula 02 (Visão geral de sistemas operacionais)
 

Similar a Windows NT: Gerenciamento de E/S, Memória e Processos

55245042 apostila-introducaoa informatica
55245042 apostila-introducaoa informatica55245042 apostila-introducaoa informatica
55245042 apostila-introducaoa informaticaAnDre Luiz
 
1455 sistemas operacionais
1455 sistemas operacionais1455 sistemas operacionais
1455 sistemas operacionaismauromagule
 
Sistema Operacional de Redes I
Sistema Operacional de Redes ISistema Operacional de Redes I
Sistema Operacional de Redes ISebastião Benicio
 
Informatica para concursos_motive_cursosonline
Informatica para concursos_motive_cursosonlineInformatica para concursos_motive_cursosonline
Informatica para concursos_motive_cursosonlineJuniorMarinho7
 
Apostila de Informatica
Apostila de InformaticaApostila de Informatica
Apostila de Informaticapetichs
 
Instalação e manutenção pdf
Instalação e manutenção pdfInstalação e manutenção pdf
Instalação e manutenção pdfLuanna Pio
 
Apostila 130227111109-phpapp02
Apostila 130227111109-phpapp02Apostila 130227111109-phpapp02
Apostila 130227111109-phpapp02Jadiel Mendes
 
apostila informatica
apostila informaticaapostila informatica
apostila informaticanetdow livros
 
Conceitos.basicos.da.informatica
Conceitos.basicos.da.informaticaConceitos.basicos.da.informatica
Conceitos.basicos.da.informaticaGuilherme Fernandes
 
Apostila informatica basica pronatec
Apostila informatica basica   pronatecApostila informatica basica   pronatec
Apostila informatica basica pronatecThales Menezes
 
Apostila introducao informatica
Apostila introducao informaticaApostila introducao informatica
Apostila introducao informaticaGabriel Sipriano
 
Apostila introducao informatica_mar2007
Apostila introducao informatica_mar2007Apostila introducao informatica_mar2007
Apostila introducao informatica_mar2007chivas_jazz_team
 

Similar a Windows NT: Gerenciamento de E/S, Memória e Processos (20)

55245042 apostila-introducaoa informatica
55245042 apostila-introducaoa informatica55245042 apostila-introducaoa informatica
55245042 apostila-introducaoa informatica
 
1455 sistemas operacionais
1455 sistemas operacionais1455 sistemas operacionais
1455 sistemas operacionais
 
1455 sistemas operacionais
1455 sistemas operacionais1455 sistemas operacionais
1455 sistemas operacionais
 
Sistema Operacional de Redes I
Sistema Operacional de Redes ISistema Operacional de Redes I
Sistema Operacional de Redes I
 
Bd apost
Bd apostBd apost
Bd apost
 
Informatica para concursos_motive_cursosonline
Informatica para concursos_motive_cursosonlineInformatica para concursos_motive_cursosonline
Informatica para concursos_motive_cursosonline
 
Ejer 12
Ejer 12Ejer 12
Ejer 12
 
Apostila de Informatica
Apostila de InformaticaApostila de Informatica
Apostila de Informatica
 
Aise
AiseAise
Aise
 
Instalação e manutenção pdf
Instalação e manutenção pdfInstalação e manutenção pdf
Instalação e manutenção pdf
 
Apostila informática
Apostila informáticaApostila informática
Apostila informática
 
Apostila infomatica windows xp
Apostila infomatica windows xpApostila infomatica windows xp
Apostila infomatica windows xp
 
Apostila 130227111109-phpapp02
Apostila 130227111109-phpapp02Apostila 130227111109-phpapp02
Apostila 130227111109-phpapp02
 
apostila informatica
apostila informaticaapostila informatica
apostila informatica
 
Informática Windows XP
Informática Windows XPInformática Windows XP
Informática Windows XP
 
3288 redes
3288 redes3288 redes
3288 redes
 
Conceitos.basicos.da.informatica
Conceitos.basicos.da.informaticaConceitos.basicos.da.informatica
Conceitos.basicos.da.informatica
 
Apostila informatica basica pronatec
Apostila informatica basica   pronatecApostila informatica basica   pronatec
Apostila informatica basica pronatec
 
Apostila introducao informatica
Apostila introducao informaticaApostila introducao informatica
Apostila introducao informatica
 
Apostila introducao informatica_mar2007
Apostila introducao informatica_mar2007Apostila introducao informatica_mar2007
Apostila introducao informatica_mar2007
 

Más de Jerônimo Medina Madruga

PyGame Over: Insert coins to learn with Python - Tchelinux Porto Alegre 2019
PyGame Over: Insert coins to learn with Python - Tchelinux Porto Alegre 2019PyGame Over: Insert coins to learn with Python - Tchelinux Porto Alegre 2019
PyGame Over: Insert coins to learn with Python - Tchelinux Porto Alegre 2019Jerônimo Medina Madruga
 
Rock & Code - Como criar música programando - Tchelinux pelotas 2019
Rock & Code - Como criar música programando - Tchelinux pelotas 2019Rock & Code - Como criar música programando - Tchelinux pelotas 2019
Rock & Code - Como criar música programando - Tchelinux pelotas 2019Jerônimo Medina Madruga
 
Rock 'n' Code - Como criar música programando - Tchelinux Camaquã 2019
Rock 'n' Code - Como criar música programando - Tchelinux Camaquã 2019Rock 'n' Code - Como criar música programando - Tchelinux Camaquã 2019
Rock 'n' Code - Como criar música programando - Tchelinux Camaquã 2019Jerônimo Medina Madruga
 
Desenvolvendo Jogos com PyGame - Jerônimo Medina Madruga - Tchelinux 2019 Rio...
Desenvolvendo Jogos com PyGame - Jerônimo Medina Madruga - Tchelinux 2019 Rio...Desenvolvendo Jogos com PyGame - Jerônimo Medina Madruga - Tchelinux 2019 Rio...
Desenvolvendo Jogos com PyGame - Jerônimo Medina Madruga - Tchelinux 2019 Rio...Jerônimo Medina Madruga
 
Dê a cara a tapa como se destacar no mercado de trabalho - Tchelinux Sant'An...
Dê a cara a tapa  como se destacar no mercado de trabalho - Tchelinux Sant'An...Dê a cara a tapa  como se destacar no mercado de trabalho - Tchelinux Sant'An...
Dê a cara a tapa como se destacar no mercado de trabalho - Tchelinux Sant'An...Jerônimo Medina Madruga
 
Rock 'n' Code: Como criar música programando - I Semana Acadêmica da Licencia...
Rock 'n' Code: Como criar música programando - I Semana Acadêmica da Licencia...Rock 'n' Code: Como criar música programando - I Semana Acadêmica da Licencia...
Rock 'n' Code: Como criar música programando - I Semana Acadêmica da Licencia...Jerônimo Medina Madruga
 
Do Zero ao Python - I Semana Acadêmica da Licenciatura em Computação - IFSul ...
Do Zero ao Python - I Semana Acadêmica da Licenciatura em Computação - IFSul ...Do Zero ao Python - I Semana Acadêmica da Licenciatura em Computação - IFSul ...
Do Zero ao Python - I Semana Acadêmica da Licenciatura em Computação - IFSul ...Jerônimo Medina Madruga
 
Desmistificando a gamificação: como "jogos" podem potencializar a educação - ...
Desmistificando a gamificação: como "jogos" podem potencializar a educação - ...Desmistificando a gamificação: como "jogos" podem potencializar a educação - ...
Desmistificando a gamificação: como "jogos" podem potencializar a educação - ...Jerônimo Medina Madruga
 
Rock And Code: Como criar música programando
Rock And Code: Como criar música programandoRock And Code: Como criar música programando
Rock And Code: Como criar música programandoJerônimo Medina Madruga
 
Remember the name: Como se tornar um rockstar no mercado de trabalho
Remember the name: Como se tornar um rockstar no mercado de trabalhoRemember the name: Como se tornar um rockstar no mercado de trabalho
Remember the name: Como se tornar um rockstar no mercado de trabalhoJerônimo Medina Madruga
 
Como se tornar um programador melhor - Saci 2017 IFSul Bagé
Como se tornar um programador melhor - Saci 2017 IFSul BagéComo se tornar um programador melhor - Saci 2017 IFSul Bagé
Como se tornar um programador melhor - Saci 2017 IFSul BagéJerônimo Medina Madruga
 
Dê a cara a tapa 5 estratégias para se sobressair no mercado e ser um profis...
Dê a cara a tapa  5 estratégias para se sobressair no mercado e ser um profis...Dê a cara a tapa  5 estratégias para se sobressair no mercado e ser um profis...
Dê a cara a tapa 5 estratégias para se sobressair no mercado e ser um profis...Jerônimo Medina Madruga
 
Aprendendo a aprender software livre - Tchelinux Bagé 2017
Aprendendo a aprender software livre - Tchelinux Bagé 2017Aprendendo a aprender software livre - Tchelinux Bagé 2017
Aprendendo a aprender software livre - Tchelinux Bagé 2017Jerônimo Medina Madruga
 
Moodle direto das trincheiras - Tchelinux UCPel 2017
Moodle direto das trincheiras - Tchelinux UCPel 2017Moodle direto das trincheiras - Tchelinux UCPel 2017
Moodle direto das trincheiras - Tchelinux UCPel 2017Jerônimo Medina Madruga
 
Aprendendo Software Livre como Neo Aprendeu Kung Fu - Tchelinux UCPel 2017
Aprendendo Software Livre como Neo Aprendeu Kung Fu - Tchelinux UCPel 2017Aprendendo Software Livre como Neo Aprendeu Kung Fu - Tchelinux UCPel 2017
Aprendendo Software Livre como Neo Aprendeu Kung Fu - Tchelinux UCPel 2017Jerônimo Medina Madruga
 
Tudo que você queria saber sobre software livre mas não tinha coragem de perg...
Tudo que você queria saber sobre software livre mas não tinha coragem de perg...Tudo que você queria saber sobre software livre mas não tinha coragem de perg...
Tudo que você queria saber sobre software livre mas não tinha coragem de perg...Jerônimo Medina Madruga
 
Aprendendo a aprender software livre - Tchelinux Bagé 2016
Aprendendo a aprender software livre - Tchelinux Bagé 2016Aprendendo a aprender software livre - Tchelinux Bagé 2016
Aprendendo a aprender software livre - Tchelinux Bagé 2016Jerônimo Medina Madruga
 
Need for (web) speed: Uma introdução a otimização de velocidade de sites e We...
Need for (web) speed: Uma introdução a otimização de velocidade de sites e We...Need for (web) speed: Uma introdução a otimização de velocidade de sites e We...
Need for (web) speed: Uma introdução a otimização de velocidade de sites e We...Jerônimo Medina Madruga
 
Dê a Cara a Tapa: Uma Palestra Intrigante sobre Oceano Azul, Cauda Longa, Mer...
Dê a Cara a Tapa: Uma Palestra Intrigante sobre Oceano Azul, Cauda Longa, Mer...Dê a Cara a Tapa: Uma Palestra Intrigante sobre Oceano Azul, Cauda Longa, Mer...
Dê a Cara a Tapa: Uma Palestra Intrigante sobre Oceano Azul, Cauda Longa, Mer...Jerônimo Medina Madruga
 

Más de Jerônimo Medina Madruga (20)

PyGame Over: Insert coins to learn with Python - Tchelinux Porto Alegre 2019
PyGame Over: Insert coins to learn with Python - Tchelinux Porto Alegre 2019PyGame Over: Insert coins to learn with Python - Tchelinux Porto Alegre 2019
PyGame Over: Insert coins to learn with Python - Tchelinux Porto Alegre 2019
 
Rock & Code - Como criar música programando - Tchelinux pelotas 2019
Rock & Code - Como criar música programando - Tchelinux pelotas 2019Rock & Code - Como criar música programando - Tchelinux pelotas 2019
Rock & Code - Como criar música programando - Tchelinux pelotas 2019
 
Rock 'n' Code - Como criar música programando - Tchelinux Camaquã 2019
Rock 'n' Code - Como criar música programando - Tchelinux Camaquã 2019Rock 'n' Code - Como criar música programando - Tchelinux Camaquã 2019
Rock 'n' Code - Como criar música programando - Tchelinux Camaquã 2019
 
Desenvolvendo Jogos com PyGame - Jerônimo Medina Madruga - Tchelinux 2019 Rio...
Desenvolvendo Jogos com PyGame - Jerônimo Medina Madruga - Tchelinux 2019 Rio...Desenvolvendo Jogos com PyGame - Jerônimo Medina Madruga - Tchelinux 2019 Rio...
Desenvolvendo Jogos com PyGame - Jerônimo Medina Madruga - Tchelinux 2019 Rio...
 
Dê a cara a tapa como se destacar no mercado de trabalho - Tchelinux Sant'An...
Dê a cara a tapa  como se destacar no mercado de trabalho - Tchelinux Sant'An...Dê a cara a tapa  como se destacar no mercado de trabalho - Tchelinux Sant'An...
Dê a cara a tapa como se destacar no mercado de trabalho - Tchelinux Sant'An...
 
Rock 'n' Code: Como criar música programando - I Semana Acadêmica da Licencia...
Rock 'n' Code: Como criar música programando - I Semana Acadêmica da Licencia...Rock 'n' Code: Como criar música programando - I Semana Acadêmica da Licencia...
Rock 'n' Code: Como criar música programando - I Semana Acadêmica da Licencia...
 
Do Zero ao Python - I Semana Acadêmica da Licenciatura em Computação - IFSul ...
Do Zero ao Python - I Semana Acadêmica da Licenciatura em Computação - IFSul ...Do Zero ao Python - I Semana Acadêmica da Licenciatura em Computação - IFSul ...
Do Zero ao Python - I Semana Acadêmica da Licenciatura em Computação - IFSul ...
 
Desmistificando a gamificação: como "jogos" podem potencializar a educação - ...
Desmistificando a gamificação: como "jogos" podem potencializar a educação - ...Desmistificando a gamificação: como "jogos" podem potencializar a educação - ...
Desmistificando a gamificação: como "jogos" podem potencializar a educação - ...
 
Rock And Code: Como criar música programando
Rock And Code: Como criar música programandoRock And Code: Como criar música programando
Rock And Code: Como criar música programando
 
Do zero ao python em 40 minutos!
Do zero ao python em 40 minutos!Do zero ao python em 40 minutos!
Do zero ao python em 40 minutos!
 
Remember the name: Como se tornar um rockstar no mercado de trabalho
Remember the name: Como se tornar um rockstar no mercado de trabalhoRemember the name: Como se tornar um rockstar no mercado de trabalho
Remember the name: Como se tornar um rockstar no mercado de trabalho
 
Como se tornar um programador melhor - Saci 2017 IFSul Bagé
Como se tornar um programador melhor - Saci 2017 IFSul BagéComo se tornar um programador melhor - Saci 2017 IFSul Bagé
Como se tornar um programador melhor - Saci 2017 IFSul Bagé
 
Dê a cara a tapa 5 estratégias para se sobressair no mercado e ser um profis...
Dê a cara a tapa  5 estratégias para se sobressair no mercado e ser um profis...Dê a cara a tapa  5 estratégias para se sobressair no mercado e ser um profis...
Dê a cara a tapa 5 estratégias para se sobressair no mercado e ser um profis...
 
Aprendendo a aprender software livre - Tchelinux Bagé 2017
Aprendendo a aprender software livre - Tchelinux Bagé 2017Aprendendo a aprender software livre - Tchelinux Bagé 2017
Aprendendo a aprender software livre - Tchelinux Bagé 2017
 
Moodle direto das trincheiras - Tchelinux UCPel 2017
Moodle direto das trincheiras - Tchelinux UCPel 2017Moodle direto das trincheiras - Tchelinux UCPel 2017
Moodle direto das trincheiras - Tchelinux UCPel 2017
 
Aprendendo Software Livre como Neo Aprendeu Kung Fu - Tchelinux UCPel 2017
Aprendendo Software Livre como Neo Aprendeu Kung Fu - Tchelinux UCPel 2017Aprendendo Software Livre como Neo Aprendeu Kung Fu - Tchelinux UCPel 2017
Aprendendo Software Livre como Neo Aprendeu Kung Fu - Tchelinux UCPel 2017
 
Tudo que você queria saber sobre software livre mas não tinha coragem de perg...
Tudo que você queria saber sobre software livre mas não tinha coragem de perg...Tudo que você queria saber sobre software livre mas não tinha coragem de perg...
Tudo que você queria saber sobre software livre mas não tinha coragem de perg...
 
Aprendendo a aprender software livre - Tchelinux Bagé 2016
Aprendendo a aprender software livre - Tchelinux Bagé 2016Aprendendo a aprender software livre - Tchelinux Bagé 2016
Aprendendo a aprender software livre - Tchelinux Bagé 2016
 
Need for (web) speed: Uma introdução a otimização de velocidade de sites e We...
Need for (web) speed: Uma introdução a otimização de velocidade de sites e We...Need for (web) speed: Uma introdução a otimização de velocidade de sites e We...
Need for (web) speed: Uma introdução a otimização de velocidade de sites e We...
 
Dê a Cara a Tapa: Uma Palestra Intrigante sobre Oceano Azul, Cauda Longa, Mer...
Dê a Cara a Tapa: Uma Palestra Intrigante sobre Oceano Azul, Cauda Longa, Mer...Dê a Cara a Tapa: Uma Palestra Intrigante sobre Oceano Azul, Cauda Longa, Mer...
Dê a Cara a Tapa: Uma Palestra Intrigante sobre Oceano Azul, Cauda Longa, Mer...
 

Windows NT: Gerenciamento de E/S, Memória e Processos

  • 1. UNIVERSIDADE FEDERAL DE PELOTAS INSTITUTO DE FÍSICA E MATEMÁTICA DEPARTAMENTO DE INFORMÁTICA BACHARELADO EM CIÊNCIA DA COMPUTAÇÃO ESTUDO DE CASO: WINDOWS NT Jerônimo Medina Madruga Leonardo Lobo da Luz Mauro Sérgio Cardoso Kade Trabalho de pesquisa apresentado na disciplina de Sistemas operacionais 2 do Curso de Bacharelado em Ciência da Computação, Instituto de Física e Matemática, Universidade Federal de Pelotas. Professor: Prof. Gil Medeiros 2007
  • 2. Lista de Figuras Figura 1: Componentes do Sistema de E/S...........................................................................14 Figura 2: Rotinas primárias de drivers de dispositivos.........................................................16 Figura 3: Abrindo um objeto de arquivo...............................................................................21 Figura 4: Enfileirando e completando uma requisição de E/S..............................................25 Figura 5: Mapeando Páginas Virtuais para estruturas de página físicas...............................33 Figura 6: Mapeando Visões em uma Seção..........................................................................38 Figura 7: Section Object........................................................................................................39 Figura 8: Antes do copy-on-write.........................................................................................42 Figura 9: Depois do copy-on-write.......................................................................................43 Figura 10: Espaço de Endereçamento Virtual.......................................................................45 Figura 11: Tabela de Páginas Conceitual..............................................................................47 Figura 12: Esquema de tradução de endereço virtual para endereço físico em arquiteturas Intel.......................................................................................................................................54 Figura 13: Principais funções API Win32 para gerenciamento da memória virtual.............59 Figura 14: Representação de um processo como objeto.......................................................61 Figura 15: Representação de uma Thread como um objeto..................................................62 Figura 16: Tabela de prioridades do Windows 2000............................................................67 Figura 17: Principais funções API Win32 para funções de arquivos....................................70 Figura 18: Tabela Mestre de Arquivos NTFS.......................................................................73 Figura 19: Registro da MFT para um arquivo......................................................................75 Figura 20: Registro da MFT para um pequeno diretório......................................................79 Figura 21: Visão geral de um FSD local...............................................................................80 Figura 22: Operação de FSD remoto....................................................................................81 Figura 23: Criptografia de Arquivos.....................................................................................84
  • 3. Sumário APRESENTAÇÃO.................................................................................................................5 1. HISTÓRICO.......................................................................................................................6 1.1 MS-DOS........................................................................................................................6 1.2 Windows.......................................................................................................................6 1.3 Windows NT.................................................................................................................7 1.4 Windows 2000..............................................................................................................8 2. GERENCIAMENTO DE E/S...........................................................................................11 2.1 Principais objetivos do sistema de E/S .......................................................................11 2.2 Componentes do Sistema de E/S.................................................................................12 2.2.1 Gerenciador de E/S..................................................................................................15 2.2.2 Drivers de Dispositivo..............................................................................................15 2.2.2.1 Estrutura de um Driver..........................................................................................16 2.2.3 Gerenciador de PnP (Plug-and-Play).......................................................................17 2.2.4 Gerenciador de Cache..............................................................................................18 2.3 Estruturas de Dados de E/S.........................................................................................19 2.3.1 Objetos de Arquivo..................................................................................................19 2.3.2 Objetos de Driver e Objetos de Dispositivo.............................................................22 2.3.3 Pacotes de Requisição de E/S..................................................................................22 2.4 Processamento de E/S.................................................................................................23 2.4.1 Tipos de E/S.............................................................................................................23 2.5 Suporte a RAID...........................................................................................................26 2.6 Plug-and-play..............................................................................................................26 2.7 Suporte a multiprocessamento....................................................................................27 2.8 Recuperação de falha de energia.................................................................................27 3. GERENCIAMENTO DE MEMÓRIA..............................................................................29 3.1 Memória Virtual..........................................................................................................30 3.2 Gerenciando a Memória..............................................................................................34 3.2.1 Estados de uma página virtual..................................................................................35 3.2.2 Memória Compartilhada..........................................................................................36 3.2.2.1 Section Object.......................................................................................................39 3.2.3 Proteção de Memória...............................................................................................41 3.3 Implementação............................................................................................................44 3.3.1 Mecanismos de Paginação.......................................................................................46 3.3.2 Políticas de Paginação..............................................................................................49 3.3.3 Gerenciamento da memória física............................................................................51 3.3.4 Tradução de Endereços............................................................................................53 3.3.5 Tratamento de Falta de Página.................................................................................55 3.3.6 Descritores de Endereço Virtual..............................................................................56 3.4 Chamadas ao Sistema..................................................................................................58 4. GERÊNCIA DE PROCESSOS.........................................................................................60 4.1 Caracterização de Jobs, Processos, Threads e Fibers..................................................60 4.2 Técnicas de comunicação............................................................................................63 4.3 Técnicas de sincronização...........................................................................................64 4.4 Criação de Processos e Threads..................................................................................65
  • 4. 4.5 Escalonamento............................................................................................................66 5. SISTEMA DE ARQUIVOS..............................................................................................68 5.1 Conceitos Fundamentais do NTFS..............................................................................68 5.2 Chamadas de API........................................................................................................70 5.3 Estrutura do Sistema de Arquivos...............................................................................71 5.4 Arquitetura do Driver de Sistema de Arquivos...........................................................79 5.5 Compressão de Arquivos............................................................................................82 5.6 Criptografia de Arquivos.............................................................................................83 REFERÊNCIAS BIBLIOGRÁFICAS..................................................................................87
  • 5. APRESENTAÇÃO Este trabalho tem como objetivo realizar uma análise em um dos sistemas operacionais mais difundidos no mundo, o Windows NT. Em um primeiro momento, faremos uma abordagem da história do desenvolvimento desse sistema, revelando suas raízes e mostrando sua evolução ao longo dos anos. Após, abordaremos os componentes mais relevantes na estrutura do sistema operacional em estudo: o gerenciamento de entrada e saída, gerenciamento de memória, gerenciamento de processos, e gerenciamento de arquivos, comparado com os elementos previamente estudados na disciplina.
  • 6. 1. HISTÓRICO Este capítulo tem como objetivo representar os avanços em sistemas operacionais e o contexto histórico que levaram ao desenvolvimento da arquitetura do desenvolvimento do Windows NT. Daremos enfoque aos predecessores do Windows NT, o MS-DOS e Windows, citando suas características, vantagens e desvantagens. Após, entraremos mais afundo no projeto do Windows 2000, um dos representantes mais recentes do Windows NT, mostrando suas inovações tecnológicas e os princípios de desenvolvimento do mesmo. 1.1 MS-DOS Em 1981, a IBM produzia o IBM PC utilizando o processador 8088. Esse computador vinha com sistema operacional de 16 bits monousuário chamado MS- DOS (Microsoft Disk Operational System). Esse sistema operacional consistia em 8 KB de código residente na memória e foi modelado de forma similar ao CP/M, um sistema operacional pequeno para os processadores de 8 bits 8080 e Z80. Dois anos depois, uma nova versão, o MS-DOS 2.0, foi lançada, contendo um processador de linha de comando e com diversas características semelhantes ao UNIX. Com o passar do tempo foram sendo lançada novas versões de acordo com a evolução dos computadores, que agregavam novas características, mas continuava basicamente sendo um sistema orientado a linha de comando [TANENBAUM, 2001]. 1.2 Windows Tendo como inspiração a interface de usuário do Apple Lisa, a Microsoft decidiu dar ao MS-DOS uma interface gráfica, a qual foi chamada de Windows. O Windows 1.0 foi lançado em 1985, mas não chegou a ter sucesso, assim como seu sucessor Windows 2.0. A popularização começou com o Windows 3.0 e seus
  • 7. derivados, mas é importante salientar que nenhuma dessas versões iniciais do Windows eram realmente sistemas operacionais, eles eram interfaces gráficas para o usuário trabalhar em cima do MS-DOS, que ainda gerenciava a máquina e o sistema de arquivos. Todos os programas rodavam no mesmo espaço de endereçamento e um defeito em qualquer um deles poderia causar uma pane geral no sistema. Esse cenário começa a mudar com o Windows 95, onde apesar do MS- DOS ainda estar intrínseco no sistema, grande parte do sistema operacional já era gerenciado pelo sistema, além de já contar com características de um sistema mais maduro, como memória virtual, gerenciamento de processos e multiprogramação. Como herança do MS-DOS, o Windows 95 ainda continha partes do código sendo composta por código assembly de 16 bits e ainda usava o sistema de arquivos do MS-DOS. O sucessor do Windows 95, o Windows 98, ainda continha o MS-DOS, agora na versão 7.1, mas já tinha um sistema de arquivos novo. Ele também tinha uma maior integração entre a Internet e o desktop do sistema. O Windows 98 tinha ainda dois problemas crônicos, fora a presença do legado do MS-DOS: o código do kernel não era reentrante, o que ocasionava problemas na execução de diversos processos que utilizassem estruturas de dados do kernel e o fato que havia uma parte do espaço de endereçamento virtual que era compartilhada por todos os processos, além do kernel, assim um defeito em um programa poderia afetar todo o sistema. Após veio o Windows Me (Windows Millenium Edition), que era essencialmente o Windows 98, com a correção de alguns dos defeitos e com alguns novos recursos relativos aos dispositivos que despontavam na época e a aplicativos multimídia. 1.3 Windows NT Em 1988, a Microsoft decidiu desenvolver um sistema operacional para a década de 1990. O MS-DOS tinha sido desenvolvido para hardware antigo, e
  • 8. assim os modos de utilização do mesmo começaram a ficar rapidamente restritivos e obsoletos, como o suporte a modo monousuário unicamente, arquitetura de 8 e 16 bits com um suporte rústico para múltiplos processos, sem proteção de memória entre eles. A alternativa da época, o OS/2, foi uma tentativa de aumentar o escopo de uso, mas continha grandes fragmentos de código em assembly para arquitetura CISC monoprocessada, e assim não poderia evoluir para usufruir das vantagens dos novos processadores RISC e das ferramentas de proteção à memória presentes nos processadores subseqüentes da Intel. Também durante esse tempo, várias pesquisas acadêmicas sobre sistemas operacionais começaram a ser divulgadas [BACON, 2003]. Para desenvolver esse novo sistema, Dave Cutler, que foi um importante desenvolvedor do sistema operacional VMS, foi contratado pela Microsoft, com o intuito de liderar a equipe que iria desenvolver o sistema que seria chamado posteriormente de Windows NT (Windows New Technology), que seria o primeiro Windows a funcionar totalmente 32 bits, tendo foco tanto para o mercado empresarial quanto para os computadores domésticos. . A primeira versão foi batizada Windows NT 3.1, que apesar de ser superior tecnicamente à versão do Windows baseada no MS-DOS que existia no momento, não chegou a ter muito sucesso devido ao fato que o sistema era mais pesado e ainda não havia grande gama de aplicativos 32 bits. Após, foram lançadas sucessivas atualizações para o sistema NT, até ser lançada uma nova versão em 1996, o Windows NT 4.0, que tinha a mesma interface que consagrou o Windows 95, em conjunto com poder, segurança e confiabilidade, e assim esse sistema teve uma aceitação muito maior que seu predecessor. Sendo quase totalmente escrito em C, o Windows NT era extremamente portável, e com isso ele rodava em diversas outras plataformas, em contraste ao Windows 95 e seus descendentes, que rodavam somente na Arquitetura X86 da Intel [TANENBAUM, 2001]. 1.4 Windows 2000
  • 9. O Windows 2000 foi o nome do sucessor do Windows NT 4.0, e tinha como objetivo ter a confiabilidade da família NT com a interface do Windows 98. O Windows 2000 manteve diversas características do Windows NT, sendo um sistema totalmente 32 bits (mas mantendo compatibilidade com aplicativos 16 bits) focado para quase todo o mercado de computadores: de laptops a estações multiprocessadas. O Windows 2000 teve diversos princípios utilizados para seu desenvolvimento, entre eles podemos citar: • Extensibilidade: para encarar as constantes mudanças na demanda do mercado, o Windows 2000 foi desenvolvido numa estrutura modular baseada em objetos, o que permitiu que funções comuns, como controle de acesso a recursos, fossem separadas das funções especificas. Assim drivers de dispositivos pode ser carregados e descarregados dinamicamente. • Portabilidade: tendo como objetivo poder ser portado para outras arquiteturas com o menor numero de mudanças possível, o Windows 2000 foi quase totalmente escrito em C e C++, sendo assim a linguagem assembly se restringe às camadas dependentes de hardware. • Escalabilidade: o Windows 2000 permite que as aplicações explorem todo o potencial do hardware, tendo suporte para multiprocessamento e grande espaço de endereçamento físico. • Robustez: o sistema deve ser capaz de proteger-se contra erros internos, defeitos e ataques externos. O sistema de proteção previne que nenhum programa corrompa o sistema operacional ou outra aplicação. • Compatibilidade: o Windows 2000 mantém compatibilidade com os aplicativos desenvolvidos para as versões mais antigas de sistemas operacionais da Microsoft. • Segurança: O Windows 2000 tem segurança classe C2 para multi- usuário e sistemas comerciais, que consiste em um sistema de login
  • 10. protegido por senha, o sistema operacional rodando em modo protegido, espaços de endereçamentos protegidos e cotas de recursos. • Performance: O sistema tem de ser rápido ao responder para o usuário [BACON, 2003].
  • 11. 2. GERENCIAMENTO DE E/S Este capítulo tem por objetivo descrever as funcionalidades, os componentes e o funcionamento básico do sistema de gerência de E/S do Windows NT, assim como a interação entre esses diversos componentes que compõe o sistema de E/S. 2.1 Principais objetivos do sistema de E/S Alguns dos objetivos principais do sistema de gerência de E/S do Windows NT são: • Tornar o processamento de E/S rápido tanto para arquiteturas mono quanto multiprocessadas. • Utilizar mecanismos de segurança para proteger recursos compartilhados. • Prover serviços de E/S para as interfaces Win32, POSIX e OS/2. • Permitir que drivers de dispositivo sejam instalados e desinstalados de forma dinâmica, garantindo sua configuração automática, assim como do hardware a ser adicionado ou removido do sistema. • Provê suporte a vários sistemas de arquivo, entre eles a tabela de alocação de arquivos (FAT), o sistema de arquivo de CD-ROM (CDFS), o formato de disco universal (UFS), e o sistema de arquivos do Windows NT (NTFS). A seguir, uma descrição detalhada dos componentes do sistema de gerência de E/S e a maneira pela qual eles atuam para atingir tais objetivos.
  • 12. 2.2 Componentes do Sistema de E/S O Windows NT consiste em uma série de componentes que, em conjunto, oferecem diversos serviços de E/S periféricos atuantes em um sistema de computador. Tais componentes fazem parte da camada executiva do Windows NT. A figura 1 a seguir ilustra todos esses componentes. • O gerenciador de E/S é responsável pelos acessos ao sistema de arquivos, gerenciamento de cache, drivers de dispositivo e drivers de rede. Ele determina quais sistemas de arquivo instaláveis são carregados, e gerencia os buffers para as requisições de E/S. Ele trabalha com o gerenciador de MV (Máquina Virtual) para prover um sistema de E/S mapeado em memória, e controla o gerenciador de cache do NT. O gerenciador de E/S suporta operações síncronas e assíncronas, provê timeouts para os drivers, e possui mecanismos para um driver chamar outro. • O gerenciador de cache oferece serviços de cache para todos os componentes em controle do gerenciador de E/S, e trabalha próximo ao gerenciador de MV (Máquina Virtual). O tamanho da cache muda dinamicamente, de acordo com a quantidade de memória livre disponível no sistema. • Um driver de dispositivo tipicamente oferece uma interface de E/S para um tipo de dispositivo em particular. Drivers de dispositivo recebem comandos roteados para eles pelo gerenciador de E/S, sendo enviados para os dispositivos que eles gerenciam, informando ao gerenciador de E/S quando esses comandos terminarem. • O gerenciador PnP (Plug-and-Play) atua em conjunto com o gerenciador de E/S e com um driver de dispositivo chamado driver de barramento para guiar a alocação dos recursos do hardware de forma segura e responder satisfatoriamente às adições e/ou remoções de componentes de hardware. O gerenciador PnP e os drivers de barramento são
  • 13. responsáveis por carregar um driver de dispositivo quando um determinado componente é detectado. • O gerenciador de força atua em conjunto com o gerenciador de E/S para guiar o sistema, assim como os drivers de dispositivo, através de transições de estados de força ou de energia. • O registro serve como uma base de dados que armazena uma descrição básica dos dispositivos de hardware presentes no sistema, assim como inicialização e configuração de um driver. • Arquivos INF, designados pela extensão .inf, que são arquivos de instalação de drivers. Esses arquivos são a ligação entre um dispositivo de hardware particular e o driver que assume o controle do dispositivo. • A camada de abstração de hardware (HAL – Hardware Abstraction Layer) oferece API’s que escondem as diferenças entre as plataformas dos drivers. Na prática, o HAL é um driver de barramento para todos os dispositivos da placa-mãe do computador que não são controlados por outros dispositivos.
  • 14. Figura 1: Componentes do Sistema de E/S Muitas operações de E/S não envolvem todos os componentes descritos acima. Uma típica requisição de E/S começa com uma aplicação executando uma determinada função de E/S (por exemplo, ler dados de um disco rígido) que é processada por um gerenciador de E/S, um ou mais drivers de dispositivo, e o HAL. No Windows NT, diferentes threads realizam E/S em arquivos virtuais. O sistema operacional abstrai todas as requisições de E/S como se fossem operações em um arquivo virtual, escondendo o fato de que o objetivo de uma operação de E/S pode não ser um dispositivo estruturado de arquivo. Essa abstração generaliza uma interface de aplicação para os dispositivos. Um arquivo virtual, por sua vez, refere-se a qualquer fonte ou destino para a E/S que é tratada como se fosse um arquivo comum. Todos os dados que são lidos ou gravados são considerados como um simples fluxo de bytes dirigidos para esses arquivos virtuais. Aplicações em modo usuário chamam funções específicas, que por sua vez chamam funções internas do sistema de E/S para ler de um arquivo, escrever
  • 15. em um arquivo, e/ou realizar outras operações. O gerenciador de E/S envia dinamicamente essas requisições dos arquivos virtuais para o driver de dispositivo apropriado. Nas seções seguintes, os componentes serão descritos com mais profundidade. Primeiramente será visto o gerenciador de E/S e, logo após, os drivers de dispositivo, assim como as estruturas de dados do sistema de E/S. 2.2.1 Gerenciador de E/S O gerenciador de E/S é responsável pelos acessos ao sistema de arquivos, gerenciamento de cache, drivers de dispositivo e drivers de rede. Ele determina quais sistemas de arquivo instaláveis são carregados, e gerencia os buffers para as requisições de E/S. Ele trabalha com o gerenciador de MV (Máquina Virtual) para prover um sistema de E/S mapeado em memória, e controla o gerenciador de cache do NT. O gerenciador de E/S suporta operações síncronas e assíncronas, provê timeouts para os drivers, e possui mecanismos para um driver chamar outro [SILBERSCHATZ, 1998]. O gerenciador de E/S converte as requisições que recebe em um formato padrão chamado IRP (I/O Request Packet). Ele então encaminha o IRP para o driver correto para processamento. Quando a operação termina, o gerenciador de E/S recebe o IRP do driver que recentemente executou uma operação, e completa a requisição. 2.2.2 Drivers de Dispositivo Um driver de dispositivo funciona como a ponte necessária entre o gerenciador de E/S e os componentes do sistema de E/S. Entre alguns dos tipos de drivers de dispositivo encontram-se:
  • 16. • Drivers de sistema de arquivo: aceitam requisições para arquivos. • Drivers do Windows NT: atuam em conjunto com os gerenciadores de força e PnP do Windows NT, quando requisitados. • Drivers de dispositivo virtuais: utilizados para emular aplicações de 16 bits do MS-DOS. 2.2.2.1 Estrutura de um Driver O sistema de E/S controla a execução dos drivers de dispositivo. Os drivers de dispositivo consistem em uma série de rotinas que são chamadas para processar os vários estágios de uma requisição de E/S. A figura abaixo (Figura 2) ilustra algumas dessas rotinas. Figura 2: Rotinas primárias de drivers de dispositivos
  • 17. O gerenciador de E/S executa uma rotina de inicialização do driver (initialization routine), que é denominada DriverEntry, quando carrega o driver no sistema operacional. Um driver que suporta Plug-and-Play implementa uma rotina de adição de dispositivo (add-device routine). O gerenciador de PnP manda uma notificação a um driver através dessa rotina. Ela também permite que um driver aloque um objeto de dispositivo para representar o dispositivo. Rotinas de envio (Set of dispatch routines) são funções vitais que um driver de dispositivo oferece. Alguns exemplos são abertura (open), fechamento (close), leitura (read), escrita (write) e outras capacidades relacionadas a dispositivos, sistema de arquivos ou suporte a rede. Quando chamado para realizar uma operação de E/S, o gerenciador de E/S gera um IRP e chama um driver através de uma rotina de envio de driver. Um driver pode usar uma rotina de início de E/S (start I/O routine) para iniciar uma transferência de dados para ou de um dispositivo. Essa rotina é definida somente em drivers que contam com o gerenciador de E/S para uma serialização IRP. O gerenciador de E/S serializa IRP’s para um driver garantindo que o driver processe somente um IRP por vez. Quando um dispositivo causa uma interrupção, o despachador de interrupção do kernel transfere o controle para uma rotina chamada serviço de interrupção (interrupt service routine – ISR). Uma rotina de serviço de interrupção DPC (interrupt-servicing DPC routine) realiza muito do trabalho envolvido no tratamento de uma interrupção de dispositivo após a ISR executar. A rotina DPC executa a nível de dispositivo, para evitar bloqueio de outras interrupções desnecessariamente. 2.2.3 Gerenciador de PnP (Plug-and-Play) O gerenciador de PnP é o componente principal envolvido no suporte às habilidades do Windows NT de reconhecimento e adaptação às mudanças de
  • 18. configuração de hardware. Desta forma, o usuário não precisa entender as particularidades do hardware para instalar ou remover dispositivos. O suporte a Plug-and-Play requer uma cooperação entre o hardware, os drivers de dispositivo e os diferentes níveis do sistema operacional. Algumas capacidades do suporte a esse sistema são: • O gerenciador PnP reconhece automaticamente dispositivos instalados, um processo que inclui enumerar dispositivos acoplados ao sistema durante uma operação de boot e detectar a adição ou remoção de dispositivos enquanto o sistema encontra-se em execução. • A alocação de recursos de hardware é um papel que o gerenciador de PnP desempenha juntando as exigências dos recursos dos dispositivos conectados ao sistema e, em um processo chamado arbitragem de recursos, designar recursos para que os dispositivos conheçam as exigências necessárias para suas operações. Esse processo também deve ser feito de forma dinâmica pelo gerenciador de PnP. • O gerenciador de PnP também é responsável por carregar os drivers apropriados. • O gerenciador de PnP implementa aplicações e mecanismos de driver para detecção das mudanças nas configurações de hardware. Aplicações ou drivers às vezes requerem um dispositivo de hardware específico para a função, então o Windows NT oferece os meios para que sejam conhecidos notificações da presença, adição ou remoção de dispositivos. 2.2.4 Gerenciador de Cache Geralmente, a cache é dividida em blocos de 256 KB. Cada bloco de cache é descrito por um VACB (Virtual-Address Control Block) que armazena os endereços virtuais e também um offset de arquivo para a região mapeada em
  • 19. memória, juntamente com o número de processos que estão usando a região especificada. O VACB reside em um vetor que é mantido pelo gerenciador de cache. Para cada arquivo aberto, o gerenciador de cache mantém um índice separado no vetor VACB. Esse vetor possui um elemento para cada pedaço de 256 KB do arquivo. Dessa forma, um arquivo de 2 MB teria 8 entradas no vetor de índices VACB. Uma entrada nesse vetor de índices aponta para o VACB se aquela parte do arquivo encontra-se na cache. Em caso contrário, ela tem um valor nulo. 2.3 Estruturas de Dados de E/S Quatro estruturas de dados estão associadas com as requisições de E/S: objetos de arquivo, objetos de driver, objetos de dispositivo e pacotes de requisição de E/S ( I/O Request Packets - IRP ). Cada uma dessas estruturas é definida em um cabeçalho de arquivo DDK denominado Ntddk.h. 2.3.1 Objetos de Arquivo Objetos de arquivo são construções em modo kernel para lidar com arquivos ou dispositivos. Eles estabelecem critérios para os objetos no Windows NT: eles são recursos de sistema em que dois ou mais processos em modo-usuário podem compartilhar, eles podem ter nomes, são protegidos por um tipo de segurança baseada em objeto e suportam sincronização. Recursos compartilhados no sistema de E/S são manipulados como se fossem objetos. Objetos de arquivo provêem uma representação baseada em memória dos recursos que obedecem a uma interface centrada em E/S, a qual eles podem ser lidos de ou escritos para. A seguir, serão descritos alguns atributos dos objetos de arquivo:
  • 20. • Nome de arquivo (Filename): identifica o arquivo físico a que o objeto de arquivo se refere. • Byte corrente de offset (Current byte offset): identifica a localização atual no arquivo (válido apenas para operações de E/S sincronizadas). • Modos de compartilhamento(Share modoes): indica onde outros chamadores podem abrir os arquivos para ler, escrever ou deletar operações enquanto o chamador atual está em funcionamento. • Ponteiro para objeto de dispositivo (Pointer to device object): indica o tipo de dispositivo onde o arquivo reside. • Ponteiro para o bloco de parâmetro de volume (Pointer to the volume parameter block - VPB): indica o volume ou a partição em que o arquivo reside. Quando um chamador abre um arquivo para um dispositivo simples, o gerenciador de E/S retorna um handle para um objeto de arquivo. A figura abaixo ilustra o que acontece quando um arquivo é aberto.
  • 21. Figura 3: Abrindo um objeto de arquivo Nesse exemplo, (1) um programa em C chama uma rotina chamada fopen, a qual (2) chama uma função da API Win32 chamada CreateFile. A DLL do subsistema Win32 chamada kernel32.dll então (3) chama uma função nativa denominada NtCreateFile que se encontra no arquivo Ntdll.dll. A rotina presente nesse arquivo contém a instrução apropriada para causar uma transição do modo kernel para o sistema de despachador de serviço (system service dispatcher), o qual (4) chama a rotina real NtCreateFile no arquivo Ntoskrnl.exe. Assim como outros objetos do executivo, arquivos de objeto são protegidos por um descritor de segurança que contém uma lista de controle de acesso (acess- control list – ACL).
  • 22. 2.3.2 Objetos de Driver e Objetos de Dispositivo Quando uma thread abre um handle para um objeto de arquivo, o gerenciador de E/S deve determinar qual driver ou drivers do objeto de arquivo deve ser chamado para processar a requisição. O gerenciador de E/S deve ser capaz de localizar essa informação da próxima vez que uma thread usar o mesmo handle de arquivo. Um objeto de driver representa um driver individual no sistema. O gerenciador de E/S obtém o endereço de cada rotina de envio dos drivers do objeto de driver. Já os objetos de dispositivo representam um dispositivo lógico ou físico no sistema e descrevem suas características. O gerenciador de E/S cria um objeto de driver enquanto um driver é carregado no sistema, e então chama uma rotina de inicialização do driver denominada DriverEntry, a qual encaixa os atributos do objeto com os pontos de entrada do driver. Após ser carregado, um driver pode criar objetos de dispositivo para representar dispositivos, ou até mesmo uma interface para o driver, através de uma chamada a rotina IoCreateDevice. 2.3.3 Pacotes de Requisição de E/S O pacote de requisição de E/S (I/O Request Packet - IRP) é onde o sistema de E/S armazena informações necessárias para processar uma requisição de E/S. Quando uma thread chama um serviço de E/S, o gerenciador de E/S constrói um IRP para representar a operação enquanto ele atravessa o sistema de E/S. Um IRP consiste de duas partes: um cabeçalho fixo, e um ou mais pilhas de localização. A parte fixa contém informações acerca do tipo e tamanho da requisição, se a requisição é síncrona ou assíncrona, um ponteiro para um buffer e informações a respeito do estado de operação da requisição.
  • 23. 2.4 Processamento de E/S As requisições de E/S passam por diversos estágios de processamento. Os estágios variam dependendo se a requisição se destina a um dispositivo operado por um driver de camada única ou por um driver de múltiplas camadas, e também em relação a operações síncronas ou assíncronas. 2.4.1 Tipos de E/S As aplicações possuem diversas opções para as requisições de E/S que elas geram. Elas podem especificar E/S síncrona ou assíncrona, E/S que mapeia um dado de dispositivo em um espaço de endereço da aplicação. Muitas operações de E/S das aplicações são síncronas, ou seja, a aplicação espera enquanto o dispositivo realiza a transferência de dados e retorna um código de estado quando a operação de E/S termina. O programa pode continuar e acessar os dados transferidos imediatamente. Quando usados em sua forma mais simples, as rotinas da API Win32 ReadFile e WriteFile são executadas de forma síncrona. Elas completam uma operação de E/S antes de retornar o controle ao chamador. Operações de E/S assíncronas permitem que uma aplicação faça uma requisição de E/S e continue executando enquanto o dispositivo transfere os dados. Esse tipo de E/S pode melhorar o tempo de resposta de uma aplicação por permitir que a mesma continue a realizar outro tipo de trabalho enquanto espera pelo término de uma operação de E/S. Para usar uma operação assíncrona de E/S, deve-se especificar um flag denominado FILE_FLAG_OVERLAPPED quando for chamado a função CreateFile da API Win32. Após emitir a operação assíncrona de E/S, a thread deve ter cuidado para não acessar nenhum dado da operação de E/S até o driver de dispositivo terminar a transferência de dados. A thread deve sincronizar sua execução com o término da requisição de E/S monitorando um handle de um objeto de sincronização.
  • 24. Internamente, as operações de E/S são representadas por IRP’s que são realizados de forma assíncrona, ou seja, uma vez iniciada a requisição de E/S, o driver de dispositivo retorna ao sistema de E/S. O fato de o sistema de E/S retornar imediatamente ao chamador depende se o arquivo foi aberto de forma síncrona ou assíncrona. Por outro lado, a E/S rápida é um mecanismo especial que permite que o sistema de E/S vá diretamente ao driver de sistema de arquivo ou ao gerenciador de cache para completar uma requisição de E/S. A E/S mapeada em arquivo é um importante esquema do sistema de E/S, o qual é produzido pelo sistema de E/S e pelo gerenciador de memória. A E/S mapeada em arquivo refere-se a habilidade de visualizar um arquivo residente em disco como parte de um processo da memória virtual. Um programa pode acessar o arquivo como um vetor sem bufferizar os dados ou realizar E/S em disco. A E/S mapeada em arquivo está disponível em modo usuário através das funções do subsistema Win32 CreateFileMapping e MapViewOfFile e é rotineiramente usada para operações importantes como caching um arquivo e ativação de imagem (carregar e rodar programas executáveis). O gerenciador de cache é um consumidor importante desse esquema. Uma operação de requisição de E/S síncrona para um driver de dispositivo com camada única em modo kernel é descrito a seguir. Tal operação consiste de sete passos: 1. A requisição de E/S passa pelo subsistema DLL. 2. O subsistema DLL chama o serviço do gerenciador de E/S denominado NtWriteFile. 3. O gerenciador de E/S aloca um IRP descrevendo a requisição e o envia para o driver de dispositivo através de uma chamada para a função IoCallDriver. 4. O driver transfere os dados do IRP para o dispositivo e inicia a operação de E/S. 5. O driver sinaliza o término da E/S através de uma interrupção da CPU.
  • 25. 6. Quando o dispositivo completa a operação e interrompe a CPU, o driver de dispositivo dá assistência à interrupção. 7. O driver chama uma função do gerenciador de E/S chamado IoCompleteRequest, que informa o término do processamento da requisição de IRP, e o gerenciador de E/S completa a requisição de E/S. Esses sete passos são descritos na figura a seguir. Figura 4: Enfileirando e completando uma requisição de E/S Após um dispositivo de E/S completar uma transferência de dados, ocorre uma interrupção e o kernel do Windows NT, o gerenciador de E/S e o driver de dispositivo são chamados. Quando uma interrupção de dispositivo ocorre, o processador transfere o controle para o “trap handler” do kernel, o qual indexa na
  • 26. tabela de despache de interrupção a localização de uma rotina para tratamento de interrupção (ISR) para o dispositivo em questão. 2.5 Suporte a RAID O Windows NT oferece também suporte a RAID, tanto por hardware como por software. No suporte a RAID por hardware são oferecidos drivers de disco com capacidade de gerenciar controladoras RAID. Desta forma, diferentes discos podem trabalhar em conjunto para compor um ou mais discos lógicos. No RAID por hardware, a própria controladora gerencia a criação e a manutenção da informação de redundância necessária à recuperação dos dados [OLIVEIRA, 2004]. O suporte a RAID por software é disponível apenas nas versões server do Windows NT. Ele emula a partir de serviços do sistema operacional o funcionamento de uma controladora com suporte RAID. Um driver de dispositivo denominado FTDISK é responsável por essa tarefa. Esse driver oferece RAID 1 e RAID 5. 2.6 Plug-and-play Outro detalhe importante a respeito do NT são as melhorias introduzidas na funcionalidade plug-and-play, ou seja, a capacidade de um sistema de reconhecer e adaptar-se dinamicamente a alterações ou modificações em sua forma ou configuração inicial de hardware. Tal melhora traduz-se em um modelo genérico para implementação e gerência de drivers de dispositivo denominado WDM (Win32 Driver Model). Este modelo permite fácil portabilidade de drivers de dispositivos de um sistema operacional para outro. Os drivers de dispositivo que seguem o WDM permitem compatibilidade a nível de código binário entre todas as
  • 27. plataformas baseadas em processadores x86 executando Windows NT e Windows 98, e são portáveis a nível do código fonte para qualquer outra arquitetura. 2.7 Suporte a multiprocessamento O Windows NT oferece suporte a multiprocessamento. Um ambiente multiprocessado é aquele em que o mesmo código pode rodar simultaneamente em mais de um processador. Embora todo o sistema operacional precise estar envolvido com tal característica, é no sistema de E/S que o multiprocessamento fica mais evidente, mais especificamente nos drivers de dispositivo. Um driver pode ser executado em dois ou mais processadores simultaneamente, necessitando de uma sincronização aos dados do mesmo. Técnicas de exclusão mútua para proteção a recursos compartilhados devem ser utilizadas, já que, em um ambiente multiprocessado, podem ocorrer erros por inconsistência de dados. 2.8 Recuperação de falha de energia Cada driver de dispositivo tem de saber quando efetivamente ocorreu uma falha de energia, reajustando posteriormente o dispositivo por ele operado. Qualquer operação de E/S que tenha sido interrompida deve ser reinicializada, mas se isso não for possível, pelo menos o gerenciador de E/S deve ser notificado da falha em uma operação de E/S a fim de retornar uma condição de erro. O gerenciador de E/S, juntamente com o kernel, oferece um recurso que permite aos drivers de dispositivo lidar de forma razoavelmente tranqüila com interrupções no fornecimento de energia elétrica. Quando a energia acaba, ocorre uma interrupção de falha de energia e o sistema operacional tem um breve período de tempo para preparar-se para o blecaute. O kernel copia rapidamente
  • 28. para a memória todos os registros importantes do sistema, incluindo o contador de programa. Se a memória do computador estiver equipada com uma bateria reserva, estas informações são gravadas e, quando a energia voltar, o kernel e o sistema de E/S podem usá-las para reiniciar ou encerrar as operações de E/S que foram interrompidas. O sistema de E/S pode reiniciar ou encerrar as operações de E/S que foram interrompidas. No Windows NT, cada driver de dispositivo pode executar várias tarefas para ajudar na recuperação de falha de energia elétrica. Primeiro, cada driver de dispositivo pode criar e registrar uma rotina de recuperação de energia que reajusta o dispositivo para um estado conhecido após o blecaute. Depois de restaurado o fornecimento, o kernel localiza e executa a rotina de cada driver. Segundo, cada driver assegura que não será possível ocorrer uma interrupção de falha de energia enquanto o driver estiver gravando seqüências de dados críticos em seu dispositivo. Isto é importante porque, quando o fornecimento elétrico for restaurado, o processador dará continuidade a sua execução no contador de programa em que foi interrompido.
  • 29. 3. GERENCIAMENTO DE MEMÓRIA A arquitetura de memória do Windows NT é um sistema de memória virtual paginada por demanda. É baseada em um espaço de endereçamento contínuo e linear de 32 bits, que permite a cada processo do Windows NT acessar até 4 GB de memória. O Windows NT mapeia os endereços da memória virtual para a memória física em blocos de 4 KB, denominados páginas. Utilizando a memória virtual do Windows NT, parte do código e algumas informações dos aplicativos são mantidas na RAM, enquanto outras informações podem ser paginadas temporariamente na memória virtual. Quando as informações paginadas são requisitadas, o Windows NT as carrega de volta para a RAM, paginando outras informações para a memória virtual, se necessário. Este modelo de memória permite que os usuários executem aplicativos que utilizam mais memória do que a que o hardware suporta. Neste trabalho, apresentaremos como funciona o Gerenciamento de Memória no Windows NT, como o Windows NT implementa a memória virtual e como ele gerencia o subconjunto mantido na memória física. Estas atividades envolvem duas tarefas principais: • Traduzir ou mapear o espaço de endereços virtuais de um processo para a memória física. • Paginar parte do conteúdo da memória para o disco quando ela se tornar insuficiente e trazer o conteúdo de volta para a memória física quando for
  • 30. necessário. Além de fornecer o gerenciamento de memória virtual de 32 bits, o gerenciador de memória fornece um conjunto básico de serviços em que os vários subsistemas de ambiente do Windows NT são montados. Esses serviços incluem arquivos mapeados na memória (internamente chamados section object), memória de copy-on-write e suporte para aplicações usando espaços de endereços grandes e esparsos. Neste trabalho, mostraremos esses serviços básicos e explicaremos os conceitos pertinentes, como memória reservada versus comprometida, memória compartilhada e também a estrutura interna e os elementos que compõem o gerenciador de memória. 3.1 Memória Virtual A memória virtual do Windows NT foi implementada por Lou Perazzoli. Lou estabeleceu as seguintes metas para o gerenciador de memória virtual: • Torná-lo o mais portátil possível. • Ser confiável e eficiente em aplicações de todos os tamanhos, sem exigir adaptações do sistema por um usuário ou administrador. • Proporcionar recursos modernos de gerenciamento de memória, como arquivos mapeados, memória do tipo copy-on-write e suporte a aplicações que usam espaços de endereçamento grandes e possivelmente escassos. • Permitir aos processos alocar e gerenciar a memória privativa.
  • 31. • Proporcionar mecanismos que suportam os subsistemas de ambiente, como permitir a um subsistema (com os direitos apropriados de acesso) gerenciar a memória virtual de um processo cliente. • Equilibrar as necessidades de multiprocessamento com velocidade de acesso à memória. (Por exemplo, proteger as estruturas de dados usando vários níveis de bloqueio pode aumentar o paralelismo no gerenciador de memória virtual, mas cada bloqueio pode criar improdutividade adicional). O espaço de endereçamento virtual é o conjunto de endereços de memória disponíveis para uso pelas threads de um processo. Todo processo tem um espaço de endereçamento virtual exclusivo que normalmente é muito maior do que a memória física. Apesar de o número de endereços físicos de um determinado computador ser limitado pela quantidade de memória que o mesmo possui, o número de endereços de memória virtual só é limitado pelo número de bits de um endereço virtual. A discrepância entre um espaço de endereçamento físico e um espaço de endereçamento virtual torna inevitável as duas tarefas de um sistema de memória virtual: • Traduzir, ou mapear um subconjunto dos endereços virtuais de cada processo para localizações de memória física. Quando uma thread lê ou escreve em seu espaço de endereçamento virtual, o sistema de memória virtual usa o endereço virtual para encontrar o endereço físico correto antes
  • 32. de transferir os dados. • Gravar parte do conteúdo de memória para o disco quando as threads do sistema tentam usar mais memória do que há fisicamente disponível. A movimentação de dados da memória para o disco (e vice-versa) seria absurdamente lenta se o gerenciador de memória virtual movesse um byte de cada vez. É por isto que o espaço de endereçamento virtual é dividido em blocos de tamanho igual, chamados páginas. Já a memória física é dividida em blocos chamados de estruturas de página, que são usados para conter páginas. Cada processo tem um conjunto de páginas de seu espaço de endereçamento virtual presente na memória física em um dado momento. As páginas que estão na memória física e estão disponíveis são chamadas de páginas válidas. As páginas que estão armazenadas em disco (ou que estão na memória, mas não disponíveis) são chamadas de páginas inválidas, conforme ilustra a Figura 5.
  • 33. Figura 5: Mapeando Páginas Virtuais para estruturas de página físicas Quando uma thread em execução acessa um endereço virtual em uma página marcada como inválida, o processador emite uma trap de sistema chamada de falta de página. O sistema de memória virtual localiza a página solicitada no disco e carrega-a para uma estrutura de página livre na memória física. Quando o número de estruturas de página disponíveis fica baixo, o sistema de memória virtual seleciona estruturas de página para serem liberadas e copia seu conteúdo para o disco. Esta atividade, conhecida como paginação, é imperceptível ao programador. Apesar do mapeamento de endereços virtuais para endereços físicos e a
  • 34. transferência de dados de (ou para o) armazenamento swap serem as principais tarefas de um sistema de memória virtual, ele precisa cumprir outras obrigações também: • Permitir que dois processadores compartilhem a memória com facilidade e eficiência. • Proteger tanto a memória compartilhada quanto a memória privativa contra acesso desautorizado. • Se for executado em computadores multiprocessados, precisa responder a faltas de página de mais de uma thread de cada vez. 3.2 Gerenciando a Memória O gerenciador de Memória Virtual fornece um conjunto de serviços nativos que um processo pode usar para gerenciar diretamente sua memória virtual. Estes serviços permitem que um processo faça o seguinte: • Aloque memória em um processo de dois estágios. • Leia e escreva na memória virtual. • Bloqueie páginas virtuais na memória física. • Obtenha informações sobre páginas virtuais. • Proteja páginas virtuais. • Execute a operação de swapping.
  • 35. 3.2.1 Estados de uma página virtual Cada página virtual pode estar em um destes três estados: livre, reservado, ou commited. O gerenciador de memória virtual estabelece uma abordagem de duas fases para alocar memória: reservado e commited, através da função VirtualAlloc. Essas duas fases podem ser chamadas na mesma chamada de função através da função VirtualAllocEx. Uma página livre não está em uso atual e uma referência para ela causará uma falta. Quando um processo inicia, todas suas páginas estão no estado de livre até o programa e seus dados iniciais serem mapeados para o espaço de endereçamento. Uma vez que dados ou códigos são mapeados numa página, está página é dita como commited. Uma referência para uma página commited é mapeada usando o hardware de memória virtual, e é considerado um sucesso se a página está na memória principal. Se a página não estiver na memória principal, uma falta de página ocorre e o sistema operacional faz uma busca no disco para encontrar essa página e traze-la para a memória principal. Uma página virtual pode também estar no estado de reservada, significando que ela não está disponível para ser mapeada até a reserva ser removida explicitamente. Uma referência a uma página reservada causará uma falta, pois ela não está mapeada. Pode-se ver a vantagem de possuir página reservada quando, por exemplo, uma nova thread é criada, 1 MB de espaço de pilha é
  • 36. reservada no espaço de endereçamento virtual do processo, mas apenas uma página é alocada. Essa técnica significa que a pilha pode crescer eventualmente até 1 MB sem o receio de que alguma outra thread aloque o pedaço de espaço de endereçamento virtual contíguo necessário. Em adição aos atributos livre, reservado e alocado, as páginas possuem outros atributos, tais como passível de leitura, passível de escrita e executável. Por questão de desempenho, o Windows NT permite que um processo, com privilégios necessários, possa bloquear páginas em memória, fazendo com que essas páginas nunca sofram procedimento swapping. Finalmente, quando é reservada uma região do espaço de endereços, o Windows NT assegura que o tamanho da região seja um múltiplo do tamanho da página do sistema, qualquer que seja. Por exemplo, como os sistemas x86 usam páginas de 4 KB, se se tentasse reservar uma região da memória com 18 KB, a quantidade real reservada em um sistema x86 seria 20 KB. 3.2.2 Memória Compartilhada Assim como todos os outros componentes do Windows NT, o gerenciador de memória virtual é totalmente paralelo. Ele roda simultaneamente em todos os processadores de um computador multiprocessado e tem de compartilhar suas estruturas de dados com as threads que estão sendo executadas em processadores diferentes. Portanto, era importante criar uma solução segura e eficiente para o compartilhamento de memória no Windows NT.
  • 37. Memória compartilhada pode ser definida como a memória que é visível a partir de mais de um processo ou que está presente em mais de um espaço de endereçamento virtual. A abordagem do Windows NT ao compartilhamento de recursos é implementá-los como objetos protegidos e a memória não é nenhuma exceção. Dois processos podem compartilhar um mesmo espaço de endereçamento de memória, ver Figura 6. O Windows NT chama um bloco de memória compartilhada de section object, e oferece uma abstração de visão para os processos. Essa abstração consiste em um processo de mapear uma porção de seu espaço de endereçamento a um objeto, o qual é utilizado por outros processos para acessos compartilhados a essa porção. O mecanismo de abstração de visão também permite que em caso de swapping de uma região compartilhada de memória, as páginas correspondentes a essa região sejam transferidas ou para a área de swap ou para um arquivo especial chamado mapped file. Também é possível fixar um endereço virtual para essa região, permitindo que ela resida sempre em um mesmo endereço virtual em todos os processos que a utilizam.
  • 38. Figura 6: Mapeando Visões em uma Seção O executivo do NT usa os arquivos mapeados para carregar imagens executáveis para a memória e o gerenciador de cache do sistema usa os arquivos mapeados para ler e gravar em páginas da cache. O sistema de E/S do NT usa os
  • 39. arquivos mapeados para executar solicitações de entrada e saída, permitindo ao gerenciador de memória virtual paginar para o disco qualquer mudança ocorrida, como parte de suas operações normais de paginação. 3.2.2.1 Section Object Os objetos de seção, assim como outros objetos, são alocados e desalocados pelo gerenciador de objetos. Este cria e inicializa um cabeçalho de objeto, o qual é utilizado para gerenciar os objetos; o gerenciador de memória virtual define o corpo do section object. O gerenciador de memória virtual também implementa serviços que as threads do modo usuário podem chamar para recuperar e alterar os atributos armazenados no corpo dos section object. O section object pode ser visto na Figura 7. Figura 7: Section Object
  • 40. Mapear a visão de um section object torna visível uma parte da seção no espaço de endereçamento virtual de um processo. Igualmente, desmapear a visão de um section object remove-a do espaço de endereçamento virtual do processo. O compartilhamento ocorre quando dois processos mapeiam partes do mesmo objeto de seção em seus espaços de endereçamento. Quando dois processos compartilham memória desta maneira, eles precisam sincronizar seus acessos a ela para evitar a alteração de dados ao mesmo tempo. Eventos, semáforos ou mesmo bloqueios dependentes do hardware podem ser usados para sincronizar o acesso a uma seção compartilhada. Os section objects propriamente ditos não são definidos como objetos de sincronização; ou seja, uma thread não pode sincronizar sua execução aguardando um handle para um section object. As aplicações do Win32 podem usar mutexes, eventos, seções críticas ou semáforos para sincronizar seu acesso ao objeto de mapeamento de arquivo - equivalente a um section object. Para mapear a visão de uma seção, o processo precisa primeiro adquirir um handle para ela. O processo que cria o section object sempre tem um handle. Outros processos (aqueles com direito de acesso apropriado) podem abrir handles para o section object se a seção tiver nome. Alternativamente, o processo pode receber um handle para um section object através de herança ou quando um outro processo duplica seu handle de seção e passa o handle duplicado para o processo receptor. O compartilhamento de memória ocorre em todos estes casos. Se uma seção compartilhada é criada como objeto temporário, o gerenciador de
  • 41. objetos elimina a memória compartilhada quando a última referência ao section object é emitida. 3.2.3 Proteção de Memória O Windows NT oferece proteção de memória para os processos e para o sistema operacional. O objetivo dessa proteção é que nenhum processo do usuário possa inadvertidamente corromper o espaço de endereço de outro processo (ou do próprio sistema operacional). Essa proteção é fornecida de quatro formas: • Todas as estruturas de dados e memory pools em nível de sistema usados pelos componentes do modo kernel do sistema só podem ser acessados estando no modo kernel. Se houver uma tentativa de violação dessa condição, o hardware gerará uma falta, que por sua vez o gerenciador de memória informa a thread como uma violação de acesso. • Cada processo possui um espaço de endereçamento separado e privado, protegido contra acesso por qualquer thread que pertença a outro processo (exceto quando a memória compartilhada está sendo usada, nesse caso, apenas as páginas compartilhadas podem ser vistas por mais de um processo). • Todos os processadores aceitos pelo Windows NT oferecem alguma forma de proteção de memória controlada pelo hardware (como leitura/escrita,
  • 42. apenas leitura e assim por diante). • Os section object da memória compartilhada possuem listas de controle de acesso (ALCs) padrão do Windows NT, que são verificadas quando os processos tentam abri-los, limitando assim o acesso da memória compartilhada aos processos com os devidos direitos. Essa ultima forma é chamada de cópia-na-escrita (Copy-on-Write). A proteção de página por cópia-na-escrita é uma otimização que o gerenciador de memória usa para economizar a memória física. Quando um processo mapeia uma visão de cópia-na-escrita de um section object que contém páginas de leitura/escrita, em vez de criar um processo de cópia privada quando a visão for mapeada, o gerenciador de memória adia a criação de uma cópia das páginas até que a página seja modificada. Por exemplo, como vemos na Figura 8, dois processos estão compartilhando três páginas, cada uma marcada como cópia-na- escrita. Figura 8: Antes do copy-on-write
  • 43. Se um thread em qualquer processo escreve na página, uma falta de gerenciamento de memória é gerada. O gerenciador de memória vê que a escrita é para uma página de cópia-na-escrita e, em vez de informar a falta como uma violação de acesso, ele reserva uma nova página de leitura/escrita na memória física (copiando a página no arquivo de paginação), copia o conteúdo da página original para a nova página, atualiza a informação de mapeamento de página correspondente nesse processo apenas para apontar para o novo local e dispensa a exceção, fazendo assim com que a instrução que gerou a falta seja novamente executada. Dessa vez, a operação de escrita tem sucesso, mas, como vemos na Figura 9 a seguir, a página recém copiada agora é privada ao processo que fez a escrita, e não é visível aos outros processos que ainda compartilham a página de cópia-na-escrita. Cada novo processo que escreve nessa mesma página compartilhada também receberá sua própria cópia privada. Figura 9: Depois do copy-on-write
  • 44. A cópia-na-escrita é usada para implementar o suporte para ponto de interrupção (breakpoint) nos depuradores. A proteção de página cópia-na-escrita é um exemplo de uma técnica de otimização chamada Avaliação Preguiçosa (lazy evaluation), que o gerenciador de memória virtual utiliza sempre que possível. Os algoritmos de avaliação preguiçosa evitam efetuar uma operação dispendiosa até que ela seja absolutamente necessária. Se a operação nunca foi solicitada, então não se perde tempo com ela. 3.3 Implementação A maioria dos sistemas operacionais de 32 bits utilizam um espaço de endereçamento virtual de até 4 GB de memória virtual, separando metade dessa memória virtual para o sistema operacional e a outra metade para dados e códigos dos usuários. O Windows NT também utiliza esse método e podemos observar essa distribuição na Figura 10. O NT também oferece uma opção para modificar a alocação de memória para um processo, de forma que esse possa ter 3 GB para usuário e apenas 1 GB ao sistema operacional. Essa modificação é muito útil para algumas aplicações, tais como banco de dados, que passaram a poder armazenar uma parcela maior de dados dentro do espaço endereçado da própria aplicação. O Windows NT ainda prevê uma extensão denominada VLM(Very Large Memory),
  • 45. para arquiteturas de 64 bits, que permite um processo usuário alocar até 28 GB de memória virtual suplementar. Figura 10: Espaço de Endereçamento Virtual Os primeiros e os últimos 64KB do espaço de endereçamento virtual de cada processo normalmente não são mapeados. Esta escolha foi feita intencionalmente para ajudar na captura de erros dos programas. Ponteiros inválidos freqüentemente possuem os valores 0 ou -1 e tentativas de usá-los no Windows NT causariam uma parada imediata, ou pior, escreveriam em um local incorreto da memória. Em contra partida, quando está sendo rodado em modo de emulação programas do antigo MS-DOS, esses 64 + 64 KB podem ser mapeados.
  • 46. A partir do kilobyte 64, temos os códigos e dados privados do usuário, isto extende-se até quase 2 GB. Os últimos pedaços dos primeiros 2 GB contém alguns contadores do sistema e temporizadores que são compartilhados para todos os usuários dando-lhes permissão de leitura, somente. Isso permite aos processos acessá-los sem um overhead de chamada de sistema. Os outros 2 GB são compartilhados entre todos os processos, exceto a tabela de páginas, o qual cada processo utiliza a sua. Esses 2 GB não são passiveis de escrita e também não podem ser lidos por processos de modo usuário. 3.3.1 Mecanismos de Paginação Todo processador que suporta a memória virtual o faz de maneira diferente. Conseqüentemente, o código que tem interface direta com o hardware de memória virtual não é portátil e tem de ser modificado para cada plataforma. Os endereços virtuais freqüentemente usados provavelmente têm inserções na TLB (Translation Look-aside Buffer), que propicia traduções extremamente rápidas de endereço físico para virtual. Se um endereço virtual não está presente na TLB, ele poderá estar na memória, mas o software de memória virtual terá de encontrá-lo, caso em que o tempo de acesso é ligeiramente mais lento. Se uma página virtual foi paginada fora da memória, o sistema de memória virtual invalida sua entrada na TLB. Se um processo a acessa novamente, ocorre uma falta de página e o gerenciador de memória virtual traz a página novamente para a memória e recria uma entrada para ele na TLB.
  • 47. O kernel e o gerenciador de memória virtual usam tabelas de páginas criadas por software para encontrar páginas que não estão presentes na TLB. As tabelas de páginas estão disponíveis na maioria dos sistemas de memória virtual: às vezes, elas são implementadas pelo hardware, e às vezes, pelo software. Em termos conceituais, a tabela de páginas assemelha-se à estrutura de dados mostrada na Figura 11. Figura 11: Tabela de Páginas Conceitual Uma entrada na tabela de páginas (PTE - page table entry) contém todas as informações necessárias para o sistema de memória virtual localizar uma
  • 48. página quando uma thread usa um endereço. Em um sistema de memória virtual simples, uma entrada inválida em uma tabela de páginas significa que a página não está na memória física e tem de ser carregada do disco. Ocorre uma exceção de falta de página e o software de paginação carrega a página solicitada para a memória e atualiza a tabela. O processador reemite a instrução que gerou a falta de página. Desta vez, porém, a inserção da tabela de páginas é válida e os dados são recuperados da memória com sucesso. No momento de localizar uma entrada na tabela de páginas, o gerenciador de memória virtual (e o kernel do NT) traduz o endereço virtual do formato MIPS para o endereço no formato Intel, usando partes diferentes dele como deslocamentos na estrutura da tabela de páginas. Além disso, uma inserção na TLB sempre contém o endereço virtual base do diretório de página do processo atualmente em execução (É este o motivo pelo qual um processo usuário não pode “ver” o espaço de endereçamento do outro. Eles têm diretórios de página diferentes, que apontam para tabelas de páginas diferentes). As entradas da tabela de páginas nestas tabelas definidas pelo NT representam um aperfeiçoamento sobre a tabela conceitual mostrada anteriormente. Cada entrada da tabela de páginas (e cada entrada do diretório de página) tem um sinalizador de transição. Se a entrada da tabela de páginas está marcada como inválida e o sinalizador de transmissão está ativado, a página é escolhida para ser reutilizada, mas seu conteúdo ainda é válido. Validar uma página transicional é uma operação muito rápida porque o gerenciador de
  • 49. memória virtual não precisa ler a página do disco para a memória. As entradas da tabela de páginas também contêm sinalizadores que registram as proteções a nível de página que o gerenciador de memória virtual aplica a cada página. Quando uma estrutura de página é compartilhada por dois processos, o gerenciador de memória virtual insere um artifício nas suas tabelas de páginas. A estrutura de dados que ele insere é chamada de protótipo de entrada na tabela de páginas (protótipo PTE). O protótipo PTE, uma estrutura de 32 bits que parece com uma entrada de tabela de páginas normal, permite ao gerenciador de memória virtual gerenciar as páginas compartilhadas sem precisar atualizar as tabelas de páginas de cada processo que compartilha a página. Por exemplo, uma página de código ou de dados compartilhada pode ser paginada para o disco em um determinado momento. Quando o gerenciador de memória virtual recupera a página do disco, ele só precisa atualizar o ponteiro armazenado no prótipo PTE para a nova localização física, e as tabelas de páginas permanecem as mesmas. Os protótipos de PTE são alocados no espaço paginado do sistema, portanto, como as entradas na tabela de páginas, podem sofrer swapout, se necessário. 3.3.2 Políticas de Paginação Os sistemas de memória virtual geralmente definem três políticas que ditam como (ou quando) a paginação é efetuada: uma política de busca, uma política de colocação e uma política de substituição.
  • 50. A política de busca determina quando o paginador deve trazer a página do disco para a memória. Um tipo de política de busca tenta carregar as páginas que um processo irá precisar antes que ele as solicite. Outras políticas de busca, chamadas de políticas de paginação por demanda, carregam uma página para a memória física apenas quando ocorre uma falta de página. Em um sistema de paginação por demanda, o processo incorre em muitas faltas de página quando suas threads são executadas pela primeira vez, porque elas fazem referência ao conjunto inicial de páginas que lhes são necessárias. Depois que este conjunto de páginas é carregado para a memória, a atividade de paginação do processo diminui. Quando uma thread recebe uma falta de página, o sistema de gerencia- mento de memória também tem de determinar onde colocar a página virtual na memória física. O conjunto de regras que ele usa chama-se política de colocação. As políticas de colocação, embora normalmente complicadas para arquiteturas de memória segmentada, em geral são simples para arquiteturas lineares, que requerem que apenas uma estrutura de página livre seja encontrada. No NT, se a memória não está esgotada, o gerenciador de memória virtual simplesmente seleciona a primeira estrutura de página em uma lista de estruturas de página livres. Se a lista está vazia, ele cruza uma série de outras listas por ele mantidas; a ordem dependerá do tipo de falta de página ocorrido. Se a memória física estiver repleta quando ocorrer uma falta de página, uma política de substituição é usada para determinar que página virtual deve ser
  • 51. removida da memória para liberar espaço para a página nova. As políticas de substituição de página no Windows NT variam de acordo com a arquitetura ou processador. Para arquiteturas do tipo multiprocessador baseadas em processadores da família Intel, e em todas as máquinas baseadas em processadores da família Alpha, a estratégia utilizada é essencialmente FIFO (First In, First Out) local. Nessa estratégia, considera-se para fins de seleção da página a ser substituída em memória, apenas as páginas pertencentes ao processo. Nas arquiteturas de monoprocessadores Intel, o algoritmo de seleção de página a ser substituída é LRU (least recently used). Implementado através do algoritmo do relógio, o algoritmo LRU exige que o sistema de memória virtual registre quando uma página de memória é usada. Quando uma nova estrutura de página é solicitada, a página que não foi usada há mais tempo é paginada para o disco e sua estrutura é liberada para satisfazer a falta de página. 3.3.3 Gerenciamento da memória física O número de páginas que um processo ocupa na memória é armazenado através do mecanismo de working set. Para cada processo, é definido um valor mínimo e um valor máximo para o tamanho desse working set, a partir do tamanho da memória física. Quando há uma elevada ocorrência de falta de página, o gerenciador da memória inicia uma verificação do working set de todos os processos residentes na memória. Os processos que tiverem mais páginas na memória que o valor mínimo terão seus working sets reduzidos, e suas áreas de
  • 52. memórias liberadas serão disponibilizadas para serem alocadas por outros processos. O gerenciador da memória física armazena a movimentação das páginas na memória através de listas . Cada página contida na memória está presente dentro do working set de algum processo ou em algumas dessas listas. Essas listas são apresentadas a seguir: • Listas de páginas disponíveis (limpas): contêm as páginas que foram recentemente removidas do working set de algum processo, mas ainda estão associadas a ele. Essas páginas possuem uma cópia no disco, podendo assim, serem descartadas pelo processo. • Listas de páginas modificadas (sujas): contêm as páginas que também foram recentemente removidas do working set de algum processo, mas ainda estão associadas a ele. Essas páginas porém não possuem uma cópia atualizada no disco. • Listas de páginas livres: contém as páginas que não estão associadas a nenhum processo. • Listas de páginas zeradas: contém as páginas que também não estão associadas a nenhum processo, mas estão preenchidas com zero. • Listas de páginas com defeito físico: contém as páginas que estão relacionadas com alguma porção de memória RAM que apresenta defeito. • Essa lista garante que tais páginas não serão mais acessadas.
  • 53. 3.3.4 Tradução de Endereços A tradução de um endereço virtual em um endereço físico é realizada da seguinte forma. Inicialmente, utilizando a parte mais significativa do endereço virtual (índice de diretório de páginas), o diretório de páginas é acessado para determinar qual tabela de páginas está associada ao endereço virtual que se deseja traduzir. Uma vez definida a tabela de páginas, o índice de tabela de páginas é empregado para determinar a página correspondente a esse endereço virtual. A entrada da tabela de páginas fornece informações de controle e a localização em memória da página a ser acessada (se presente). Finalmente, o índice de byte é somado ao endereço inicial da página em memória, resultando no endereço físico correspondente ao endereço virtual desejado. A Figura 12 apresenta a relação entre esses três valores e a forma pela qual eles são utilizados para mapear um endereço virtual em endereço físico.
  • 54. Figura 12: Esquema de tradução de endereço virtual para endereço físico em arquiteturas Intel Cada processo possui um único diretório de página para mapear a localização das tabelas de paginas pertencentes a esse processo. O diretório de páginas possui 1024 entradas o que limita o numero máximo de tabelas de páginas de um processo. As tabelas de paginas são criadas sob demanda; por conseqüência, normalmente, muitas das entradas do diretório de paginas não são válidas. Cada tabela de página possui, por sua vez, também 1024 entradas, o que, de forma análoga, limita a quantidade de páginas por tabela de páginas. O tamanho de cada entrada, tanto do diretório de paginas quanto da tabela de
  • 55. paginas, é de 4 bytes. Isso implica que cada uma dessas estruturas ocupem 4 KB de memória, ou seja, exatamente uma página. Essas tabelas são armazenadas no espaço de endereçamento virtual do processo, na área destinada ao sistema operacional, e sua localização exata é mantida no descritor de processo. 3.3.5 Tratamento de Falta de Página Uma referência a uma página inválida é chamada falta de página. O manipulador de trap do kernel despacha esse tipo de falta para o manipulador de falta do gerenciador de memória (MmAccessFault) resolver. Essa rotina é executada no contexto da thread que incorreu na falta e é responsável por tentar resolver a falta (se possível) ou levantar uma exceção apropriada. Páginas no Windows NT variam de 4 KB à 64 KB, dependendo da arquitetura. O Pentium, por exemplo, utiliza 4 KB. O algoritmo de paginação do Windows NT é baseado por demanda com clustering (em grupos). Quando ocorre uma falta de página, o gerenciador de memória carrega na memória a página que faltava e mais um pequeno número de páginas ao seu redor. Essa estratégia visa minimizar a taxa de faltas, explorando o princípio de localidade. Quando um processo é iniciado, são trazidas páginas para a memória a medida que ocorrem faltas de páginas. Essas faltas ocorrem quando: • A página referenciada não está commited. • A página está commited, mas não está mapeada.
  • 56. • Uma página compartilhada foi escrita. • Ocorreu uma violação de proteção. • A pilha precisa crescer. 3.3.6 Descritores de Endereço Virtual Anteriormente nós descrevemos as políticas de paginação que o gerenciador de memória virtual usa para determinar quando uma página deve ser trazida para a memória, onde colocá-la e que páginas remover quando a memória se esgota. O gerenciador de memória virtual usa um algoritmo de paginação por demanda para saber quando carregar páginas para a memória. Ele espera até que alguma thread use um endereço e incorra em uma falta de página para depois recuperar uma página do disco. Este tipo de paginação por demanda é uma forma de avaliação preguiçosa. Os algoritmos de avaliação preguiçosa evitam executar uma operação dispendiosa, como a paginação, até que ela seja absolutamente necessária. O gerenciador de memória virtual usa a avaliação preguiçosa em uma outra área, aquela da construção de tabelas de páginas. Por exemplo, quando uma thread aloca uma grande região de memória virtual, o gerenciador de memória virtual poderia construir imediatamente as tabelas de páginas necessárias para acessar toda a faixa de memória alocada. Entretanto, se a aplicação não usa toda
  • 57. a memória alocada, a construção das tabelas de páginas é um esforço inútil. Conseqüentemente, o gerenciador de memória virtual espera para construí-las somente quando uma thread incorre em uma falta de página. O uso da avaliação preguiçosa desta maneira resulta em ganho significativo de desempenho para as aplicações que reservam muita memória, mas raramente a usam. Alocar memória, mesmo grandes blocos de memória, é extremamente rápido com o algoritmo de avaliação preguiçosa. No entanto, o ganho de desempenho também tem suas desvantagens. Quando uma thread aloca memória, o gerenciador de memória virtual tem de responder com uma faixa de endereços virtuais que a thread poderá usar. Contudo, como o gerenciador de memória virtual só carrega a tabela de páginas do processo quando a thread acessa a memória, ele não tem condições de examinar a tabela de páginas para determinar que endereços virtuais estão livres. Portanto, o gerenciador de memória virtual precisa manter um outro grupo de estruturas de dados para registrar que endereços virtuais já foram alocados no espaço de endereçamento do processo e quais ainda não foram. Os descritores de endereço virtual atendem esta necessidade. Para cada processo, o gerenciador de memória virtual mantém um conjunto de descritores de endereço virtual que descrevem o status do espaço de endereçamento virtual do processo. Quando um processo aloca memória (ou mapeia uma visão de memória compartilhada), o gerenciador de memória virtual cria um descritor de endereço
  • 58. virtual para armazenar qualquer informação fornecida na solicitação de alocação, como a faixa de endereços que está sendo alocada, se a faixa será memória compartilhada ou privativa, se um processo filho pode herdar o conteúdo da faixa, e a proteção aplicada às páginas daquela faixa. Depois ele insere o descritor de endereço virtual em uma árvore específica do processo (uma árvore binária equilibrada) para acelerar sua localização. Quando uma thread acessa um endereço pela primeira vez, o gerenciador de memória virtual precisa criar uma entrada na tabela de páginas para a página que contém o endereço. Para tanto, ele localiza o descritor de endereço virtual cuja faixa de endereço também contém o endereço acessado e usa a informação encontrada para preencher a entrada na tabela de páginas. Se o endereço estiver fora da faixa coberta pelo descritor de endereço virtual, o gerenciador de memória virtual saberá que a thread não alocou este endereço de memória antes de usá-lo. Ocorre então, uma violação de acesso. 3.4 Chamadas ao Sistema O Win32 API contém um numero de funções que permitem que um processo gerencie sua própria memória virtual. Essas funções operam sobre uma seqüência de duas ou mais páginas consecutivas no espaço de endereçamento virtual. A Figura 13 mostra algumas dessas funções.
  • 59. Função API Win 32 Descrição VirtualAlloc Reserva ou commit uma região VirtualFree Libera ou uncommit uma região VirtualProtect Altera a proteção de leitura/escrita/execução de uma região VirtualQuery Pergunta sobre o estado de uma região VirtualLock Torna uma região residente em memória VirtualUnlock Torna a região paginável, da maneira usual CreateFile Mapping Cria um objeto de mapeamento de arquivo e (opcionalmente) atribui um nome a ele MapViewOfFile Mapeia um arquivo, ou parte dele, no espaço de endereçamento UnmapViewOfFile Remove um arquivo mapeado do espaço de endereçamento OpenFileMapping Abre um objeto de mapeamento de arquivo criado anteriormente Figura 13: Principais funções API Win32 para gerenciamento da memória virtual
  • 60. 4. GERÊNCIA DE PROCESSOS 4.1 Caracterização de Jobs, Processos, Threads e Fibers Um Job pode ser considerado como uma coleção de um ou mais processos que irão ser gerenciados como uma única unidade, compartilhando certos atributos, além de prover restrições de segurança nos processos que estão no Job. Como no Unix, um processo pode ser considerado uma instância em execução de um programa. Ele tem um espaço de endereçamento privado contendo seu código e dados. Enquanto ele é executado, o sistema operacional pode alocar recursos do sistema como semáforos e portas de comunicação. Um processo tem de ter no mínimo uma Thread, pois a Thread é a unidade a ser escalonada pelo kernel. Um processo executando no modo usuário invoca o sistema operacional através das chamadas de sistema. Através do sistema de traps, o seu modo de execução passa a ser o modo do sistema (privilegiado) e então ele entra e executa no sistema operacional e após a execução ele retorna ao modo usuário. Processos também são representados como objetos, então eles são manipulados através do serviço de gerenciamento de processos, como mostra a figura 14. O processo tem uma prioridade base usada para o escalonamento das Threads e uma afinidade com um processador padrão, que indica o conjunto de processadores no qual as Threads desse processo irão rodar. O quota limit especifica a quantidade máxima de memória paginada e não-paginada e tempo de processador. O tempo total de CPU e os recursos utilizados pelo processo são contados em tempo de execução, assim como os contadores de E/S e os contadores de operação da máquina virtual.
  • 61. Figura 14: Representação de um processo como objeto Um processo pode criar múltiplas Threads para executar no seu espaço de endereçamento e ambos os objetos do processo e objetos das Threads possuem capacidade de sincronização embutida. Threads são executadas no modo usuário durante grande parte do tempo, mas ao realizar uma chamada ao sistema, elas rodam no modo kernel, retendo suas características anteriores. Para administrar a mudança de modo de execução, cada Thread possui duas pilhas, uma usada no modo usuário e outra usada no modo kernel. Uma vez que uma Thread tenha sido criada ela é gerenciada de forma independente a seu processo pai, pois não existe nenhuma forma de hierarquia entre os processos no Windows NT. A figura 15 mostra o objeto que representa uma Thread. O ID do cliente identifica uma
  • 62. Thread de forma única. O contexto da Thread inclui o estado de memória da Thread e o seu estado de execução. Outro fato importante de salientar é que somente a Thread tem um indicador do estado da execução, visto que ela é a unidade básica a ser escalonada. Figura 15: Representação de uma Thread como um objeto Também existe uma forma de Thread leve, que é chamada de Fiber. Ao contrário de Threads, Fibers são totalmente gerenciadas no modo usuário e são invisíveis para o kernel. O Kernel gerencia as Threads e uma Thread em execução pode cooperativamente mudar de uma Fiber para outra através da diretiva SwitchToFiber. Cada Fiber tem um registro de estado associado, uma pilha, informação de tratamento de exceções e o valor de dado da Fiber. Esse gerenciamento de escalonamento no nível de usuário significa que para o funcionamento das Fibers é necessário cuidado. Se um bloco de uma Fiber em
  • 63. execução é bloqueado, toda a Thread é bloqueada. Uma aplicação utilizando fibers só pode aproveitar o poder de multiprocessamento caso exista mais de uma Thread no processo, e precisará ter controle de concorrência, pois pode ocorrer de diversas threads tentarem ceder a execução para uma Fiber. Uma aplicação que deseja usar Fibers deve utilizá-la explicitamente através do comando ConvertThreadToFiber. 4.2 Técnicas de comunicação Existem diversas técnicas para a comunicação entre threads, sendo alguma delas as pipes, pipes nomeados, mailsots, sockets, chamadas remotas de procedimento e arquivos compartilhados. Pipes tem dois modos de operação, byte e mensagem, selecionados em tempo de criação. O modo de byte funciona de forma análoga ao Unix, e o modo de mensagem preserva os limites de cada uma das mensagens. Pipes nomeados funcionam como pipes comuns, mas com suporte a uso na rede. Mailslots tem funcionamento similar ao de pipes, mas com algumas diferenças, como é uma técnica de comunicação unidirecional, enquanto pipes são bidirecionais. Mailslots tem suporte a transmissão via rede, mas sem garantia de entrega da mensagem. Outra característica importante é que mailslots permitem a transmissão de uma mensagem para diversos destinatários. Sockets tem principal utilização na conexão de processos em máquinas diferentes (remotas). Sockets podem até ser utilizados para conectar processos na mesma máquina, mas devido a ter um overhead mais alto que pipes, sua utilização fica mais restrita ao contexto de uma rede. A chamada de procedimentos remotos é uma maneira de comunicação que permite que um processo tenha acesso ao espaço de endereçamento de outro processo. Esta técnica tem restrições nos parâmetros, visto que seria inútil repassar um ponteiro para um processo diferente.
  • 64. Arquivos compartilhados são simplesmente áreas de memória compartilhada entre processos, possibilitando que um processo altere e outro leia as informações em uma área de memória especificada. 4.3 Técnicas de sincronização Assim como as técnicas de comunicação entre os processos, existem diversas técnicas de sincronização, para prover uma alternativa viável para cada tipo de situação. Algumas das técnicas de sincronização são semáforos, mutex, regiões criticas e eventos. Todas essas ferramentas são aplicáveis a threads, não a processos, visto que somente processos são escalonáveis. Semáforos são criados pela função CreateSemphore da API, que o inicia com um valor e também determina o valor máximo. Semáforos são objetos do kernel e tem descritores de segurança e handles. O handle para um semáforo pode ser duplicado utilizando DuplicateHandle e então o semáforo pode ser repassado para outros processos, permitindo sua utilização em múltiplos processos. Mutex são objetos do kernel utilizados para sincronização, mas com uma estrutura mais simples do que semáforos devido a ausência de contadores. Funcionam essencialmente com duas operações da API, WaitForSingleObject (responsável pelo bloqueio) e ReleaseMutex (responsável pela liberação). Os handles do mutex também podem ser duplicados, possibilitando o uso de um mutex para controle de threads em processos diferentes. Seções críticas são similares a mutex, mas são locais em relação a thread que as criou, ou seja, não são objetos do kernel, não tendo descritores de segurança ou handles, logo só são vistas por um processo. O bloqueio e a liberação são realizadas pelas funções EnterCrticalSection e LeaveCriticalSection, respectivamente. Devido a essas funções da API serem executadas no espaço do usuário e somente realizarem chamadas ao kernel quando é necessário realizar o bloqueio, essa técnica é mais rápida que mutex.
  • 65. O último tipo de sincronização são os eventos, que podem ser de dois tipos, eventos de reset manual ou eventos de reset automático. Um evento pode estar em dois estados, setado ou livre. Uma thread pode esperar por um evento através da função WaitForSingleObject. Se outra thread sinalizar um evento com SetEvent. O que ocorre após o evento ser setado depende do tipo de evento: em um evento de reset manual todos os threads na espera são liberados, o evento permanece setado até que seja usado o comando ResetEvent; no caso com reset automático, se uma ou mais threads estão esperando, somente uma thread é liberada, e o evento fica livre. 4.4 Criação de Processos e Threads A criação de novos processos é realizada pela função CreateProcess, sendo uma forma mais complexa do que a criação de processos em Unix, devido ao fato dessa função levar dez parâmetros, que são citados a seguir: 1. Um ponteiro para o nome do arquivo executável. 2. A própria linha de comando. 3. Um ponteiro para o descritor de segurança do processo. 4. Um ponteiro para o descritor de segurança da thread inicial. 5. Um bit que define se o processo herda o handle do criador. 6. Diversos flags. 7. Um ponteiro para strings do ambiente. 8. Um ponteiro para o nome do diretório atual do novo processo. 9. Um ponteiro para a estrutura que descreve a janela inicial na tela. 10. Um ponteiro para a estrutura que retorna 18 valores para o realizador da chamada. Apesar de não haver hierarquia entre os processos, um dos valores retornados ao realizador da chamada é o handle do novo processo, assim é possível uma hierarquia implícita entre os processos.
  • 66. A criação de threads por sua vez é relativamente menos complexa que a criação de processos, utilizando a função CreatThread e tendo somente 6 parâmetros, descritos a seguir: 1. O descritor de segurança opcional. 2. O tamanho inicial da pilha. 3. O endereço inicial. 4. Um parâmetro definido pelo usuário. 5. O estado inicial da Thread (pronta ou bloqueada). 6. O ID da Thread. 4.5 Escalonamento O escalonamento não é realizado por uma thread de escalonamento central. O sistema de escalonamento consiste em quando uma thread deixa de ser apta à execução, ela entre no modo do kernel e executa o escalonador para decidir qual a thread que será executada. Existem três situações que podem ocorrer para uma thread deixar de ser apta a execução: 1. A thread é bloqueada por uma ferramenta de sincronização. 2. A thread interage com outro objeto. 3. O quantum da thread em questão expira. No primeiro caso, a thread já estará rodando no modo do kernel, logo ela só deve salvar seu contexto, acionar o escalonador e escolher o seu sucessor que será carregado. No segundo caso, a thread também já estará executando no modo do kernel, mas sua interação poderá não resultar no seu bloqueio, logo a thread deve executar o escalonador para descobrir se sua ação não causou a liberação de uma thread com prioridade maior, pois se isso ocorrer ela deverá ceder a vez. No terceiro caso, um trap para o modo do kernel ocorre, e então a thread executará o escalonador, mas dependo do estados das outras threads, a mesma thread poderá ser selecionada para ser executada, recebendo um novo quantum, caso contrário será escolhida outra thread.
  • 67. O escalonador também poder ser chamado em duas outras ocasiões: 1. Quando uma operação de E/S é terminada. 2. Quando um tempo de espera termina. Quando uma operação de E/S é terminada, uma thread poderá ser liberada, logo é necessário a execução do escalonador para determinar se essa thread que será liberada poderá ser executada. Na segunda situação, uma thread que estava bloqueada tem seu tempo de espera esgotado, tornando-se apta para a execução novamente e assim é necessária a execução do escalonador. O sistema de escalonamento leva em conta um sistema de prioridades com 32 níveis, que variam de 0 a 31, sendo que existe a prioridade base, que é determinada de acordo com a Figura 16. E também existe a prioridade atual do processo, que nunca poderá ser menor do que o valor da prioridade base, mas poderá ser maior de acordo com as situações ocorridas no sistema. Figura 16: Tabela de prioridades do Windows 2000
  • 68. 5. SISTEMA DE ARQUIVOS Este capítulo tem por objetivo apresentar o sistema de arquivos do Windows NT e os formatos que são suportados pelo mesmo. Serão descritos os tipos de sistemas de arquivo e como eles interagem com os demais componentes do sistema operacional, como o gerenciador de memória e o gerenciador de cache, por exemplo. Também será analisado o formato padrão do sistema de arquivos do NT, denominado NTFS. Tendo sido projetado do zero, não é um aperfeiçoamento de sistemas de arquivos antigos, e portanto não é sobrecarregado pela necessidade de ser totalmente compatível com os sistemas de arquivos do MS- DOS. 5.1 Conceitos Fundamentais do NTFS O Windows NT suporta vários sistemas de arquivos, entre eles a FAT-16 (File Allocation Table - 16), FAT-32 (File Allocation Table - 32), NTFS (New Technology File System), CDFS (CD-Rom File System), UDF (Universal Disk Format). A FAT- 16 é um sistema de arquivos que usa endereços de 16 bits, limitando as partições de disco em tamanhos de no máximo 2 GB. A FAT-32 é um sistema similar a FAT- 16 que usa endereços de 32 bits, podendo ter uma partição de até 2 TB (Terabytes). Por sua vez, o NTFS utiliza endereços de 64 bits, podendo assim suportar partições de até 16 EB (Exabytes), embora outros fatores a limitem a um tamanho menor. Tendo sido projetado do zero, o sistema de arquivos NTFS não é um aperfeiçoamento de sistemas de arquivos antigos, e portanto não é sobrecarregado pela necessidade de ser totalmente compatível com os sistemas de arquivos do MS-DOS. Os nomes de arquivos no NTFS são limitados a 255 caracteres; os caminhos desde a raiz são limitados a 32767 caracteres. Esses nomes estão em Unicode, o que permite que pessoas de países que não usam o alfabeto latino utilizem nomes
  • 69. de arquivos em seu idioma nativo. O NTFS diferencia totalmente letras maiúsculas de minúsculas, mas a API Win32 não, nem para nomes de arquivos nem para nomes de diretórios, fazendo com que programas que se restrinjam a usar o Win32, para compatibilizar com o Windows 98, percam esta vantagem. Os arquivos NTFS não são apenas seqüências lineares de bytes, como o que acontece com os arquivos no Unix e no FAT-32. Eles são formados por vários atributos, representados por fluxos (streams) de bytes. A maioria dos arquivos é formada por alguns fluxos curtos, como nome de arquivo, ID de objeto de 64 bits, e mais um fluxo longo, sem nome, com os dados. Entretanto, um arquivo pode ter dois ou mais fluxos de dados. Cada fluxo tem um nome formado pelo nome do arquivo, seguido de dois pontos e o nome do fluxo, como nomeDoArquivo:fluxo1. Cada fluxo tem seu próprio tamanho e pode ser impedido independentemente dos outros fluxos. Essa idéia de múltiplos fluxos foi importada do Apple Macintosh, no qual os arquivos têm dois fluxos, os dados e os recursos. Esse conceito foi incorporado ao NTFS para permitir que um servidor utilizando esse tipo de sistema de arquivo seja capaz de servir clientes Macintosh. Os fluxos de arquivos servem para outros propósitos além da compatibilidade com o Macintosh. Por exemplo, um programa de edição de fotos poderia usar o fluxo sem nome para a imagem principal e um fluxo com nome para a versão menor, apenas para visualização. Outro uso dos fluxos dá-se no processamento de textos. Esses programas freqüentemente fazem duas versões de um documento; uma temporária, para usar durante a edição e outra final para quando o usuário terminar de editar. Com a temporária em um fluxo com nome e a final em fluxos sem nome, ambas as versões compartilham automaticamente o mesmo nome de arquivo, a mesma informação de segurança, os mesmos indicadores de tempo, etc., sem trabalho adicional. Ponteiros de arquivos são usados para acompanhar onde um processo está em cada fluxo. Esses ponteiros têm 64 bits de largura para tratar o tamanho máximo de um fluxo, que é cerca de 18,4 Exabytes. O NTFS é um sistema hierárquico de arquivos, semelhante ao Unix. O separador entre os nomes dos componentes é '', característica herdada do MS-
  • 70. DOS. Há o conceito de diretório de trabalho atual e os nomes de caminhos podem ser tanto relativos quanto absolutos. Também são suportadas ligações rígidas e simbólicas; as primeiras são implementadas por entradas múltiplas de diretório, como no Unix; as últimas são implementadas usando pontos de reanálise. Além disso, compressão, criptografia e tolerância a falhas também são suportados. 5.2 Chamadas de API As principais funções da API Win32 para gerenciamento de arquivos estão listadas na Figura 17. Na verdade existem muito mais funções, mas essas são suficientes para que se compreenda a base do sistema. Função API Win 32 UNIX Descrição CreateFile open Cria um arquivo ou abre um arquivo existente; retorna um handle DeleteFile unlink Deleta um arquivo existente CloseHandle close Fecha um arquivo ReadFile read Lê dados de um arquivo WriteFile write Escreve dados em um arquivo SetFilePointer Iseek Seta o ponteiro de arquivo em um lugar específico no arquivo GetFileAttributes stat Devolve as propriedades do arquivo LockFile fcntl Tranca uma região do arquivo para providenciar exclusão mútua UnlockFile fcntl Destrava uma região do arquivo previamente travada Figura 17: Principais funções API Win32 para funções de arquivos Não é explicado os parâmetros de todas as funções por serem muitos, por exemplo, os parâmetros para criação de um arquivo(CreateFile) são os seguintes: • Um ponteiro para o nome do arquivo a ser criado ou aberto. • Flags indicando se o arquivo pode ser lido, escrito ou ambos. • Flags indicando se múltiplos processos podem abrir o arquivo ao mesmo tempo. • Um ponteiro para o descritor de segurança dizendo quem pode acessar o
  • 71. arquivo. • Flags indicando o que fazer se o arquivo existir ou não existir. • Flags lidando com atributos como: compressão, arquivamento, etc. • A manipulação de um arquivo cujos atributos devem ser copiados para um novo arquivo. 5.3 Estrutura do Sistema de Arquivos Cada volume (ou partição) do NTFS contém arquivos, diretórios, mapas de bits e outras estruturas de dados. Cada volume é organizado como uma seqüência linear de blocos (clusters), com o tamanho do bloco sendo determinado para cada volume, e indo de 512 bytes a 64 KB, dependendo do tamanho do volume. A maioria dos discos NTFS utiliza blocos de 4 KB como um tamanho que serve como ponto de equilíbrio entre blocos grandes e blocos pequenos, gerando tanto transferências eficientes quanto baixa fragmentação interna. Os blocos são referenciados por seus deslocamentos a partir do início do volume, usando-se números de 64 bits. A principal estrutura de dados de cada volume é a MFT (Master File Table), que é uma seqüência linear de registros com tamanho de 1 KB. Cada registro da MFT descreve somente um arquivo ou diretório. O registro contém atributos do arquivo, como seu nome, a lista de endereços de disco onde seus blocos estão localizados, indicadores de tempo, etc. Caso um arquivo seja muito grande, será necessário utilizar dois ou mais registros da MFT para abrigar a lista de todos os blocos. Nesse caso, o primeiro registro da MFT, chamado de registro-base, aponta para os outros registros da MFT. Um mapa de bits faz o acompanhamento de quais entradas da MFT estão livres. A MFT é, em si, um arquivo, e como tal pode ser colocada em qualquer lugar de um volume, eliminando assim o problema com os setores defeituosos na primeira trilha. Além disso, o arquivo pode crescer o quanto for preciso, até um