Gerenciamento de memória em hardware
Recentemente estive realizando algumas pesquisas sobre implementações de virtualização, paravirtualização e suas implicações em hardware, especificamente em termos de necessidade e uso de recursos especiais do processador e gerenciamento de memória em baixo nível e sua ligação com o gerenciamento de memória no kernel através do slab allocator. Fica a dica aí para uma boa leitura e pesquisa.
Coincidentemente, o prof. Eng. Jardel Silveira (freqüentemente citado aqui no Hypercast!) pediu em um laboratório da cadeira de Sistemas de Computação aqui da Engenharia de Teleinformática, que fizéssemos um sistema de gerenciamento de memória e um pequeno resumo sobre a instrução lgdt (”Load Global Descriptor Table”). Nesse ponto quase houve uma convergência com o que citei no primeiro parágrafo, então, resolvi publicar o resumo aqui no site, para mais pessoas podem ler, aprender, corrigir, complementar, etc, enfim, a idéia do site.
Resumo sobre a instrução lgdt
Em um sistema operacional real, além de gerenciar os espaços alocados e livres, o SO é capaz ainda de indicar exceções geradas por acessos indevidos devido a permissões insuficientes para uma dada região, desreferenciamento de ponteiros ou apenas por uso incorreto de ponteiros, como na Falha de Segmentação.
Neste último caso, tomando o kernel Linux como exemplo, o processo que acessa uma área fora de seu segmento recebe imediatamente um sinal do sistema do tipo SIGSEV e a aplicação é encerrada. Para implementar este tipo de recurso, o sistema operacional precisa de suporte em hardware.
No modo real, os processadores acessam a memória física de maneira direta, como em um array linear de bytes. Dessa forma, todos os acessos são indistintos, cabendo ao programador criar divisões lógicas a nível de projeto para não sobrescrever informações importantes.
Já no modo protegido é possível utilizar um recurso de gerenciamento de memória com privilégios de acesso implementado no processador que dá uma chance ao kernel de responder pela exceção gerada.
Para contextualizar, o gerenciador de boot GRUB inicializa a GDT e indica a posição dela na memória física para o processador, que posteriormente utiliza-a também para as atividades do Linux, que será carregado posteriormente pelo GRUB.
É possível construir uma tabela própria e utilizá-la através de instruções em linguagem Assembly, utilizando diretivas para definir bytes com significados específicos que o processador espera para inicializar a GDT. Além desses bytes de configuração, também é necessário criar a primeira entrada da tabela como um segmento nulo, que é uma regra da Intel, para utilização interna.
Para informar ao processador a localização da nova tabela, utiliza-se a instrução lgdt, que precisa de um ponteiro para uma estrutura de 48 bits como parâmetro, onde 32 são para o endereço da tabela e os outros 16 para seu limite. É possível definir dinamicamente estes endereços em Assembly, criando a estrutura após a chama da instrução:
lgdt [gdt_desc]
gdt: ; Endereço para a tabela
gdt_null: ; Segmento nulo inicial
dd 0
dd 0
gdt_fim: ; Label utilizado para calcular dinamicamente o tamanho da tabela
gdt_desc: ; Descritor da GDT
dw gdt_end – gdt – 1 ; Limite / Tamanho
dd gdt ; Endereço da GDT
Espero que o resumo tenha sido útil, já que praticamente não existem textos em português que abordem o assunto. Particularmente não encontrei nenhum. E prometo um artigo sobre o assunto (ou aglomerado deles) citado no início deste post. Até lá!
Artigos Relacionados:
Sobre este artigo
You’re currently reading “Gerenciamento de memória em hardware,” an entry on Hypercast
- Published:
- 05.20.07 / 11pm
- Category:
- Desenvolvimento
8 Comments
Jump to comment form | comments rss [?] | trackback uri [?]