Gerência de Memória A multiprogramação permite que a CPU possa ser compartilhada por um conjunto de processos, em benefício do desempenho global do computador. Entretanto, para obter esse ganho, é necessário compartilhar a memória entre múltiplos processos. Neste capítulo serão discutidas as várias formas de gerenciar a memória. 6.1 Introdução A memória corresponde a um longo array de palavras ou bytes, cada um com o seu endereço. A CPU e os controladores dos dispositivos periféricos podem ler e escrever em posições da memória: CPU Memória Sistema de I/O Mecanismos para gerência de memória: Máquina pura Monitor residente Swapping Partições múltiplas Paginação Segmentação Segmentação com paginação 6.2 Máquina pura Este é o esquema mais simples que se pode imaginar, ou seja, não existe gerência de memória. Neste caso, o usuário lida diretamente com o hardware e possui total controle sobre toda a memória. Este mecanismo é o que fornece maior flexibilidade para o usuário, máxima simplicidade e custo mínimo, uma vez que não exige nenhum software nem hardware especiais. Por outro lado, o esquema apresenta uma série de problemas, que podem ser resumidos pela ausência de serviços: o sistema operacional não controla interrupções, não há monitor residente para processar chamadas de sistema ou erros, etc. Considerando que o usuário pode alterar o código do próprio sistema operacional, nos endereços dos tratadores de interrupção, etc., esta opção é viável apenas em sistemas dedicados (por exemplo, sistemas embarcados), onde o computador controla um equipamento específico, como um eletrodoméstico, uma máquina de controle numérico, um míssil, um satélite, uma bomba de gasolina, etc. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 1 6.3 Monitor Residente Neste esquema a memória é dividida em duas partes: área do usuário e área do sistema operacional. A área do sistema operacional fica geralmente no início da memória porque a tabela de interrupção usualmente ocupa os primeiros endereços da memória. 0 MONITOR Registrador limite USUÁRIO 64K Hardware de proteção Se o sistema operacional está na memória baixa e a área de usuário na memória alta, é necessário proteger o código e os dados do SO contra o acesso acidental ou malicioso por parte de um programa de usuário. Esta proteção deve ser fornecida pelo hardware e pode ser implementada através de um registrador de proteção, denominado limite. O mecanismo de acesso à memória só “aceita” endereços maiores ou iguais ao valor desse registrador. O valor do registrador é zerado quando a execução vai para o SO e somente o SO pode alterar o valor desse registrador. Relocação Um problema a ser considerado é a carga de programas. Embora o espaço de endereçamento do computador inicie em 0, o primeiro endereço do programa usuário (endereço inicial de carga) é aquele contido no registrador limite. É preciso de alguma forma acertar os endereços referidos no programa do usuário (isto é, no código de máquina correspondente ao programa de usuário). Se o endereço inicial de carga é conhecido previamente, os endereços absolutos (endereços físicos) podem ser gerados na compilação (mais exatamente, na ligação), durante a geração do código de máquina. Neste caso, uma alteração no endereço de carga implica em recompilar o programa. Quando o endereço inicial de carga não é conhecido previamente, o código de máquina (arquivo executável) é gerado supondo que o programa vai ser carregado e executado a partir do endereço zero. Neste caso, se um programa tem tamanho K, os seus endereços (isto é, os endereços referidos nas instruções de máquina desse programa) certamente são valores entre zero e K-1. Estes endereços entre 0 e K-1 constituem o que AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 2 se denomina espaço de endereçamento lógico do programa. Quando o programa é carregado na memória é necessário acertar os seus endereços lógicos para que eles passem a indicar os endereços físicos corretos. O acerto é muito simples, basta somar o endereço inicial de carga à cada endereço lógico referido no programa. Os endereços lógicos são também referidos como endereços relativos e o processo de acerto dos mesmos é conhecido como relocação. A relocação pode ser feita de forma estática ou de forma dinâmica. Na relocação estática, os endereços relativos são transformados em absolutos no momento da carga do programa. Para isso, o arquivo executável deve conter também a indicação dos locais do código que referem endereços. Essa indicação é conhecida como informação de relocação. É tarefa do carregador (loader) fazer o acerto dos endereços e isso é feito durante a carga do programa. No caso da relocação dinâmica, os endereços do programa permanecem lógicos o tempo inteiro (isto é, as instruções de máquina não são alteradas para referir endereços físicos). É o mecanismo de acesso à memória que vai fazer a correção (relocação) durante a execução do programa, conforme é explicado a seguir. Para fazer a relocação, é necessário que o endereço inicial de carga fique armazenado em um registrador da UCP. No esquema de proteção descrito anteriormente, esse endereço ficava no registrador limite. Agora, em um computador que faça relocação dinâmica, esse valor fica em um registrador referido normalmente como registrador base ou registrador de relocação. Quando a UCP requer um acesso ao endereço (lógico) E, o mecanismo de acesso a memória entende como sendo um acesso ao endereço RB+E, onde RB é o valor contido no registrador base. A figura abaixo mostra como os endereços relativos são transformados em endereços absolutos durante a execução: registrador base 1400 end. lógico CPU 346 + end. físico MEM 1746 O uso de relocação dinâmica permite movimentar um programa na memória com facilidade, basta alterar o valor do registrador base. Isto permite mudar o tamanho do sistema operacional durante a execução de um programa (como por exemplo para incluir mais buffers ou então um controlador de dispositivo pouco utilizado). Outra forma comum de permitir o aumento do tamanho do SO é carregar o programa do usuário sempre no fim da memória. Isto permite que o sistema operacional cresça até o endereço contido no registrador base e não é necessário movimentar o programa de usuário. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 3 Com o uso de registrador base, passam a haver dois tipos de endereços: endereços lógicos, entre 0...MAX (endereços vistos pelo programa); endereços físicos, entre RB+0...RB+MAX (vistos pelo sistema operacional). Todos os endereços manipulados pelo SO são físicos, pois ele acessa a memória de diversos processos. Cada endereço passado entre um programa de usuário e o SO precisa ser apropriadamente convertido. Este conceito de espaço de endereçamento lógico mapeado para um espaço de endereçamento físico é central quando se trata de esquemas de gerência de memória. 6.4 Swapping O esquema de memória descrito acima é pouco utilizado, uma vez que é monousuário. Entretanto, ele pode ser utilizado para multiprogramação através da adição de swapping: Registrador Base monitor espaço do usuário swap in usuário 1 swap out usuário 2 DISCO O programa que perde a CPU é copiado para o disco, enquanto o programa que ganha é transferido do disco para a memória principal. Este método foi utilizado nos primeiros sistema timesharing. Os programas são mantidos em um disco, que deve ser rápido e grande o bastante para conter diversas imagens de processos (códigos executáveis). 6.5 Partições Múltiplas Na multiprogramação, diversos programas devem estar presentes na memória ao mesmo tempo, para que a CPU possa ser rapidamente alternada entre eles. A solução natural para esta necessidade é dividir a memória em regiões ou partições. Cada partição pode conter um programa a ser executado, limitando então o grau de multiprogramação pelo número de partições. A memória pode ser dividida em partições de duas maneiras distintas: partições fixas, onde as regiões são estáticas; partições variáveis, onde as regiões são dinâmicas AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 4 Hardware de proteção Passa a ser necessário proteger não apenas o código e dados do sistema operacional, mas também código e dados de outros usuários. É possível implementar proteção para partições múltiplas utilizando duas técnicas diferentes: através de registradores de limite inferior e superior ou através de registrador base e registrador limite. A primeira técnica é usada quando o computador trabalha com relocação estática. Nesse caso, sendo LI e LS os endereços contidos nos registradores limite inferior e limite superior, respectivamente, um endereço E é consideralo válido quando LI≤E<LS. A segunda técnica é usada quando o computador trabalha com relocação dinâmica. Nesse caso o registrador base (RB) é usado para relocação (todo endereço E é mapeado em RB+E) e o registrador limite (RL) é usado para proteção (um endereço E é consideralo válido quando E<RL). Observe que o conteúdo do RB é o endereço inicial de carga (início da partição) e o conteúdo do RL é o tamanho do programa. Partições fixas A memória é dividida em partições que não são alteradas durante a execução do sistema. Por exemplo, uma memória de 256K palavras poderia ser dividida da seguinte forma: Monitor residente: 64K palavras; Espaço para processos pequenos: 16K palavras; Espaço para processos médios: 48K palavras; Espaço para processos grandes: 128K palavras. Quando um programa vai ser executado, é necessário levar em conta as suas necessidades de memória, para escolher a partição onde ele vai ser colocado. Tal pode ser especificado pelo usuário ou então automaticamente determinado pelo sistema operacional. A partir desse momento há duas possibilidades básicas: (a) montar uma fila individual para cada tamanho de partição ou (b) montar uma fila única que englobe todas as requisições. Existem dois tipos de perdas de memória por fragmentação. Elas são chamadas de fragmentação interna e fragmentação externa. Um processo que necessita m palavras de memória pode executar em uma região de tamanho n, onde n >= m. A diferença n - m representa a fragmentação interna, isto é, a memória desperdiçada dentro da região. Ocorre fragmentação externa quando uma região está disponível para uso, mas é pequena demais para os processos serem executados. Por exemplo, 3 programas estão esperando para serem executados. Eles possuem as seguintes necessidades de memória: 60K, 80K e 90K. Existem 3 partições livres, cada uma com 40K. Apesar da área livre total ser de 120K, a mesma não pode ser aproveitada para processá-los. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 5 Considere agora uma situação onde existem 4 partições livres, com respectivamente 100K, 40K, 40K e 40K. Neste momento, 4 processos desejam executar, necessitando das seguintes quantidades de memória: 70K, 30K, 60K e 60K. Após fornecer a partição de 100K ao processo que precisa de 70K, e fornecer uma partição de 40K ao processo que precisa de 30K, a perda de memória por fragmentação interna soma 40K (30K + 10K). A perda por fragmentação externa é de 80K (40K + 40K). A perda total nesta situação é de 55% da memória. Partições Variáveis O maior problema das partições fixas é determinar a melhor divisão da memória, mesmo porque a melhor divisão varia ao longo do tempo. A solução é permitir que o tamanho das partições varie ao longo do tempo (mecanismo de partições variáveis). O esquema é bastante simples: o sistema operacional mantém informações sobre quais partes da memória estão disponíveis e quais estão ocupadas. Inicialmente, toda a memória está disponível (um único “buraco”). Quando um processo chega para ser executado, a lista de buracos é pesquisada e o processo é colocado em uma região livre suficientemente grande. Do buraco que representa a região livre é removida a área a ser utilizada pelo processo, sendo o restante mantido no buraco livre. Exemplificando, considere os seguintes processos a serem executados: JOB 1 2 3 4 5 0 Memória 60K 100K 30K 70K 50K 0 monitor 0 monitor 40K 0 monitor 40K Job 1 Tempo 10 5 20 8 15 40K Job 1 0 monitor 40K 40K Job 5 Job 1 aloca job 5 job 1 termina 100K monitor 100K 100K 100K Job 4 90K 100K Job 4 Job 4 aloca job 4 Job 2 200K 170K job 2 termina 200K Job 3 170K 200K Job 3 170K 200K Job 3 200K Job 3 Job 3 230K 230K 230K 230K 230K 256K 256K 256K 256K 256K AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 6 Características das partições variáveis sempre existe um conjunto de áreas livres espalhadas pela memória; este conjunto é pesquisado, sendo necessário uma área maior ou igual à necessidade do programa; se a área é maior, a parte restante continua livre; quando o processo termina, ele libera a área. Se ela for adjacente a uma outra área livre, ambas são reunidas em uma única área livre. Esta liberação pode fazer com que programas esperando possam ser executados; para evitar o trabalho com pequenos espaços, a unidade de alocação não é necessariamente o byte, podendo ser blocos de tamanho 2 Kbytes, por exemplo. Isto introduz uma pequena fragmentação interna. Algoritmos de alocação para partições variáveis Existem diversos algoritmos para a escolha de uma área livre. Este problema é conhecido genericamente como alocação dinâmica de memória. Abaixo estão descritos os 3 principais algoritmos: first-fit: aloca o primeiro espaço livre que seja suficientemente grande; best-fit: aloca o menor espaço livre que seja suficientemente grande. Produz a menor sobra de espaço livre; worst-fit: aloca o maior espaço livre. Produz a maior sobra de espaço livre. Este espaço maior que fica poderá ser mais útil do que o pequeno espaço livre deixado pelo best-fit. Um bom algoritmo, utilizado na prática é conhecido como circular-fit. Ele funciona como o first-fit, mas inicia a procura na lacuna seguinte à última sobra. Compactação e swapping A utilização da memória é melhor com partições variáveis do que com partições fixas, mas a fragmentação externa é sempre um problema. Uma solução para isto é a compactação. Os programas são deslocados na memória de forma que todo o espaço livre de memória fique reunido em uma só área, no início ou no fim da memória. Se o sistema trabalha com relocação estática, a compactação fica inviável (pois é necessário corrigir os endereços utilizados nos programas). Se o sistema utiliza relocação dinâmica (registradores base e limite) a compactação fica simples, mas mesmo assim, o custo da compactação em termos de tempo de CPU deve ser considerado. É possível acrescentar swapping ao esquema de partições variáveis. Enquanto o processo está suspenso, sua memória é aproveitada por outros processos. Se o hardware dispõe de registradores de base e limite, o programa pode voltar em qualquer ponto da memória. Podemos assim obter compactação através do swapping. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 7 6.6 Paginação O uso de partições variáveis apresenta o problema da fragmentação externa, que se manifesta quando a memória não está contígua, mas fragmentada em diversos blocos espalhados. Considerando que o espaço de endereçamento de um processo precisa ser contíguo, esta memória livre espalhada não pode ser utilizada. A compactação permite o melhor aproveitamento da memória, mas possui um custo de CPU associado e nem sempre é possível. O problema é resolvido pelo esquema de paginação, que permite que o espaço fisico ocupado por um processo seja não contíguo. Hardware Cada endereço gerado pela CPU é quebrado em duas partes: um número de página p e um deslocamento d. A memória lógica de um processo está dividida em blocos denominados páginas lógicas. Da mesma forma, a memória física do computador está dividida em blocos denominados páginas físicas ou frames. Páginas físicas e lógicas possuem o mesmo tamanho, definido a nível de hardware. deslocamento endereço lógico CPU p d endereço físico f número da página d número do frame f Memória física tabela de páginas Para fixar idéias, vamos supor que o computador utilize endereços de 16 bits e que a memória seja organizada (acessada) em palavras. Isto resulta num espaço de endereçamento lógico de tamanho 216 (= 64K) words para os processos. Neste caso, as divisões poderiam ser, por exemplo, 5 bits para p e11 bits para d (isto resulta num espaço lógico com 32 páginas de tamanho 2Kwords), ou 6 bits para p e10 bits para d (64 páginas de tamanho 1Kwords) ou ainda 7 bits para p e9 bits para d (128 páginas de tamanho 512 words). A figura abaixo ilustra a divisão que usa 6 bits para p e 10 bits para d: página 15 deslocamento 10 9 0 Essa divisão é decidida em tempo de projeto do computador. Neste exemplo (endereços de 16 bits), qualquer que seja a divisão adotada pelo hardware, tem-se que o espaço de endereçamento lógico dos processos é sempre um espaço contínuo de 64K AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 8 words. É o hardware que vai considerar esse espaço lógico dividido em páginas. Na verdade, a UCP vai trabalhar sempre com endereços lógicos (entre zero e 216-1) e vai ser o mecanismo de acesso à memória (MMU – Memory Management Unit) quem vai converter os endereços lógicos em endereços físicos. Por isso, costuma-se dizer que a paginação é transparente para o software. De fato, os compiladores e ligadores geram código (arquivos executáveis) considerando que o programa vai ocupar uma área contígua da memória, iniciando no endereço zero (para eles não existe paginação). Uma observação importante é que o tamanho da memória física é determinado pelo número de bits utilizados para representar os endereços físicos. Por exemplo, se a MMU utiliza 20 bits para representar endereços físicos, então a memória física fica com tamanho 220 (= 1Mega) words, com endereços que vão de zero à 220-1. Se esse sistema utiliza páginas de tamanho 1 Kwords, essa memória física será vista pelo hardware como tendo 1024 páginas. Por último, deve ser observado que a memória física pode ser maior, igual ou menor que a memória lógica. Isso depende do número de bits usados nos endereços lógicos e físicos. Outra observação é que a UCP trabalha sempre com endereços lógicos, os quais são mapeados para endereços físicos pela MMU. Portanto tem-se relocação em tempo de execução. Quando um programa deve ser executado, suas páginas lógicas são carregadas em quaisquer páginas físicas disponíveis, e uma tabela de páginas é criada para traduzir números de páginas lógicas em números de páginas físicas, conforme ilustrado abaixo: 0 página 0 página 1 página 2 página 3 0 1 1 4 2 3 3 6 tabela de páginas memória lógica de um processo 1 página 0 2 3 4 página 2 página 1 5 6 página 3 memória física da máquina Os valores p e d correspondentes a um endereço lógico U são obtidos da seguinte forma: p = U div P d = U mod P onde P é o tamanho da página. Se o tamanho da página é potência de 2 (e isto sempre ocorre), a operação é simplificada, pois o quociente e o resto são obtidos diretamente, através de uma simples operação de shift. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 9 Implementação da tabela de páginas Há 3 formas básicas de implementar a tabela de páginas: conjunto de registradores dedicados, memória principal e memória associativa. A tabela de página pode ser contruída a partir de um conjunto de registradores dedicados, na UCP. Na mudança do processo em execução, estes registradores são carregados com os valores correspondentes ao processo que recebe a UCP. O acesso aos registradores da tabela é feito através de instruções privilegiadas. Como estes registradores são caros, sua utilização não é viável para tabelas grandes. A tabela de páginas pode ser mantida na própria memória principal. O registro descritor de cada processo contém o endereço da sua respectiva tabela de páginas. O hardware inclui um registrador que aponta para a tabela de páginas em uso (PTBR - Page Table Base Register). Este registrador é acessado através de instruções privilegiadas. O problema com esta solução é o tempo de acesso. É necessário realizar dois acessos à memória, um para fazer o mapeamento (acesso à tabela) e outro para acessar os dados. Uma forma alternativa é utilizar memória associativa. A memória associativa é uma memória de alta velocidade onde cada posição contém 2 campos: uma chave e um valor. Quando a memória associativa é consultada, ela recebe uma chave, a qual é comparada com o campo chave de todas as posições, simultaneamente. Se alguma chave igual é encontrada, o campo valor correspondente é devolvido. A pesquisa é rápida, mas o hardware é bastante caro. A idéia é colocar os números de página no campo chave e os números dos respectivos frames no campo valor. A memória associativa contém apenas algumas das entradas da tabela. Quando um endereço lógico é gerado pela CPU, seu número de página é fornecido como chave para a memória associativa. Se ele está lá, o número do frame é obtido imediatamente, com toda a operação consumindo apenas, por exemplo, 10% a mais que um acesso normal à memória. Se aquela entrada na tabela não está na memória associativa, então um acesso à memória principal deve ser feito. Além disto, pode-se adicionar esta entrada à memória associativa, removendo alguma que esteja lá agora. Ela poderá então ser encontrada rapidamente no próximo acesso. Localidade da execução A probabilidade de uma pesquisa à memória associativa resultar em sucesso é grande graças a propriedade conhecida como localidade de execução, que é apresentada pela maioria dos programas. Todo programa avança acessando o seu espaço lógico (buscando de lá instruções e dados). Durante esse avanço, a cada intervalo de tempo, utiliza apenas pequenas regiões do seu espaço de endereçamento (muitas regiões sequer são acessadas durante toda a execução). É essa propriedade da execução se manter sobre pequenas regiões do espaço de endereçamento que é denominada localidade de execução. Tempo de acesso efetivo O número de vezes em que o número da página é encontrado na memória associativa depende do tamanho desta. Uma memória associativa de 8 ou 16 posições permite uma AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 10 taxa de acerto de 80% ou 90%. Este número é chamado de hit ratio (taxa de acerto). Por exemplo, imagine que em determinado computador, a pesquisa na memória associativa demore 50 ns e que um acesso normal à memória demore 750 ns. Neste caso, um acesso com sucesso na pesquisa demora 800 ns, enquanto um acesso com fracasso na pesquisa demorará 1550 ns. Se uma taxa de acerto de 80% for obtida, o tempo de acesso efetivo à memória será: 0.8 * 800 ns + 0.2 * 1550 ns = 950 ns. Páginas compartilhadas Através da paginação é possível compartilhar código entre os processos, desde que ele seja reentrante (não modifique a si próprio). O sistema operacional deve garantir (via hardware) que nenhum processo altere (escreva) estas páginas. Outra restrição é que as páginas com código devem ter os mesmos números para todos os processos. Por ex., se a página compartilhada pelos processos P1 e P2 é a página 5 do processo P1, ela deve ser também a página 5 do processo P2. Em outras palavras, as páginas compartilhadas devem ocupar as mesmas posições relativas dentro dos espaços lógicos de cada processo. Proteção Cada entrada na tabela de páginas possui alguns bits adicionais para implementar proteção. Como todos os acessos passam pela tabela, o hardware pode verificar a legitimidade do acesso apenas verificando estes bits. Por exemplo: um bit para indicar que a página é de apenas leitura; um bit para indicar página válida/inválida. Fragmentação Com paginação existe apenas fragmentação interna na última página do programa. Como raramente o tamanho de um programa é um múltiplo do tamanho de uma página, a última página dificilmente será preenchida completamente. Pode-se dizer que, em média, haverá um desperdício de ½ página por processo. Outra perda de memória associada à paginação se refere à representação da tabela de páginas. Para um dado tamanho de memória lógica, quanto menor o tamanho da página, maior será o tamanho da tabela de páginas. 6.7 Segmentação A visão da memória pelo usuário O usuário (programador) não pensa no seu programa organizado como um array linear de palavras, mas sim como uma coleção de segmentos de tamanho variável, sem que exista necessariamente uma ordem entre os segmentos. A segmentação é um forma de gerência de memória que suporta esta visão do usuário. Com segmentação, o espaço de endereçamento lógico é uma coleção de segmentos. Cada segmento tem um nome e um tamanho. Cada posição da memória AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 11 lógica é especificada por um segmento e um deslocamento dentro deste. Para facilitar a implementação, os segmentos não recebem nomes, mas sim números. Os compiladores e montadores automaticamente criam segmentos para refletir a organização do programa. No momento da carga do programa, cada um recebe um número de segmento específico. subrotina pilha função Tabela de Símbolos Programa Principal Espaço de Endereçamento Lógico Hardware É necessário mapear os endereços lógicos, do tipo segmento/deslocamento, para endereços físicos, que continuam sendo (e sempre serão) índices de um array unidimensional. Isto é feito através de uma tabela de segmentos. 1400 Segmento 0 2400 subrotina segmento 0 função segmento 1 Programa Principal segmento 2 pilha segmento 3 Tabela de Símbolos segmento 4 Espaço de Endereçamento Lógico 0 1 2 3 4 base 1400 6300 4300 3200 4700 limite 1000 400 400 1100 1000 Tabela de segmentos 3200 Segmento 3 Segmento 2 4300 4700 Segmento 4 5700 Segmento 1 6300 6700 Memória Física AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 12 Implementação da tabela de segmentos Da mesma forma que a tabela de páginas, a tabela de segmentos pode ser colocada em registradores rápidos, na memória principal ou numa tabela em memória associativa. Se a tabela de segmentos é mantida em registradores, todo o mapeamento é feito rapidamente. Proteção e compartilhamento Como segmentos representam partes bem definidas do programa, eles possuem características bem definidas. Segmentos de código podem ser definidos como de apenas leitura, e o hardware de mapeamento irá sempre verificar se um segmento de apenas leitura não está sendo alterado. Isto é possível através da associação de bits de proteção a cada entrada da tabela de segmentos, como foi feito na paginação. Segmentos podem ser compartilhados entre usuários, mas, para isso, persiste a restrição dos segmentos de código terem que ocupar as mesmas posições relativas dentro dos espaços lógicos dos processos compartilhantes. Outra solução seria descrever os segmentos compartilhados através de uma tabela de segmentos separada – a tabela de segmentos compartilhados. Se considerarmos um sistema com dezenas de programas executando, e a maioria deles compartilhando as mesmas bibliotecas, poderemos perceber a importância do compartilhamento de código. Também é necessário salientar a importância dos bits de proteção no momento de restringir o acesso dos processos aos segmentos compartilhados. Obviamente, um segmento contendo dados de um programa é do tipo "para leitura e escrita" e não pode ser compartilhado. Fragmentação Segmentos possuem um tamanho variável. Quando um programa deve ser executado, o espaço alocado para cada segmento deve ser contínuo. A solução é utilizar um dos métodos first-fit, best-fit, etc., para alocar cada segmento. Repete-se pois o problema da fragmentação externa: a sucessiva alocação e liberação de segmentos com diferentes tamanhos faz surgir pequenos espaços de memória livre, onde não cabe um segmento (lacunas inúteis). Quanto menores forem os segmentos dos programas, menor será o problema da fragmentação externa. 6.8 Segmentação versus paginação Qual dos esquemas é o melhor? Talvez não exista resposta definitiva para esta questão, pois se trata de um assunto polêmico que vem sendo discutido há muito tempo. Contudo, pode-se apresentar as vantagens (e desvantagens) de cada um. A seguir são apresentadas as principais diferenças entre segmentação e paginação. Fragmentação Com a segmentação existe fragmentação externa, com paginação existe fragmentação interna (em média, perda de ½ página por processo). Aqui a paginação parece ser vantajosa (desde que os tamanhos das páginas não sejam muito grandes). AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 13 Administração da memória A administração da memória física é muito mais simples na paginação, já que qualquer página física pode ser usada para carregar qualquer página lógica. Praticamente, basta o SO manter uma lista com os números das páginas físicas disponíveis, para controlar a alocação de memória. Proteção e compartilhamento Aqui a segmentação é bem melhor, pois os segmentos constituem as unidades lógicas do programa (isto é, cada segmento tem um determinado significado ou função). Cada segmento poderá ser compartilhado e ter asssociada a si uma determinada proteção. Com paginação as partes de um programa estão aglutinadas, formando um bloco único (em uma mesma página podem estar funções, subrotinas e dados, por exemplo). Espaçode endereçamento Com paginação o espaço de endereçamento lógico é um espaço único (unidimensional), contínuo, com endereços que vão desde zero até MAX (onde MAX é o tamanho do programa menos 1). Com segmentação o espaço lógico é formado por um conjunto de segmentos, cada segmento u com endereços que vão de zero até MAXu (onde MAXu é o tamanho de u menos 1). Na paginação o espaço lógico é contínuo, pois se pegarmos o último endereço dentro da página p e somarmos 1, teremos o primeiro endereço da página p+1. Por exemplo, considerando que (p)2 seja a representação binária de p, tem-se que o último endereço da página p é “(p)2111...1”. Somando-se 1 tem-se “(p+1)2000...0”, que é o primeiro endereço da página p+1. Isto não ocorre na segmentação, onde o espaço lógico é descontínuo. Aqui não se pode dizer que haja vantagem de um esquema sobre o outro. As vantagens e desvantagens estão nas conseqüências destas organizações. 6.9 Sistemas Combinados Existem sistemas onde a paginação e a segmentação são combinadas em um único mecanismo. É possível utilizar tanto “paginação segmentada” como “segmentação paginada”, sendo mais comum a segunda forma, que será discutida a seguir. Segmentação paginada Com a segmentação, tem-se o problema da fragmentação externa. Uma forma de eliminar essa fragmentação é dividir os segmentos em páginas. Na solução mostrada na figura 1, a tabela de segmentos não contém o endereço do segmento na memória, mas sim o endereço da tabela de páginas do segmento. O problema da fragmentação externa é eliminado completamente. Entretanto, o sistema passa a ter fragmentação interna. Em média, teremos meia página de fragmentação interna por segmento de processo. Se as tabelas de segmentos e de páginas são mantidas na memória principal, então para cada acesso à memória vão ser necessários dois acessos adicionais. Para acessar o endereço (s,p,d) tem-se que acessar inicialmente a entrada s da tabela de segmentos para AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 14 lá pegar o endereço da tabela de páginas correspondente, após isso, acessar a entrada p da tabela de páginas para pegar o endereço da página física f e, finalmente, acessar o que interessa, que está na posição f+d. São dois acessos extras, em relação ao caso de uma máquina simples que não tenha segmentação nem paginação. A solução para essa degradação no desempenho é o uso de uma memória associativa para conter os endereços físicos das páginas lógicas recentemente acessadas. Agora, cada entrada da tabela associativa terá como chave um par (s,p) e como valor o número da página física f correspondente a esse par. Uma tabela pequena (p.ex., 16 entradas) já consegue obter um bom hit ratio (p.ex., 80%). s d Tabela de Segmentos S >= N Base da Tabela de Páginas Tamanho do Segmento d erro p d’ MEM + f f d’ Figura 1 – Segmentação paginada 6.10 Paginação por demanda No que foi considerado até aqui, supõe-se que os programas sejam carregados por inteiro na memória principal do computador (como conseqüência, o espaço de endereçamento lógico de um processo deve ser menor que a memória física). Entretanto, um programa não precisa estar todo na memória para executar. Muitas partes de um programa sequer são necessárias em toda execução. Por exemplo, considere o programa editor de texto. Normalmente, os editores de texto oferecem funções que raramente são utilizadas pela maioria dos usuários. As rotinas que implementam tais funções somente precisam estar na memória naqueles raros instantes em que realmente são necessárias. Nesta seção será descrita a técnica de gerência de memória conhecida como paginação por demanda, que permite executar programas não completamente carregados na memória física. Além de permitir o compartilhamento da memória por um número maior de processos, a técnica permite executar programas maiores do que a memória fisica do computador. Memória virtual e memória lógica A expressão memória virtual pode ser entendida de duas maneiras. Para alguns autores, memória virtual é sinônimo de memória lógica. Isto é, a memória virtual de um processo AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 15 é o conjunto de endereços que são referidos no código de máquina desse processo. Para outros autores, somente existe memória virtual quando o computador permite a execução de programas que não estão completamente carregados na memória física. Tanto paginação como segmentação podem ser estendidas para permitir a execução de programas parcialmente carregados na memória. As técnicas para isso são denominadas paginação por demanda e segmentação por demanda. Aqui iremos considerar apenas o caso da paginação, que é mais comum na prática. Mecanismo básico da paginação por demanda A paginação por demanda é baseada no mecanismo de paginação simples. Na paginação simples, considerada até aqui, todas as páginas lógicas de um processo são carregadas na memória física. Na tabela de páginas, o bit de válido/inválido é usado para indicar quais páginas estão fora da memória lógica. Quando uma página marcada como inválida é acessada, o processo é abortado por acesso ilegal à memória. Na paginação por demanda, apenas as páginas efetivamente acessadas pelo processo são carregadas para a memória física. Agora o bit válido/inválido é usado para indicar quais páginas lógicas foram carregadas. Dessa forma, na paginação por demanda, uma página marcada como inválida na tabela de páginas pode significar apenas que essa página ainda não foi carregada para a memória física. Na paginação por demanda, quando a página lógica acessada pelo processo está marcada como válida na tabela de páginas, o endereço lógico é transformado em endereço físico, e o acesso transcorre normalmente. Quando a página lógica está marcada como inválida, a MMU (Memory Management Unit) gera uma interrupção de proteção e aciona o sistema operacional. O SO consulta, então, o descritor do processo em questão. Caso a página acessada esteja fora do espaço de endereçamento do processo, o processo é abortado. Caso contrário tem-se que a página referenciada ainda não foi carregada para a memória, e é dito que ocorreu uma interrupção por falta de página (page fault). Quando ocorre uma falta de página, as seguintes ações devem ser realizadas: O processo que gerou a interrupção de falta de página é suspenso, seu descritor de processo é removido da fila do processador e inserido em uma fila especial, a "fila dos processos esperando página lógica"; Uma página física livre deve ser alocada; A página lógica acessada deve ser localizada no disco (a localização das páginas no disco é indicada no registro descritor do processo); Uma operação de leitura do disco deve ser solicitada, indicando o endereço da página lógica no disco e o endereço da página física alocada. Enquanto isso, o processo que executava fica suspenso, à espera da página de que ele necessita para continuar sua execução. A gerência do processador pode então AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 16 selecionar outro processo para executar. Quando a operação de leitura do disco for concluída, a gerência de memória concluirá o atendimento à falta de página realizando as seguintes ações: A tabela de páginas do processo é corrigida para indicar que a página lógica causadora da interrupção é agora válida e está na página física que fora alocada antes; O descritor do processo é retirado da "fila dos processos esperando página lógica" e colocado na fila do processador. Observe que o processo deverá repetir a instrução que causou a falta de página (esta instrução não foi executada devido a falta de página). Repetir uma instrução após a carga da página faltante requer uma arquitetura de computador adequada, especialmente projetada para suportar memória virtual. Nem todos os processadores suportam esse mecanismo. Na "paginação por demanda pura", somente são carregadas para a memória física aquelas páginas realmente referidas pelo processo (a carga das páginas é feita à medida que ocorrem as faltas de página). O processo inicia só com a sua página zero na memória, ou seja, todas as entradas da sua tabela de páginas, exceto a primeira, são inválidas. Nas primeiras instruções que o processo executa certamente ocorrem várias faltas de página. Após algum tempo, o processo consegue se estabilizar e iniciar efetivamente sua execução. Para evitar essa rajada inicial de interrupções por falta de página, alguns sistemas carregam várias páginas automaticamente, antes de iniciar um processo. O sistema procura carregar páginas que serão realmente usadas. Um "bom chute" é carregar as páginas iniciais da memória lógica. A Figura 2 ilustra o mecanismo da paginação por demanda. O processo da figura possui uma memória lógica composta por 8 páginas. Entretanto, apenas 3 páginas foram carregadas para a memória principal. São elas as páginas lógicas 2, 3 e 6. As demais estão marcadas como inválidas na tabela de páginas. Caso o processo tente acessar as páginas 2, 3 e 6, tudo transcorre como na paginação simples. Caso o processo tente acessar alguma das outras páginas, vai ocorrer uma interrupção por falta de página. Nesse momento, o sistema operacional deverá alocar uma página física livre, copiar a página solicitada do disco para a memória física e corrigir a tabela de páginas do processo. Substituição de páginas na memória Como parte do atendimento a uma interrupção por falta de página, uma página física livre deve ser alocada. Entretanto, à medida que processos vão sendo carregados para a memória, é possível que todas as páginas físicas acabem ocupadas. Nesse caso, para atender à falta de página, será necessário antes liberar uma página física ocupada. Isso significa escolher uma página lógica que está na memória, copiar seu conteúdo de volta para o disco (se necessário) e marcar a respectiva página como inválida na tabela de páginas do seu processo. A página a ser substituída é chamada de página vítima. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 17 Memória Lógica Memória Física 0 A 0 1 B 1 2 C 2 3 D 3 D 4 E 4 G 5 F 5 6 G 7 H Tabela de Páginas 0 i 1 i 2 10 v 3 3 v 4 i 5 6 7 i 4 v i Disco B C 6 D 7 E 8 F 9 10 A G C H 11 12 13 14 15 Figura 2 - Mecanismo básico da paginação por demanda. As Figuras 3 e 4 ilustram o mecanismo de substituição de páginas. A Figura 3 mostra a situação original do sistema. Existem dois processos, chamados processo 1 e processo 2. Cada processo possui uma memória lógica composta por 4 páginas lógicas. Seriam necessárias 8 páginas físicas para manter os dois processos integralmente na memória. Como a memória física possui apenas 6 páginas, esses processos possuem algumas páginas na memória física e outras no disco. Existe espaço alocado no disco para toda a memória lógica de cada processo, mas uma página na memória física pode ser alterada durante a execução e, portanto, sua respectiva cópia em disco pode estar desatualizada. A Figura 3 mostra que o processo 1 possui as páginas 0, 1 e 3 na memória física e a página 2 no disco. O processo 2 possui as páginas 0, 1 e 2 na memória física e a página 3 no disco. Suponha agora que o processo 2 tente acessar sua página lógica 3. A MMU vai gerar uma interrupção de proteção, pois essa página está marcada como inválida na tabela de páginas. O sistema operacional vai identificar essa interrupção como uma falta de página e tentar alocar uma página física livre. Como não existem mais páginas físicas livres, um algoritmo de substituição de páginas deve ser usado para escolher uma página vítima. Suponha que a página lógica 2 do processo 2 seja escolhida como vítima. Ela deve então ser marcada como inválida na tabela de páginas do processo 2, e seu conteúdo, copiado para o disco. Após a escrita em disco terminar, a página física 4 é declarada livre. A partir desse momento, é aplicado o tratamento normal para uma interrupção por falta de página. A página lógica 3 do processo 2 será lida do disco para a página física 4. A configuração final da memória é mostrada na Figura 4. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 18 Memória Lógica do Processo 1 Tabela de Páginas do Processo 1 0 A 0 1 v 1 B 1 5 v 2 C 2 3 D 3 i 0 v Memória Lógica do Processo 2 Tabela de Páginas do Processo 2 0 E 0 3 v 1 F 1 2 v 2 G 2 4 v 3 H 3 Disco Memória Física 0 D 1 A 2 F 3 E 4 G 5 B A B C D E F G H i Figura 3 - Sistema hipotético com dois processos. O algoritmo de substituição de páginas é responsável pela escolha da página vítima. Ele é muito importante para a eficiência do mecanismo como um todo. Uma escolha errada significa que a página removida será novamente acessada em seguida, gerando uma nova falta de página. É importante que o algoritmo usado seja capaz de remover da memória física páginas que provavelmente não serão necessárias logo em seguida. Memória Lógica do Processo 1 Tabela de Páginas do Processo 1 0 A 0 1 v 1 B 1 5 v 2 C 2 3 D 3 i 0 v Memória Lógica do Processo 2 Tabela de Páginas do Processo 2 0 E 0 3 v 1 F 1 2 v 2 G 2 3 H 3 i 4 Disco Memória Física 0 D 1 A 2 F 3 E 4 H 5 B A B C D E F G H v Figura 4 - Sistema da Figura 3 após uma substituição de página. Bits auxiliares da tabela de páginas Vários bits auxiliares são normalmente adicionados à tabela de páginas, com o objetivo de facilitar a implementação do mecanismo de substituição de páginas. Embora a existência de tais bits não seja absolutamente necessária, eles tornam o mecanismo mais simples e eficiente. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 19 O bit de sujeira (dirty bit) indica quando uma página foi alterada durante a execução do processo. Esse bit é zerado pelo sistema operacional quando a página é carregada para a memória. A MMU automaticamente liga o bit quando o processo realiza uma operação de escrita nessa página. Dessa forma, o sistema operacional é capaz de determinar se essa página está alterada com relação à sua cópia em disco. A maioria das páginas de um processo (código e constantes) é apenas lida e nunca escrita. Dessa forma, graças ao bit de sujeira, na maioria das substituições de páginas haverá apenas um acesso ao disco, e não dois. Observe que o tempo necessário para atender a uma falta de página é dado basicamente pelo tempo do acesso ao disco. A disponibilidade do bit de sujeira significa que o tempo de atendimento à falta de página pode ser reduzido para a metade na maioria dos casos. O bit de referência (reference bit) indica quando uma página foi acessada pelo processo. Este bit é feito igual a zero determinadas situações, ditadas pelo algoritmo de substituição de página empregado. A MMU liga automaticamente esse bit sempre que a página correspondente é acessada. O bit de tranca (lock bit) serve para o sistema operacional "trancar" uma página lógica na memória física. Existem situações nas quais uma determinada página lógica não deve ser escolhida como vítima (por exemplo, quando a página está envolvida em uma operação de E/S). Algoritmos de substituição de páginas Vamos agora descrever os principais algoritmos de substituição de páginas encontrados na literatura. Em geral, os sistemas operacionais empregam alguma variação dos algoritmos apresentados aqui. Isso ocorre porque é necessário adaptar o algoritmo desejado às facilidades oferecidas pela MMU do processador em questão. FCFS (First Come First Served) É o algoritmo com implementação mais simples. A página escolhida como vítima é sempre aquela que está há mais tempo na memória. Para implementar FCFS, o SO deve manter uma lista de números de páginas lógicas carregadas. Quando uma página é carregada na memória, o seu número é incluído no final da lista. No momento de escolher uma página vítima, basta pegar o número que aparece no início da lista, pois essa é a página que está há mais tempo na memória. Em geral, o desempenho do FCFS não é bom. O fato de uma página estar velha na memória principal não está relacionado com a sua necessidade (ou não) para a execução do processo. ÓTIMO O algoritmo escolhe como vítima a página lógica cujo próximo acesso vai ocorrer mais remotamente no futuro. Na verdade, é impossível implementar tal algoritmo, pois ele exige o conhecimento prévio do comportamento dos processos. Saber quais páginas um processo vai acessar no futuro implica conhecer exatamente o seu fluxo de controle AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 20 futuro. Como, na maioria dos programas, o fluxo de execução depende dos dados processados, não é possível implementar o algoritmo ÓTIMO. Entretanto, podemos tentar imaginar algoritmos factíveis que aproximem o seu comportamento. LRU (Least Recently Used) O algoritmo escolhe para vítima a página acessada mais remotamente no passado (isto é, aquela que há mais tempo não é acessada). Ele se baseia na suposição de que as páginas acessadas recentemente por um processo continuarão sendo acessadas no futuro próximo. A utilização de laços, sub-rotinas e módulos na construção dos programas faz com que essa suposição seja verdadeira a maior parte das vêzes. Embora possível de ser implementado, o LRU exige um suporte de hardware raramente encontrado. É necessário que a MMU mantenha na tabela de páginas o instante exato no qual cada página foi acessada pela última vez. Isso implica em manter um registrador adicional de vários bytes para cada uma das entradas da tabela. Segunda chance O algoritmo da 2ª chance tenta se aproximar do LRU. O gerente de memória considera que todas as páginas lógicas presentes na memória formam uma lista circular. Um apontador percorre essa lista e indica qual a página vítima, da maneira explicada a seguir. Quando uma página vítima é necessária, o algoritmo verifica o bit de referência da página indicada pelo apontador. Caso esse bit esteja desligado, essa página é efetivamente escolhida como vítima, e o apontador avança uma posição na lista circular. Caso o bit de referência da página apontada esteja ligado, o bit de referência é desligado, e ela recebe uma segunda chance. O apontador avança uma posição na lista circular, e o procedimento é repetido para a próxima página. No caso extremo, todas as páginas possuem o bit de referência ligado. Nesse caso, o apontador fará uma volta completa na lista, desligando todos os bits de referência. Ao chegar novamente na primeira página visitada, essa terá agora o bit de referência desligado e será escolhida como página vítima. Devido a esse comportamento circular, o algoritmo também é conhecido como algoritmo do relógio (clock algorithm), em analogia aos ponteiros de um relógio. Variante da segunda chance O seguinte algoritmo combina os algoritmos FIFO e 2ª chance e pode ser usado mesmo quando a MMU não implementa o bit de referência. Novamente, um apontador percorre uma lista circular de páginas lógicas. Além disso, o gerente de memória mantém uma fila de páginas físicas livres com um número fixo de páginas. Quando ocorre uma falta de página, o algoritmo de substituição escolhe como vítima a primeira página da fila de páginas livres (e a remove da fila). A página indicada pelo apontador é então marcada como inválida, atualizada em disco e inserida no fim da fila de páginas físicas livres. Entretanto, seu conteúdo não é alterado. Caso essa página volte a ser acessada em seguida, ocorrerá uma falta de página, pois ela está marcada como inválida na respectiva tabela de páginas. Entretanto, essa falta de página será atendida rapidamente, pois não é AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 21 necessário nenhum acesso a disco. A página é simplesmente retirada da fila de páginas livres (pode ser retirada do meio da fila) e reativada na tabela de páginas apropriada. O tempo de permanência da página na fila de páginas livres oferece a ela uma segunda chance de permanecer na memória e evitar o acesso ao disco. É importante observar que, como uma página é removida do conjunto de páginas livres, uma outra página vítima deve ser escolhida para completar o conjunto. Alocação de páginas físicas Uma questão importante é: quantas páginas lógicas cada processo deve possuir na memória física? Em outras palavras, quantas páginas físicas devem ser alocadas para cada processo? Alocação local Uma solução possível é o SO decidir, para cada processo, o número de páginas físicas que ele disporá para executar o seu programa. Quando for necessário escolher uma página vítima, a escolha se restringirá ao conjunto de páginas do próprio processo (isto é, a substituição ocorrerá entre as próprias páginas do processo que gerou a falta). Dessa forma, o número de páginas físicas alocadas ao processo permanece fixo e tem-se uma política de substituição local. O problema da alocação local está exatamente em definir quantas páginas físicas cada processo deve receber. Os programas possuem tamanhos diferentes. Ao mesmo tempo, o número de páginas físicas que um programa necessita para executar com uma baixa taxa de falta de páginas depende do fluxo de controle desse programa. Alocação global É possível evitar o problema da definição do número de páginas físicas para cada processo empregando uma alocação global. Neste caso, a escolha da página vítima envolve todas as páginas que estão na memória física. Isso significa que uma página de um processo pode substituir uma página de outro processo. Um inconveniente é que processos com baixa prioridade são prejudicados. Como eles executam com baixa freqüência, acabam perdendo suas páginas físicas para processos de prioridade mais alta. Quando o processo de baixa prioridade finalmente consegue executar, seu número de páginas físicas é pequeno, e logo acontece uma falta de página. É necessário algum mecanismo limitador, que impeça um processo de ficar com um número muito pequeno de páginas físicas, que venha prejudicar sua execução. Soluções para o problema da alocação de páginas físicas são consideradas a seguir, na discussão de um outro problema associado, denominado thrashing. Vale observar que todos os algoritmos de substituição de páginas apresentados anteriormente podem utilizar tanto políticas locais como globais. Mesmo o “variante da 2ª chance” pode usar uma política local, se for desejado (nesse caso, cada processo terá a sua fila de páginas físicas livres). AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 22 Trashing O tratamento de uma falta de página é várias ordens de grandeza mais lento que um acesso normal à memória. Logo, o impacto da taxa de page faults sobre o tempo de execução do processo é muito grande. Quando um processo possui um número alto de páginas físicas alocadas, a sua taxa de page faults é baixa. À medida que o número de páginas físicas diminui, a taxa de page faults aumenta e pode chegar a um ponto em que o processo pára de realizar trabalho útil. Tudo que o processo faz é esperar pelo atendimento de falta de páginas. Nesse momento, é dito que está ocorrendo thrashing. Para os usuários, o thrashing se manifesta como um congelamento do sistema. No caso da alocação local, esse congelamento pode se limitar a apenas alguns processos. Quando alocação global é empregada, a tendência é o thrashing tomar conta de todo o sistema, pois os processos “roubam” páginas uns dos outros. Para retirar o sistema do estado de thrashing é necessário suspender alguns processos temporariamente, removê-los para o disco e liberar suas páginas físicas. Isto é feito através do mecanismo de swapping. Como o swapping não é algo desejável, pois aumenta o tempo de resposta dos processos, é necessário que a gerência de memória seja capaz de detectar o momento certo de usá-lo, isto é, o momento em que o sistema vai entrar em thrashing. Uma forma simples de detectar o thrashing é observar a taxa de falta de páginas no sistema (o SO pode ter um contador de falta de páginas que seja testado e zerado a cada segundo, por exemplo - nesse caso, em cada teste o valor do contador indica o número de page faults por segundo). É definida uma taxa máxima aceitável e, sempre que o sistema exibe uma taxa maior que a aceitável, imediatamente é feito o swap-out de algum processo. Outra indicação de thrashing é o tamanho da fila de processos esperando carga de página lógica (tamanho da fila do disco, ou partição, usado na implementação da paginação). O emprego de um mecanismo para detectar o thrashing e iniciar o swapping torna atraente o emprego de alocação global. Além disso, a alocação global libera a gerência de memória da tarefa de determinar quantas páginas físicas cada processo deve receber para sua execução. O modelo do Working Set Uma vantagem do modelo de alocação local sobre o modelo global é que o comportamento de um processo não afeta outros processos, isto é, a falta de página de um processo não é resolvida reduzindo o conjunto de páginas de outro processo. Por outro lado, o número de páginas físicas que um programa realmente necessita para executar com uma baixa taxa de page faults depende apenas do fluxo de controle desse programa. Essas e outras considerações levaram ao desenvolvimento da teoria do working set. O working set de um processo no tempo t, para um período de observação (ou janela temporal) , é definido como o conjunto das páginas que o processo refere no intervalo de tempo (t-; t). Normalmente, os sistemas trabalham com simplificações do AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 23 modelo, que consideram apenas a cardinalidade do working set (isto é, o número de elementos do conjunto). A idéia básica dos algoritmos que alocam páginas físicas com base nesta teoria é manter alocadas para o processo o número de páginas do seu working set. O problema do modelo é determinar o valor adequado para a constante (largura da janela temporal). Um valor pequeno para pode não englobar toda a localidade de referência de um processo, provocando falta de páginas. Um valor grande demais tende a manter na memória páginas que não são mais referenciadas. Normalmente, o valor de é definido de forma empírica, levando em conta o grau de multiprogramação desejado, a quantidade de memória RAM disponível e o tamanho médio dos processos. O seguinte algoritmo se baseia na teoria do working set para definir o número de páginas necessárias para um processo e, como conseqüência, obter um bom desempenho para o sistema. Vai ser utilizada uma lista global de páginas livres e os processos não irão roubar páginas uns dos outros Algoritmo FFP (Freqüência de Falta de Páginas) O método utiliza três parâmetros de configuração: taxa de page faults máxima admitida no sistema (tax_max), taxa de page faults mínima (tax_min) e período de contabilização de page faults. Se um processo, durante o período de contabilização, provoca um número de page faults maior que tax_max, isto significa que ele está executando com menos memória que o necessário; nesse caso o SO aloca mais páginas físicas para o processo. Se, durante o período de contabilização, o processo provoca um número de page faults menor que tax_min, isto significa que ele possui mais memória que o necessário; nesse caso o SO libera algumas de suas páginas físicas, as quais são inseridas na lista de páginas físicas livres do sistema. Se um processo necessita de mais páginas físicas e não há espaço disponível (i.é, a lista de páginas livres está vazia), a solução é suspender um processo e transferí-lo para a área de swap. O processo a ser suspenso pode ser o que ocasionou a falta de página ou outro qualquer (a decisão é tomada pelo escalonador de médio prazo). Desempenho da paginação por demanda O tempo efetivo de acesso à memória (te) em um sistema que utiliza paginação por demanda é dado por: te = (1-p) * tam + p * ttf onde p é a taxa de page faults, tam é o tempo médio de acesso à memória principal quando não ocorre page fault e ttf é o tempo médio necessário para o tratamento completo de uma falta de página (inclusive o acesso ao endereço físico resultante, após a busca). Observe que a taxa de page faults corresponde, de fato, à probabilidade de ocorrência de um page fault: se p=0 todos os acessos ao espaço de endereçamento não geram page fault; no outro extremo, se p=1, todos os acessos geram page faults. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 24 Como tam é uma constante (característica de hardware), restam dois fatores para melhorar o desempenho do sistema (ttf e p). O valor de ttf pode ser melhorado otimizando o procedimento de acesso ao disco (localização e busca de páginas). Isto normalmente é feito através da definição de áreas específicas do disco para implementação de paginação (p.ex., as partições de swap dos sistemas UNIX). O valor de p pode ser minimizado através de políticas adequadas de alocação de memória e de substituição de páginas. Exercícios 1) Considere um sistema cuja gerência de memória é feita através de partições variáveis. Nesse momento, existem as seguintes lacunas (áreas livres): 10K, 4K, 20K, 18K, 7K, 9K, 12K e 13K, nessa ordem. Quais espaços serão ocupados pelas solicitações: 5K, 10K e 6K, nessa ordem, se: (a) First-Fit for utilizado? (b) Best-Fit for utilizado? (c) Worst-Fit for utilizado? (d) Circular-Fit for utilizado? 2) Compare partições fixas, partições variáveis, paginação simples e segmentação simples com respeito ao compartilhamento de memória (código). Para cada uma, mostre como é possível implementar ou por que é impossível implementar. Lembre-se de que é sempre necessário manter a proteção entre usuários, e que os programas ocupam um espaço lógico contíguo. 3) Qual a fragmentação apresentada pelos métodos de gerência de memória baseados em partições fixas, partições variáveis, paginação simples e segmentação simples? Justifique. 4) Considere um sistema operacional que trabalha com paginação simples. As páginas são de 1Kbyte. O endereço lógico é formado por 16 bits. O endereço físico é formado por 20 bits. Qual o tamanho do: (a) Espaço de endereçamento lógico (maior programa possível)? (b) Espaço de endereçamento físico (memória principal)? (c) Entrada da tabela de páginas, sem considerar bits de proteção? (d) Tabela de páginas (número de entradas necessárias no pior caso)? 5) O sistema operacional XYZ utiliza paginação como mecanismo de gerência de memória. São utilizadas páginas de 1Kbyte. Um endereço lógico ocupa 20 bits. Um endereço físico ocupa 24 bits. Cada entrada na tabela de páginas contém, além do número da página física, um bit de válido/inválido e um bit que indica apenas leitura (read-only). Mostre como podem ser calculados os seguintes valores: (a) Qual o tamanho máximo para a memória física. (b) Qual o maior programa que o sistema suporta. (c) Quantas entradas possui a tabela de páginas. (d) Quantos bits serão necessários para a tabela de páginas (cálculo exato). 6) Mostre a diferença entre fragmentação interna e fragmentação externa. Em que situação poderá ocorrer fragmentação interna quando partições variáveis são utilizadas? AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 25 7) Descreva passo a passo o que acontece após uma falta de página. 8) Como é possível determinar se uma interrupção de proteção acionada pela MMU é devida a um acesso ilegal à memória ou a uma falta de página? 9) Um processo deve executar em 5 páginas físicas. O momento da carga (valor do relógio no momento da carga), o momento do último acesso (valor do relógio no último acesso) e o bit de referência para cada página na memória são mostrados. Qual página será escolhida como vítima se o algoritmo de substituição utilizado for: (a) Segunda chance circular (apontador inicia em 0)? (b) LRU? (c) Segunda chance FIFO? Página Carga Última refer. Bit refer. 0 126 279 1 1 230 255 0 2 160 280 1 3 119 272 0 4 123 123 0 10) Como a medida da freqüência de page faults pode ser utilizada para controlar o thrashing? 11) Porque não se pode determinar quantos frames um processo necessita para seu conjunto de trabalho (working set), em um dado instante, olhando apenas o tamanho do programa? 12) O sistema operacional SO/S-plus observa o conjunto de páginas lógicas em uso pelos processos para decidir se pode ou não iniciar a execução de um novo processo. Esse sistema define, como conjunto de trabalho, o conjunto das páginas acessadas no último intervalo completo do timer. O sistema dispõe de 20 páginas físicas. A história do sistema no último intervalo completo do timer é mostrada abaixo. Quantas páginas físicas o sistema poderá fornecer a um novo processo, mantendo ainda o conjunto de trabalho dos processos atuais? P0(4,5,3,6,3,4,5,3,3,6) P1(1,7,8,8,1,3,1,7,8,9) P2(6,7,8,5,8,6,6,7,5,5) 13) Ilustre, através de um exemplo numérico com 10 acessos à memória, a diferença entre os algoritmos de substituição de páginas ÓTIMO e LRU. Faça com que o número de faltas de página seja diferente. Utilize 3 páginas físicas. 14) Cite uma vantagem e uma desvantagem de usar páginas menores na memória virtual com paginação por demanda. 15) Qual problema pode ocorrer quando um periférico pode acessar diretamente a memória e utiliza-se paginação por demanda? Como resolvê-lo? 16) Suponha que a taxa de page faults em um sistema seja inversamente proporcional à quantidade de memória RAM. Quando a capacidade de memória é dobrada a taxa de page faults reduz-se à metade. Correntemente, o sistema possui 32 Mb de memória e o tempo efetivo de acesso é 300 µs. Nos acessos normais (sem page fault) o tempo médio de acesso é 1 µs. Quando ocorre um page fault o tempo médio de acesso é de 1 ms. Calcule quanto de memória adicional seria necessário para reduzir o tempo efetivo de acesso para 100 µs. Suponha que a memória total do sistema deva ser uma potência de 2. AMBIENTES OPERACIONAIS – Prof. Simão Toscani Gerência de Memória (Do livro Sistemas Operacionais, Oliveira R., Carissimi A. e Toscani S., Ed. Sagra-Luzzatto, 2004) p. 26