O desenvolvimento do OS/2 foi marcado principalmente pelas diferenças entre a Microsoft e a IBM, em termos de concepção do produto e forma de trabalhar. Esta tensão chegou ao limite após o lançamento da versão 3 do Windows, o que levou a uma separação entre as duas empresas. Esta separação deixou com a Microsoft o que a IBM chamava OS/2 3.0.
Este projeto, iniciado em 1988, era comandado por David Cutler (que tinha larga experiência no projeto de sistemas operacionais adquirida na DEC) sob o nome de NT - New Technoly. No começo de 1991, era anunciado o desenvolvimento do Windows NT e a expansão da interface de programação do Windows de 16 para 32 bits - o Win32. O Windows NT só veio a ser lançado na metade de 93 e teve um aceitação lenta (em parte por exigir a extravagância de 16 Megabytes de Ram, numa das raras ocasiões em que o preço da memória estava subindo ao invés de descer).
Uma das características do NT era a independência do processador utilizado, inicialmente o NT estava disponível não somente para o x86 mas também para processadores RISC como MIPS, Alpha e POWER. Isto influenciou algumas decisões na parte de gerenciamento de memória.
Enquanto que o Windows NT foi escrito praticamente a partir do zero, uma outra implementação do Win32 foi feita a partir do Windows 16 bits, criando o Windows 95.
Para tentar ajudar a migração aos 32 bits, existia uma "adaptação técnica" que implementava um subconjunto do Win32 sobre o Windows 16 bits - o chamado Win32s. Para os fins deste post vamos ignorar o Win32s.
O Mapa da Memória
No Win32 os recursos de gerenciamento de memória do processador são usados para dar a cada processo o seu próprio espaço de endereçamento com 4GB (é claro que a maior parte desde espaço normalmente não tem memória física associada).
No Windows 9x (95, 98 e Me), os 4GB são divididos da seguinte forma:
- os primeiros 4M (endereços 0x00000000 a 0x003FFFFF) são reservados para o sistema operacional (DOS e Windows 16 bits) e não devem ser acessados pelas aplicações (porém apenas os primeiros 4K estão protegidos)
- os bytes seguintes até a metade do espaço de endereçamento (0x00400000 a 0x7FFFFFFF) estão diponíveis para o processo. Esta memória é privada ao processo; outros processos não podem acesssá-la.
- em seguida existe 1G (de 0x80000000 a 0xBFFFFFFF) de endereçamento compartilhado por todos os processos. É nesta região que são colocados os arquivos mapeados em memória e DLLs compartilhadas.
- O último gigabyte (0xC0000000 a 0xFFFFFFFF) contém o sistema operacional e não deve ser acessado pelas aplicações (porém não está protegido e é compartilhado por todos os processos)
No Windows NT (e 2000 e XP), os 4GB são divididos um pouco diferente:
- os primeiros 64K (0x00000000 a 0x0000FFFF) são inacessíveis, para facilitar a detecção de ponteiros inválidos (tipicamente com NULL).
- de 0x00010000 a 0x7FFEFFFF (2G - 128K) fica a região privada do processo. Ela é usada para o código e dados do processo, os arquivos mapeados em memória e as DLLs.
- os 64K no final da primeira metade (0x7FFF0000 a 0x7FFFFFFF) são inacessíveis, para facilitar a detecção de ponteiros inválidos.
- os dois últimos gigabytes (0x80000000 a 0xFFFFFFFF) contém o sistema operacional e não podem ser acessados pela aplicação.
Usando o Espaço de Endereçamento
Quando um processo é criado, a maior parte do seu espaço de endereçamento é marcada como livre. Uma tentativa de acessar um destes endereços causará um erro.
O primeiro passo apra usar a memória é alocar uma região usando a função VirtualAlloc. A alocação não associa memória física à região, apenas a marca como em uso. O endereço inicial da região deve ser múltiplo da granularidade de alocação (64KB) e o tamanho deve ser múltiplo do tamanho da página do mecanismo de memória virtual (o que varia conforme o processador). A função VirtualFree libera uma região.
O passo seguinte é associar memória às páginas da região (commit). O Commit é controlado no nível de página, portanto não é necessário associar todas as páginas da região de uma só vez. O commit é feito também pela VirtualAlloc; VirtualFree pode ser usada para cancelar o commit liberando a memória. A memória associda não corresponde necessáriamente a RAM física, o Win32 utiliza os recursos de memória virtual do processador para controlar a movimentação das páginas entre a Ram e o disco (arquivo de paginação), simulando uma memória Ram maior que a real se necessário.
Arquivos Mapeados na Memória
O mesmo recurso que é usado para simular uma memória Ram maior que a real, através da movimentação de páginas entre a Ram e o arquivo de paginação pode ser usado com arquivos comuns.
O resultado são arquivos mapeados em memória: do ponto de vista do programador é como se todo o arquivo tivesse sido carregado para a memória, ficando acessível via ponteiros ao invés de funções de acesso a arquivo. Isto é usado no Win32 de três formas principais:
- para carregar e executar arquivos EXE e DLL. Desta forma a paginação do código é feita diretamente entre a Ram e o arquivo original, não envolvendo o arquivo de paginação.
- para simplificar o acesso a dados em um arquivo. O programa manipula o arquivo através de ponteiros sem precisar se preocupar em chamar as funções de acesso a arquivo ou gerenciar buffers de leitura e escrita.
- como forma de compartilhamento de dados e inter-comunicação entre processos rodando em uma máquina. Dois ou mais processos podem mapear em memória o mesmo arquivo, desta forma as alterações feitas por um são visíveis a todos.
Um comentário:
Muito bom seu site. Você poderia abordar em um artigo as diferenças e usos das várias funções de alocação de memória(new, malloc, HeapAlloc, VirtualAlloc, etc.).
Postar um comentário