Universidade Estadual de Mato Grosso do Sul – UEMS Curso de Licenciatura em Computação Sistemas Operacionais Memória Virtual Prof. José Gonçalves Dias Neto [email protected] Introdução Memória virtual é uma técnica que combina-se as memórias principal e secundária para dar a impressão ao usuário de existir uma memória principal muito maior do que a real existente. Não vincula o endereço feito no programa aos endereços físicos da memória principal. Os programas deixam de estar limitados ao tamanho da memória principal, pois podem estar associados à memoria secundária. Visa diminuir a fragmentação da memória principal e aumentar seu compartilhamento. Primeira implementação da memória virtual foi feita em 1960 no sistema operacional Atlas. Algumas funções da Gerência de Memória Virtual são desenvolvidas em Hardware. (Desempenho) O SO deve implementar suporte a arquitetura do processador, principalmente seu endereçamento. (X86 X64) Espaço de Endereçamento Virtual Similar ao endereçamento de um vetor. Espaço de Endereçamento Virtual Um programa no ambiente de memória virtual não faz referência a endereços físicos, somente a endereços virtuais. O processador manipula somente endereços da memória principal. Assim, antes da execução, os endereços virtuais necessitam ser convertidos para endereços físicos. Espaço de endereçamento Virtual: é o espaço de endereços do processo ao qual este pode endereçar. Espaço de endereçamento Real: Espaço de endereços reais que o processador pode referenciar. Espaço de Endereçamento Virtual Espaço de Endereçamento Virtual Como o espaço de endereçamento Virtual não tem relação com o Espaço de Endereçamento Real (memória principal), isso permite que o processo esteja fora da memória principal. Quando um programa é executado, somente parte dele fica residente em memória principal, o restante fica em memória secundária até ser chamado. O programador não é afetado pelos endereços virtuais. Os compiladores e linkers fazem o trabalho desse gerenciamento. O SO cuida dos detalhes durante a execução. Espaço de Endereçamento Virtual Mapeamento Nos sistemas modernos, o mapeamento de memória virtual para memória real é feito por Hardware conjuntamente com o sistema operacional. MMU (Memory Management Unit) é o dispositivo responsável por efetuar o mapeamento. Quando um endereço de memória virtual é chamado, a MMU entra em ação convertendo esse endereço virtual em endereço real. Assim o processador pode acessar a memória principal. Mapeamento Cada processo possui sua própria tabela de mapeamento. Quando um processo começa a executar, sua tabela de mapeamento é carregada para fazer a conversão de endereços virtuais em reais. A troca de tabelas de mapeamento é realizada inserindo em um registrador o endereço inicial da tabela a ser acessada. As tabelas mapeiam blocos de dados cujo tamanho indica a quantidade de entradas nas tabelas de mapeamento. Quanto maior o bloco de dados, menos entradas nas tabelas, isso faz com que as tabelas ocupem menos espaço de memória. Mapeamento Mapeamento Mapeamento (segundo a wikipedia) IA-32/x86 A arquitetura x86 possui uma MMU muito complexa com vários modos de operação devido à compatibilidade que foi mantida ao longo dos anos com a evolução do x86. Na IA-32 a CPU primeiro divide a memoria em páginas de 4 KiB, o endereço da memória é mascarado para que não seja maior do que 32 bits. O resultado desse endereço pode ser pesquisado através de uma estrutura de árvore, que é dividido da seguinte forma 10 bits para a raiz, 10 bits para as folhas e os outros 12 bits são copiados diretamente para o resultado. x86-64 A x86-64 é uma extensão de 64 bits do x86, a diferença é que quando usado páginas de 4 KiB a tabela de páginas tem quatro níveis ao invés de três. O endereço virtual é dividido em 9 bits para cada um dos quatro níveis da árvore, 12 bits copiados diretamente para o resultado e os 16 restantes ficam inutilizados. Em páginas de 2 MiB são apenas 3 níveis da tabela de páginas. Algumas CPUs mais novas da arquitetura x86 também suportam páginas de 1 GiB com dois níveis de paginação. Mapeamento – bloco de dados Memória Virtual por Paginação Técnica onde os espaços de endereçamento de memória virtual e real são divididos em blocos de mesmo tamanho chamados páginas. Páginas no espaço virtual são chamadas páginas virtuais, já as páginas no espaço real são denominadas frames. Cada processo possui sua própria tabela de páginas. Cada página virtual possui uma entrada na tabela de página (ETP) com informações que permitem encontrar a página real correspondente. Execução: As página virtuais são transferidas da memória secundária e colocadas nos frames. Memória Virtual por Paginação Memória Virtual por Paginação O ETP possui um bit (valid bit) que indica se a página está ou não em memória. Sempre que houver referência a endereço virtual, verifica-se antes de tudo o bit de validade. Se a página não estiver em memória (page fault), o sistema transfere a página da memória secundária para a memória principal (page in). A quantidade de page fault em determinado intervalo de tempo, determina a taxa de paginação do processo. Essa taxa serve para identificar o overhead causado pela utilização de paginação, que é maior quando utiliza-se de E/S. Memória Virtual por Paginação Memória Virtual por Paginação Quando ocorre um page fault, o processo entra em estado de espera (bloqueado) até que a página seja recuperada da memória secundária. Ao terminar a busca, o processo retorna a fila de prontos e aguarda novo escalonamento. Através da paginação o podemos executar programas sem que todo seu código esteja disponível em memória principal. Política de Busca de Páginas A política de busca de página determina quando uma página deve ser carregada na memória principal. Paginação por Demanda (demand paging) as páginas são transferidas da memória secundária para a principal somente quando são referenciadas. Paginação Antecipada (antecipatory paging) o sistema carrega em memória principal, além da pagina referenciada, outras páginas que podem vir a ser utilizadas, ou não. (princípio da localidade). Pode ser empregada no momento da criação do processo e/ou na ocorrência de page faults Quais as vantagens e desvantagens de cada uma? Políticas de Alocação de Páginas A política de alocação de página termina quantos frames cada processo pode manter na memória principal. Política de alocação de tamanho fixo: Cada processo tem um número máximo de frames que podem ser utilizados durante a execução do processo. Esse valor máximo pode ser igual para todos os processos ou escolhido individualmente e fica dentro do contexto de software. Política de alocação de tamanho variável: A quantidade máxima de frames utilizados por cada processo pode variar em função da taxa de paginação e da ocupação de memória principal. ( exigem que o sistema monitore constantemente as taxas referentes aos processos ). Quais as vantagens e desvantagens de cada uma? Políticas de Substituição de Páginas Quando um processo atinge seu limite de alocação de frames e ainda assim necessita alocar mais, devemos escolher qual página residente em memória real substituir pela nova página. A página a ser substituída pode conter dados ou programas executáveis. No caso de programas a página não precisa ser salva, pois já existe uma cópia em memória virtual. No caso de dados que tenham sofrido modificação, esta página deve ser atualizada na página de memória virtual para que os dados não sejam perdidos. Este processo de salva o “contexto” da página em memória secundária é denominado page out. Políticas de Substituição de Páginas Políticas de Substituição de Páginas O Sistema identifica se a página foi modificada através de um bit (dirty bit ou modify bit). A política de substituição pode ser: Local: Somente as páginas do processo que gerou o page fault são candidatas ao sofrer page out. Global: Todas as páginas residentes em memória principal são candidatas a page out. (com exceção das páginas do kernel do SO) A política de alocação fixa permite unicamente substituição local, já a alocação variável permite que seja escolhida a politica de substituição local ou global. Princípio de Localidade O princípio de localidade indica que o processador tenderá a concentrar suas referências a um conjunto de páginas do processo durante um determinado período de tempo. Existem dois tipos de localidade: Localidade espacial: tendência de que após uma referencia a uma posição de memória sejam realizadas novas referencias a endereços próximos. Localidade temporal: tendência de que após a referência a uma posição de memória, esta mesma posição seja novamente referenciada em um curto intervalo de tempo. Algoritmos de Substituição de Páginas “O maior problema na gerência de memória virtual por paginação não é decidir quais páginas carregar para a memória principal, mas quais liberar. (Denning, 1968) Esses algoritmos têm o objetivo de selecionar os frames com menores chances de serem referenciados em um futuro próximo. Através do conceito de localidade, a maioria dos algoritmos tenta prever o comportamento futuro das aplicações em função do comportamento passado. O problema é que quanto mais sofisticado o algoritmo de substituição de páginas for, maior o overhead que ele gera. Algoritmos de Substituição de Páginas Dentre os algoritmos mais conhecidos temos: Ótimo; Aleatório; FIFO; LFU; LRU; NRU; FIFO com buffer; FIFO circular; Algoritmo de substituição de páginas Ótimo Ele é ótimo… ... mas praticamente impossível de ser implementado. O Sistema Operacional não tem como prever o comportamento futuro das aplicações. Seleciona uma página que não será mais referenciada no futuro ou aquela que levará mais tempo para ser novamente utilizada. Utilizado apenas como modelo comparativo. Algoritmo para substituição de página Aleatório Utiliza o critério de aleatoriedade; Qualquer página residente em memória está apta a ser substituída, até os frames muito utilizados; Consome pouco recurso computacional; Pouco utilizado; Baixa eficiência. Algoritmo para substituição de página FIFO (First In First Out) O algoritmo seleciona a página que está a mais tempo residente em memória para ser substituída; O algoritmo pode associar a cada página o seu timestamp para verificar quem é a página mais antiga; ou O algoritmo pode organizar as páginas em uma fila segundo ordem de criação; Nem sempre a página mais antiga é a menos utilizada; Páginas constantemente referenciadas, como as páginas de dados, o fator tempo da sua criação não indica quantidade de referencias; Raramente implementado sem outro mecanismo que minimize o problema de páginas constantemente referenciadas. Algoritmo para substituição de página FIFO (First In First Out) Algoritmo para substituição de páginas LFU (Least Frequently Used) Seleciona a página menos utilizada; O algoritmo deve manter um contador para cada página a fim de armazenar a quantidade de referências a esta; A página com menor quantidade de referências será a substituída; As páginas que estão a pouco tempo em memória podem ser escolhidas pois seus contadores estarão com valores baixos; É possível que uma página muito utilizada no passado não esteja mais sendo utilizada; Algoritmo pouco utilizado; Algoritmo para substituição de páginas LRU (Least Recently Used) Escolhe a página que está a mais tempo sem ser utilizada para sofrer substituição; Justificada pelo princípio da localidade; Uma página que não foi recentemente utilizada provavelmente não será utilizada em um futuro próximo; É necessário que cada página armazene o momento do seu último acesso e que atualize este valor a cada novo acesso; ou Dispor as páginas em uma fila (lista encadeada) segundo o seu último acesso; Sua eficiência é comparável ao algoritmo ótimo, porém tem alto custo computacional. Algoritmo para substituição de páginas NRU (Not Recently Used) Necessita de um bit adicional (Bit de Referência – BR) presente em cada entrada da tabela de páginas. Quando a página é carregada para a memória principal o bit é alterado para 1 (via hardware); Periodicamente o sistema verifica e altera o bit para 0; A medida que a página é utilizada o bit é alterado para 1 novamente; Para substituir uma página o algoritmo localiza uma página que esteja com o bit == 0 e a substitui; Algoritmo para substituição de páginas NRU (Not Recently Used) O NRU torna-se mais eficiente se o bit de modificação for utilizado em conjunto com o bit de referência. Assim as páginas podem ser classificadas em 4 categorias; O algoritmo então escolhe as páginas que não foram utilizadas recentemente e não foram modificadas; caso não existam, o algoritmo escolhe então as que não foram referenciadas recentemente, mas foram modificadas. No último caso, mesmo as páginas havendo necessidade de gravar na memória secundária a página modificada, há pouca chance desta página ser novamente referenciada. Algoritmo para substituição de páginas NRU (Not Recently Used) *Bits de referência e modificação Algoritmo para substituição de páginas FIFO Circular (clock) As páginas são alocadas em uma estrutura de lista circular; Existe um ponteiro que guarda a posição da página mais antiga da lista; Cada página possui também um bit BR; Para substituir uma página, o sistema verifica o bit BR da página mais antiga; Se BR==0 a página é substituída; Caso contrário BR=0 e o ponteiro é incrementado para a próxima posição; Caso BR == 1 para todas as páginas, a lista circular voltará a primeira posição, que agora já estará com BR == 0 e a página será substituída; Algoritmo implementado (com pequenas alterações) na maioria dos sistemas UNIX; Algoritmo para substituição de páginas FIFO Circular (clock) Tamanho da página Fator importante pra implementação de memória virtual por paginação; O tamanho da página tem impacto direto no tamanho da tabela de páginas e no tamanho que esta ocupa na memória principal; Páginas pequenas aumentam o tamanho da tabela de páginas e ocupam muito espaço na memória principal; Páginas grandes diminuem o tamanho da tabela de páginas porém facilitam a fragmentação interna. Quanto maior a página, maior a ocorrência de termos código pouco referenciado residente em memória principal, ocupando espaço desnecessariamente. Translation Lookaside Buffer (TLB) O mapeamento de memória virtual para memória real implica em pelo menos dois acessos à memória: 1 – tabela de páginas; 2 – acesso a página; Somente uma pequena parte da tabela de páginas é necessária por vez; TLB é uma memória adicional (hardware), próxima à MMU responsável por armazenar parte da tabela de páginas evitando o acesso constante a tabela de páginas completa; TLB mantém apenas as traduções de páginas mais recentemente utilizadas (tipo uma cache); A TLB está presente fisicamente nos processadores e pode apresentar diversos níveis como uma cache. Translation Lookaside Buffer (TLB) Translation Lookaside Buffer (TLB) Para traduzir um endereço virtual: 1 – sistema verifica na TLB; 2 – caso exista a tag, retorna o endereço físico mapeado na TLB (TLB hit); 3 – Caso não exista a tag, a tabela de mapeamento deve ser consultada (TLB miss); 4 – Se a página estiver na memória principal, a tradução do endereço virtual é colocado na TLB; 5 – caso contrário, ocorre um page fault, a página deve ser carregada em memória principal, a tabela de páginas deve ser atualizada e a informação é carregada na TLB; Translation Lookaside Buffer (TLB) Quando todas as entradas da TLB ficam cheias e uma nova entrada precisa se admitida, é necessário escolher qual entrada remover; As políticas mais empregadas são a aleatória e, mais raramente a NRU; Apesar de pequena (8 a 2048 endereços), a TLB proporciona um alto índice de TLB hit, aumentando o desempenho do sistema; Geralmente a TLB contém unicamente dados sobre o processo em execução, mas também pode ser utilizada para armazenar dados de vários processos, para isso deve existir um campo IDPROCESSO. Translation Lookaside Buffer (TLB) Proteção básica da memória Basicamente o sistema de paginação possui implícito um sistema simples mas funcional de proteção; Cada processo tem sua própria tabela de mapeamento; A tradução é sempre feita pelo sistema; Não é possível um processo acessar áreas de memória de outro processo sem que haja compartilhamento explícito; Proteção por bits do sistema Adicionalmente existem dois bits em cada página que funcionam também como mecanismo de proteção; Os bits especificam o tipo de acesso permitido; Compartilhamento de Memória É Bastante simples a implementação de compartilhamento de memória entre os diversos processos; Para compartilhar código entre diversos processos, basta que as entradas das tabelas de mapeamento dos processos apontem para os mesmos frames na memória principal. O compartilhamento de dados é similar, bastando garantir o sincronismo no acesso a região compartilhada. Memória Virtual por Segmentação Técnica onde o espaço de endereçamento virtual é dividido em blocos de tamanhos diferentes (segmentos). O programa é dividido logicamente em subrotinas e estruturas de dados, alocadas em segmentos na memória principal. Existe relação entre a lógica do programa e sua alocação na memória principal. Cada segmento pode representar um procedimento, função, vetor ou pilha. Memória virtual por Segmentação Memória virtual por Segmentação O tamanho do segmento pode ser alterado durante a execução do programa ( facilita estruturas dinâmicas). Os segmentos são mapeados através de Tabelas de Mapeamento de Segmentos (TMS). O endereço são compostos pelo numero do segmento virtual (NSV) e um deslocamento. O endereço real é obtido a partir do índice retornado pela TMS + Deslocamento. Memória virtual por Segmentação Memória virtual por Segmentação Vantagens na implementação de estruturas dinâmicas; Se aplicações não forem desenvolvidas em módulos, grandes segmentos estarão na memória desnecessariamente. Para alocar segmentos na memória principal, o SO mantém uma tabela com áreas livres e ocupadas. Apenas os segmentos referenciados são transferidos da memória secundária para a memória principal. Assim, o sistema para selecionar uma área livre suficiente para comportar o segmento, pode utilizar a mesma política da alocação particionada dinâmica (first, best ou worst fit). Enquanto na paginação ocorre o problema de fragmentação interna, na segmentação ocorre a fragmentação externa. ( não existe área grande suficiente para comportar o segmento ) Memória Virtual por Segmentação Memória Virtual por Segmentação com Paginação Técnica de gerência de memória na qual o espaço de endereçamento é divido em segmentos e por sua vez, cada segmento dividido em páginas. Oferece tanto vantagens da segmentação quando da paginação. Um endereço virtual é formado pelo numero do segmento virtual (NSV), um número da página virtual (NPV) e um deslocamento. O NSV indica uma página virtual, que por sua vez funciona como um índice na tabela de páginas. Na visão do programador, seu programa continua sendo mapeado na memória em segmentos. O sistema trata cada segmento como um conjunto de páginas de tamanho fixo. Assim cada segmento não precisa estar contíguo na memória principal, evitando a fragmentação externa. Trashing Problema encontrando tanto em sistemas que implementam paginação quanto segmentação. Trashing é a excessiva taxa de transferência de páginas/segmentos entre a memória principal e a memória secundária. Paginação: Excessivo número de page fault: Dimensionamento incorreto de limite máximo de páginas do processo (pequeno); Ausência do principio de localidade. Segmentação: Modularização extrema Exercícios 1 – Descreva todo o processo gerência de memória virtual por paginação que ocorre quando é solicitada uma página de memória virtual que pode ou não estar contida em memória principal. (leve em consideração a TLB e os possíveis escalonamentos que o processo pode sofrer). Exercício 01 - Solução 1 – O sistema possui a página de memória virtual necessária; 2 – O sistema consulta a TLB; 2 – caso exista a tag, retorna o endereço físico mapeado na TLB (TLB hit); 3 – Caso não exista a tag, a tabela de mapeamento deve ser consultada (TLB miss); 4 – Na tabela de mapeamento é verificado através do valid bit se a página está na memória principal 4.1 - nesse caso a tradução do endereço virtual é colocado na TLB e esta retorna o endereço físico. 5 – Caso contrário, ocorre um page fault 5.1 - a página deve ser carregada em memória principal, 5.1.1 – O processo solicita acesso de E/S, enquanto o sistema operacional efetua a busca da informação o processo sofre preempção e é posto na fila de bloqueados até o retorno dos dados solicitados. 5.1.2 – Após isso o processo volta à fila de prontos e aguarda até sofrer escalonamento para o estado de execução. 5.1.3 – os dados são mapeados para a memória principal, caso haja espaço disponível; 5.1.4 – Caso contrário o algorítimo de substituição de páginas deve escolher qual página substituir, fazendo com que a antiga vá para a memória secundária e a nova página ocupe seu espaço. 5.1.5 A tabela de páginas deve ser atualizada e a informação é carregada na TLB;