Buscar

Slide Capítulo 8

Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original

Sistemas Operacionais
Memória Principal
Capítulo 8
Caio Macedo Santos
João Pedro da Cunha Dias
Juliana Corrêa Guedes
Laís Barreto Batalha
Leonardo Yundi Aikawa
Lucas Ribeiro Sant’Ana
Objetivos do Capítulo
Fornecer uma descrição detalhada de várias maneiras de organizar o hardware da memória. 
Explorar várias técnicas de alocação de memória aos processos. 
Discutir em detalhes como a paginação funciona nos sistemas de computação contemporâneos.
Hardware Básico
A maioria das CPUs pode decodificar instruções e executar operações simples sobre o conteúdo dos registradores à taxa de uma ou mais operações por tique do relógio. A memória principal é acessada por transação no bus (barramento) da memória. Um acesso pode precisar de vários ciclos, nesse caso ocorre uma interrupção, já que o processador não possui os dados.
A solução é adicionar uma memória rápida entre a CPU e a memória principal, geralmente no chip da CPU para acesso rápido (cache). Para gerenciar a cache embutida, o hardware acelera automaticamente o acesso à memória sem nenhum controle operacional.
A memória principal e os registradores embutidos são o único espaço de armazenamento de uso geral que a CPU pode acessar diretamente. Quaisquer instruções em execução e quaisquer dados que estiverem sendo usados pelas instruções devem estar em um desses dispositivos de armazenamento de acesso direto. Se os dados não estiverem, devem ser transferidos para lá antes que a CPU possa operar sobre eles. 
Hardware Básico
Para a operação apropriada do sistema, devemos proteger o sistema operacional contra o acesso de processos de usuário. Em sistemas multiusuários, devemos adicionalmente proteger os processos de usuário uns dos outros.
É preciso se certificar de que cada processo tenha espaço de memória separado. Isso é fundamental para existir múltiplos processos carregados na memória para execução concorrente. Para assegurar que ele possa acessar somente endereços legais necessita de dois registradores, o registrador base contendo menor endereço físico de memória legal e o registrador limite especifica o tamanho do intervalo.
A proteção de espaço de memória é fornecida pela comparação que o hardware da CPU faz entre cada endereço gerado em modalidade de usuário e os registradores. Esse esquema impede que um programa de usuário modifique o código ou estrutura dados do sistema. Somente o sistema operacional pode modificar esses valores.
Os dois registradores podem ser carregados apenas pelo sistema que usa uma instrução privilegiada espacial, já que são executadas na modalidade kernel.
Hardware Básico
O sistema operacional, sendo executado em modalidade kernel, tem acesso irrestrito tanto à memória quando à memória dos usuários. Isso permite que carregue ou descarregue programas de usuário na memória de usuário, acesse e modifique parâmetros de chamada de sistema, execute I/O a partir da memória do usuário e para a memória do usuário, e forneça muitos outros serviços. 
Vinculação de Endereços
Um programa reside em disco como um arquivo binário. O processo pode ser movimentado entre o disco e a memória durante sua execução. Eles em discos, esperando para serem trazidos a memória para execução, formam uma lista de entrada.
Os endereços podem ser representados de diferentes maneiras. Os endereços de programa-fonte são simbólicos. Um compilador vincula esses endereços a endereços relocáveis. O linkage editor ou carregador vincula os endereços realocáveis a endereços absolutos. Cada vinculação é um mapeamento de um espaço de endereçamento para outro.
Vinculação de Endereços 
A vinculação de instruções e dados a endereços pode ser feita em qualquer passo ao longo do percurso:
Tempo de Compilação: Se souber, onde o processo residirá na memória, um código absoluto pode ser gerado.
Tempo de Carga: Se não for conhecido, onde o processo residirá na memória, então o compilador deve gerar código relocável.
Tempo de execução: Se o processo for movido de um segmento de memória para outro durante sua execução, então a vinculação deverá ser adiada até o tempo de execução. A maioria dos sistemas operacionais de uso geral emprega esse método.
Tempo de compilação-compilador ou montador
tempo de carga -loader e linkage editor
tempo de execução- imagem de memória binária armazenada na memória
Espaço de Endereçamento Lógico x Espaço de Endereçamento Físico 
Um endereço gerado pela CPU é referenciado como endereço lógico, enquanto um endereço visto pela memória, que é carregado no registrador de endereços da memória, é referenciado como endereço físico.
Os métodos de vinculação de endereços em tempo de compilação e em tempo de carga geram endereços lógicos e físicos idênticos. Usualmente referenciamos o endereço lógico como endereço virtual. O conjunto de todos os endereços lógicos gerados por um programa é um espaço de endereçamento lógico. O conjunto de todos os endereços físicos correspondentes a esses endereços lógicos é um espaço de endereçamento físico.
Espaço de Endereçamento Lógico x Espaço de Endereçamento Físico 
O mapeamento de endereços virtuais para endereços físicos em tempo de execução é feito por um dispositivo de hardware chamado de unidade de gerenciamento da memória (MMU). Um MMU simples é gerenciado pelo registrador de base. O registrador de base é chamado de registrador de relocação. O valor do registrador de relocação é adicionado ao endereço quando enviado para a memória.
O programa do usuário nunca vê os endereços físicos reais, ele lida com endereços lógicos. O hardware de mapeamento de memória converte endereços lógicos em endereços físicos.
Espaço de Endereçamento Lógico x Espaço de Endereçamento Físico 
Temos agora dois tipos de endereços: lógicos (0 a max) e físicos (R + 0 a R + max para um valor base R). O programa de usuário gera somente endereços lógicos. Esses endereços devem ser mapeados para endereços físicos antes de serem usados. O conceito de um espaço de endereçamento lógico vinculado a um espaço de endereçamento físico separado é essencial para o gerenciamento apropriado da memória.
Carga Dinâmica 
O programa inteiro e todos os dados tinham que estar na memória física para o processador ser executado. Para utilizarmos melhor o espaço de memória podemos usar a carga dinâmica. Com ela, uma rotina não é carregada até ser chamada. Todas as rotinas são mantidas em disco em formato de carga relocável. 
A vantagem é que a rotina é carregada somente quando necessário. É útil quando grandes volumes de códigos são manipulados com pouca frequência. O tamanho total do programa pode ser grande, mas a parte usada é muito menor. A carga dinâmica não requer suporte espacial do sistema operacional.
Quando uma rotina precisa chamar outra rotina, a rotina chamadora verifica, primeiro, se a outra rotina foi carregada. Se não, o carregador de vinculação relocável é chamado para carregar a rotina desejada na memória e atualizar as tabelas de endereços do programa para que reflitam essa alteração. Em seguida, o controle é passado à rotina recém-carregada.
Vinculação Dinâmica e Bibliotecas Compartilhadas 
As bibliotecas vinculadas dinamicamente são vinculadas a programas de usuários quando os programas são executados. A vinculação dinâmica é semelhante a carga dinâmica. A vinculação é adiada até o tempo de execução. Esse recurso é usado com bibliotecas do sistema. Sem isso, cada programa deve incluir uma cópia de sua biblioteca.
Um strub é incluído na imagem para cada referência a rotinas da biblioteca. Ele é um pequeno fragmento de código que indica como localizar a rotina de biblioteca apropriada residente na memória ou carregar a biblioteca se a rotina ainda não estiver presente.
Se a biblioteca for atualizada, o programa substitui por uma nova versão. Sem essa vinculação, todos esses programas teriam de ser vinculados novamente para ter acesso a nova biblioteca. Mais de uma versão da biblioteca pode estar carregada na memória, e cada programa usará suas informações sobre
a versão para decidir que cópia da biblioteca deve usar. Esse sistema é conhecido como biblioteca compartilhada.
Ao contrário da carga dinâmica, a vinculação dinâmica e as bibliotecas compartilhadas geralmente requerem ajuda do sistema operacional. Se os processos na memória estiverem protegidos uns dos outros, o sistema será a única entidade que poderá verificar se a rotina está no espaço de memória de outro processo ou permite que múltiplos processos acessem os mesmos endereços de memória.
Permuta entre processos (Swapping) 
Para ser executado um processo deve estar na memória. Porém, ele pode ser transferido temporariamente da memória principal para uma memória de retaguarda e, então, trazido de volta à memória principal para continuar a execução. Com a permuta é possível que o endereçamento físico de todos os processos exceda a memória física real, aumentando o grau de multiprogramação. 
Permuta-Padrão
A permuta-padrão envolve a transferência de processos entre a memória principal e uma memória de retaguarda. 
A memória da retaguarda é um normalmente um disco veloz.
O sistema mantém uma fila de prontos composta por todos os processos cujas imagens da memória estão na memória de retaguarda ou na memória principal
Permuta-Padrão
A permuta também é restringida por outros fatores. Para poder permutar um processo, tem que ter certeza que ele está ocioso. Qualquer I/O pendente é particularmente importante. Um processo pode estar esperando por uma operação de I/O quando quisermos removê-lo para liberar memória, mas se a operação I/O estiver acessando assincronamente a memória do usuário em busca de buffers de I/O, o processo não poderá ser removido. 
A permuta-padrão não é usada nos sistemas operacionais modernos.
Permuta em Sistemas Móveis
Os sistemas móveis normalmente não suportam forma alguma de permuta. 
A restrição de espaço é um motivo para os projetistas evitarem a permuta, e o número limitado de gravações que a memória flash tolera é outro motivo. 
Permuta em Sistemas Móveis
No iOS da apple no lugar da permuta, eles solicitam que às aplicações abandonem voluntariamente a memória alocada.
O Android usa uma estratégia parecida com a da Apple, ele pode encerrar um processo se não houver memória livre suficiente disponível.
Alocação de memória contígua 
A memória principal deve acomodar tanto o sistema operacional quanto os diversos processos de usuário. Portanto, precisamos alocar a memória principal da maneira mais eficiente possível.
A memória é usualmente dividida em duas partições: uma para o sistema operacional residente e outra para os processos de usuário.
Na alocação de memória contígua, cada processo fica contido em uma única seção da memória que é contígua à seção que contém o próximo processo
Proteção da Memória 
Para impedir que um processo acesse memória que ele não possui, utilizamos um registrador de relocação, junto com um registrador limite.
O registrador de relocação contém o valor do menor endereço físico;
O registrador limite contém o intervalo de endereços lógicos.
A MMU mapeia o endereço lógico dinamicamente adicionando o valor ao registrador de relocação. Esse endereço mapeado é enviado à memória.
Proteção da Memória 
Quando o scheduler da CPU seleciona um processo para execução, o despachante carrega os registradores de relocação e limite com os valores corretos como parte da mudança de contexto. Já que todo endereço gerado por uma CPU é verificado em relação a esses registradores, podemos proteger tanto o sistema operacional quanto os programas e dados de outros usuários para que não sejam modificados pelo processo em execução.
O esquema do registrador de relocação fornece um modo eficaz para permitir que o tamanho do sistema operacional mude dinamicamente.
Alocação de Memória
Um dos métodos mais simples para alocação da memória é dividir a memória em várias partições de tamanho fixo. Cada partição pode conter exatamente um processo.
Método MFT
Nesse método de partições múltiplas, quando uma partição está livre, um processo é selecionado da fila de entrada e carregado na partição disponível. Quando o processo termina, a partição torna-se disponível para outro processo.
Esse método (chamado MFT) foi originalmente usado pelo sistema operacional IBM OS/360, mas não está mais em uso
Método MVT
Esse método é uma generalização do esquema de partições fixas, ele é usado principalmente em ambientes batch. Muitas das ideias apresentadas aqui também são aplicáveis a um ambiente de tempo compartilhado que use a segmentação pura no gerenciamento da memória.
Partições Variáveis
O sistema operacional mantém uma tabela indicando quais partes da memória estão disponíveis e quais estão ocupadas. 
Inicialmente, toda a memória está disponível para processos de usuário e é considerada um grande bloco de memória disponível, uma brecha. 
Conforme os processos entram no sistema, eles são colocados em uma fila de entrada.
Partições Variáveis
O sistema operacional leva em consideração os requisitos de memória de cada processo e o montante de espaço disponível na memória para determinar que processos devem ter memória alocada.
Quando um processo recebe espaço, ele é carregado na memória e pode, então, competir por tempo da CPU. 
Quando um processo termina, libera sua memória a qual o sistema operacional pode então preencher com outro processo da fila de entrada
Partições Variáveis 
Quando um processo chega e precisa de memória, o sistema procura no conjunto por uma brecha que seja suficientemente grande para esse processo. Se a brecha for grande demais, ela será dividida em duas partes. 
Uma parte é alocada ao processo que chegou; 
E a outra é devolvida ao conjunto de brechas;
Quando um processo é encerrado, ele libera seu bloco de memória que é, então, colocado novamente no conjunto de brechas. Se a nova brecha for adjacente a outras brechas, essas brechas adjacentes serão mescladas para formar uma brecha maior.
Soluções para esse problema 
As estratégias do primeiro-apto, do mais-apto e do menos-apto são as mais usadas para selecionar uma brecha livre no conjunto de brechas disponíveis.
Primeiro-apto(first fit): Aloca a primeira brecha que seja suficientemente grande. A busca pode começar tanto no início do conjunto de brechas quanto na locação na qual a busca anterior pelo primeiro-apto terminou. Podemos encerrar a busca, assim que encontrarmos uma brecha livre suficientemente grande.
Soluções para esse problema 
Mais-apto(best fit): Aloca a menor brecha que seja suficientemente grande. Devemos pesquisar a lista inteira, a menos que ela seja ordenada por tamanho. Essa estratégia produz a brecha com menos espaço sobrando.
Menos-apto(worst fit): Aloca a maior brecha. Deve-se pesquisar a lista inteira, a menos que ela seja classificada por tamanho. Essa estratégia produz a brecha com mais espaço sobrando, que pode ser mais útil do que a brecha com menos espaço sobrando da abordagem do mais-apto.
Soluções para esse problema 
Fragmentação
A fragmentação da memória pode ser interna ou externa.
À medida que processos são carregados na memória e dela removidos, o espaço de memória livre é fragmentado em pequenos pedaços.
A fragmentação externa ocorre quando há espaço total na memória suficiente para atender a uma solicitação, mas os espaços disponíveis não são contíguos: a memória está fragmentada em um grande número de pequenas brechas
Soluções para o problema da fragmentação 
Uma solução para o problema da fragmentação externa é a compactação. Ela é possível apenas se a relocação for dinâmica e feita em tempo de execução. O objetivo é mesclar os conteúdos da memória para unir toda a memória disponível em um grande bloco. No entanto se a relocação for estática e feita em tempo de montagem ou de carga, a compactação não poderá ser realizada.
Outra solução para o problema da fragmentação externa é permitir que o espaço de endereçamento lógico dos processos seja não contíguo, possibilitando assim que um processo receba memória
física onde quer que essa memória esteja disponível.
Segmentação
A segmentação é um esquema de gerenciamento de memória que dá suporte à visão da memória do programador.
A segmentação permite que o hardware forneça um mecanismo de memória que mapeia a visão do programador para a memória física real.
Um espaço de endereçamento lógico é um conjunto de segmentos.
O sistema tem mais liberdade para gerenciar a memória enquanto o programador possui um ambiente de programação mais natural. 
Cada segmento tem um nome e um tamanho.
O programador, especifica cada endereço com dois valores: um nome de segmento e um deslocamento.
Paginação 
Assim como a segmentação, a paginação permite que o espaço de endereçamento físico de um processo seja não contíguo. No entanto, a paginação evita a fragmentação externa e a necessidade de compactação, enquanto a segmentação não faz isso. 
Ela também resolve o considerável problema de acomodar trechos de memória de vários tamanhos na memória de retaguarda.
A memória de retaguarda apresenta os mesmos problemas de fragmentação discutidos em relação à memória principal, mas o acesso é muito mais lento e, portanto, a compactação é impossível.
A maioria dos esquemas de gerenciamento da memória, usada antes da introdução da paginação, sofria desse problema. O problema surge porque, quando fragmentos de código ou dados que residem na memória principal precisam ser transferidos, um espaço deve ser encontrado na memória de retaguarda.
-Leonardo Aikawa
Paginação
Em razão de suas vantagens sobre os métodos anteriores, a paginação em suas várias formas é usada na maioria dos sistemas operacionais, desde os de mainframes aos de smartphones.
A paginação é implementada pela cooperação entre o sistema operacional e o hardware do computador.
Método básico 
O método básico para a implementação da paginação envolve a fragmentação da memória física em blocos de tamanho fixo chamados quadros e a fragmentação da memória lógica em blocos do mesmo tamanho chamados páginas.
Quando um processo está para ser executado, suas páginas são carregadas em quaisquer quadros de memória disponíveis a partir de sua origem (um sistema de arquivos ou a memória de retaguarda).
A memória de retaguarda é dividida em blocos de tamanho fixo que são do mesmo tamanho dos quadros da memória ou clusters de múltiplos quadros.
Método básico
Cada endereço gerado pela CPU é dividido em duas partes: um número de página (p) e um deslocamento de página (d). O número de página é usado como índice em uma tabela de páginas.
Cada endereço lógico é vinculado pelo hardware de paginação a algum endereço físico. O uso da paginação é semelhante ao uso de uma tabela de registradores base, um para cada quadro de memória. 
A tabela de páginas contém o endereço base de cada página na memória física. Esse endereço base é combinado com o deslocamento de página para definir o endereço de memória física que é enviado à unidade de memória.
O tamanho da página (assim como o tamanho do quadro) é definido pelo hardware.
Método básico 
Quando usamos um esquema de paginação, não temos fragmentação externa: qualquer quadro livre pode ser alocado a um processo que precise dele. No entanto, podemos ter alguma fragmentação interna.
Quando um processo chega ao sistema para ser executado, seu tamanho, expresso em páginas, é examinado. Cada página do processo precisa de um quadro. Portanto, se o processo requer n páginas, pelo menos n quadros devem estar disponíveis na memória. Se n quadros estiverem disponíveis, eles serão alocados a esse novo processo.
Observe que os quadros são alocados como unidades. Se os requisitos de memória de um processo não coincidirem com os limites da página, o último quadro alocado pode não ficar completamente cheio.
Método básico 
A primeira página do processo é carregada em um dos quadros alocados, e o número do quadro é inserido na tabela de páginas desse processo. A página seguinte é carregada em outro quadro, o número do quadro é inserido na tabela de páginas, e assim por diante (Figura 8.13).
Método básico 
Um aspecto importante da paginação é a separação clara entre a visão que o programador tem da memória e a memória física real. O programador vê a memória como um espaço único contendo apenas o programa corrente. Na verdade, o programa do usuário se estende por toda a memória física que também mantém outros programas. 
A diferença entre a visão que o programador tem da memória e a memória física real é reconciliada pelo hardware de tradução de endereços. Os endereços lógicos são traduzidos para endereços físicos. Esse mapeamento fica oculto do programador e é controlado pelo sistema operacional. Observe que o processo do usuário, por definição, não pode acessar memória que ele não possui. Ele não tem como endereçar memória que não faz parte de sua tabela de páginas, e a tabela inclui apenas as páginas que o processo possui.
Método básico 
Já que o sistema operacional está gerenciando a memória física, ele tem de conhecer os detalhes de alocação dessa memória. Essas informações são geralmente mantidas em uma estrutura de dados chamada tabela de quadros. A tabela de quadros tem uma entrada para cada quadro de página físico, indicando se o último quadro está livre ou alocado e, se está alocado, para que página de que processo ou processos ele está alocado. Além disso, o sistema operacional deve ter conhecimento de que processos de usuário operam no espaço do usuário, e todos os endereços lógicos devem ser mapeados para produzir endereços físicos. 
O sistema operacional mantém uma cópia da tabela de páginas de cada processo. Essa cópia é usada para traduzir endereços lógicos para endereços físicos sempre que o sistema operacional tem que mapear um endereço lógico para um endereço físico manualmente. Ela também é usada pelo despachante da CPU para definir a tabela de páginas de hardware quando um processo precisa ser alocado à CPU. Portanto, a paginação aumenta o tempo de mudança de contexto.
Suporte de Hardware 
A implementação da tabela de páginas em hardware pode ser feita de várias maneiras. No caso mais simples, a tabela de páginas é implementada como um conjunto de registradores dedicados. Esses registradores devem ser construídos com lógica de altíssima velocidade para tornar eficiente a tradução página-endereço.
Outra opção é a tabela de páginas ser mantida na memória principal, e um registrador base da tabela de páginas (PTBR − page-table base register) aponta para ela. A alteração das tabelas de páginas requer apenas a alteração desse registrador, reduzindo substancialmente o tempo de mudança de contexto.
O problema dessa abordagem é o tempo requerido para acessar uma locação de memória do usuário.
O uso de registradores na tabela de páginas é satisfatório se a tabela de páginas for razoavelmente pequena (por exemplo, 256 entradas). No entanto, a maioria dos computadores contemporâneos permite que a tabela de páginas seja muito grande (por exemplo, com 1 milhão de entradas). Nessas máquinas, o uso de registradores rápidos para implementar a tabela de páginas não é viável.
Suporte de Hardware 
A solução-padrão para esse problema é usar um cache de hardware especial e pequeno, de pesquisa rápida, chamado buffer de tradução paralelo (TLB − translation look-aside buffer) que é uma memória associativa de alta velocidade. Cada entrada do TLB é composta de duas partes: uma chave (ou tag) e um valor. Quando um item é apresentado à memória associativa, ele é comparado com todas as chaves simultaneamente. Se o item for encontrado, o campo de valor correspondente será retornado. 
Suporte de Hardware 
O TLB é usado com as tabelas de páginas como descrito a seguir. Ele contém apenas algumas entradas na tabela de páginas. Quando um endereço lógico é gerado pela CPU, seu número de página é apresentado ao TLB. Se o número de página for encontrado, seu número de quadro fica imediatamente disponível e é usado para acessar a memória. Como acabamos de mencionar, esses passos
são executados como parte do pipeline de instruções dentro da CPU, não comprometendo o desempenho se comparado a um sistema que não implemente paginação.
Se o número da página não estiver no TLB (o que é conhecido como omissão do TLB), uma referência de memória à tabela de páginas deve ser estabelecida. Dependendo da CPU, isso pode ser feito automaticamente em hardware ou via uma interrupção para o sistema operacional. Quando o número do quadro for obtido, podemos usá-lo para acessar a memória (Figura 8.14). Além disso, adicionamos o número da página e o número do quadro ao TLB, para que eles sejam encontrados rapidamente na próxima referência.
Suporte de Hardware 
Se o TLB já estiver cheio de entradas, uma entrada existente deve ser selecionada para substituição. As políticas de substituição vão da menos recentemente utilizada (LRU – least recently used), passando pela escolha por round-robin, até a substituição aleatória. Algumas CPUs permitem que o sistema operacional participe da substituição da entrada LRU, enquanto outras manipulam a questão por elas mesmas. Alguns TLBs também permitem que certas entradas sejam protegidas, significando que elas não podem ser removidas do TLB. Normalmente, as entradas do TLB para códigos de kernel essenciais são protegidas. 
Suporte de Hardware 
Alguns TLBs armazenam identificadores do espaço de endereçamento (ASIDs − address-space identifiers) em cada entrada. Um ASID identifica cada processo de maneira exclusiva e é usado para fornecer proteção ao espaço de endereçamento desse processo.
Se o TLB não der suporte a ASIDs separados, então sempre que uma nova tabela de páginas for selecionada, ele terá que ser esvaziado (ou apagado) para assegurar que o próximo processo em execução não use as informações de tradução erradas.
Quando o TLB tenta resolver números de página virtuais, ele verifica se o ASID do processo em execução corrente coincide com o ASID associado à página virtual. Se os ASIDs não coincidirem, a tentativa é tratada como uma omissão do TLB. Além de fornecer proteção ao espaço de endereçamento, um ASID permite que o TLB contenha entradas para vários processos diferentes simultaneamente.
Suporte de Hardware 
O percentual de vezes que um número de página de interesse é encontrado no TLB é chamado taxa de sucesso. Para encontrar o tempo efetivo de acesso à memória, avaliamos o caso por sua probabilidade: tempo efetivo de acesso = chance de encontrar × tempo de acesso no TLB + chance de não encontrar × tempo de acesso fora do TLB
Proteção 
A proteção da memória em um ambiente paginado é executada por bits de proteção associados a cada quadro. Normalmente, mantidos na tabela de páginas.
Um bit pode definir se uma página é de leitura-gravação ou somente-de-leitura.
A tentativa de gravação em uma página somente-de-leitura provoca uma interceptação de hardware para o sistema operacional (ou violação da proteção à memória).
Toda referência à memória percorre a tabela de páginas para encontrar o número de quadro correto. Ao mesmo tempo em que o endereço físico está sendo calculado, os bits de proteção podem ser verificados para descobrir se alguma gravação está sendo feita em uma página somente-de-leitura.
-Caio Macedo
Proteção 
Pode-se criar um hardware que forneça proteção somente de leitura, de leitura-gravação ou somente-de-execução; ou, fornecendo bits de proteção separados para cada tipo de acesso, podemos permitir qualquer combinação desses acessos. Tentativas ilegais serão interceptadas para o sistema operacional.
Um bit adicionar normalmente é colocado em cada entrada da tabela de páginas como: um bit válido-inválido. 
Proteção 
Quando esse bit é posicionado como válido, a página associada está no espaço de endereçamento lógico do processo e, portanto, é uma página legal (ou válida). Quando o bit é posicionado como inválido, a página não está no espaço de endereçamento lógico do processo. Endereços inválidos são interceptados com o uso do bit válido-inválido. O sistema operacional posiciona esse bit para cada página de modo a permitir ou não o acesso à página. 
Exemplo Proteção 
No exemplo a seguir, temos um sistema com espaço de endereçamento de 14 bits (0 a 16383). tenhamos um programa que use apenas os endereços de 0 a 10468. Dado um amanho de página de 2 KB, temos a situação mostrada na a seguir. Os endereços nas páginas 0, 1, 2, 3, 4 e 5 são mapeados normalmente pela tabela de páginas. Qualquer tentativa de gerar um endereço nas páginas 6 ou 7, no entanto, encontrará o bit válido-inválido posicionado como inválido, e o computador fará uma interceptação para o sistema operacional (referência de pagina invalida).
-Caio Macedo
Observe que esse esquema gerou um problema. Já que o programa se estende somente até o endereço 10468, qualquer referência além desse endereço é ilegal. No entanto, referências à página 5 são classificadas como válidas; assim, acessos aos endereços até 12287 são válidos. Somente os endereços de 12288 a 16383 são inválidos. Esse problema é resultado do tamanho da página de 2 KB e reflete a fragmentação interna da paginação. Raramente um processo usa todo o seu intervalo de endereços. Na verdade, muitos processos usam apenas uma pequena fração do espaço de endereçamento disponível para eles. Seria desperdício, nesses casos, criar uma tabela de páginas com entradas para cada página do intervalo de endereços. Grande parte dessa tabela não seria usada, mas ocuparia um espaço valioso na memória. Alguns sistemas fornecem hardware, na forma de um registrador do tamanho da tabela de páginas (PLTR — page-table length register), para indicar o tamanho da tabela de páginas. Esse valor é verificado para cada endereço lógico para descobrir se o endereço está no intervalo válido para o processo. Falhas nesse teste causam uma interceptação por erro para o sistema operacional.
-Caio Macedo
Páginas Compartilhadas 
Uma vantagem da paginação é a possibilidade de compartilhamento de código comum. Esse aspecto é particularmente importante em um ambiente de tempo compartilhado. Considere um sistema que suporte 40 usuários, cada um deles executando um editor de texto. Se o editor de texto consiste em 150 KB de código e 50 KB de espaço de dados, precisamos de 8.000 KB para suportar os 40 usuários. No entanto, se o código for código reentrante (ou código puro), ele poderá ser compartilhado, como mostrado na Figura a seguir. 
Veremos, três processos compartilhando um editor com três páginas — cada página com 50 KB de tamanho (o tamanho de página grande é usado para simplificar a figura). Cada processo tem sua própria página de dados.
Páginas Compartilhadas 
Código reentrante não é código auto modificável: ele nunca muda durante a execução. Portanto, dois ou mais processos podem executar o mesmo código ao mesmo tempo. Cada processo tem sua própria cópia de registradores e armazenamento de dados para manter os dados de sua execução. Os dados de dois processos diferentes são, é claro, diferentes.
Apenas uma cópia do editor precisa ser mantida na memória física. A tabela de páginas de cada usuário é mapeada para a mesma cópia física do editor, mas as páginas de dados são mapeadas para quadros diferentes. Portanto, para suportar 40 usuários, precisamos apenas de uma cópia do editor (150 KB), mais 40 cópias dos 50 KB de espaço de dados por usuário. 
 Páginas Compartilhadas 
O espaço total requerido agora é de 2.150 KB em vez de 8.000 KB — uma economia significativa.
Outros programas muito usados também podem ser compartilhados — compiladores, sistemas de janelas, bibliotecas de tempo de execução, sistemas de banco de dados, e assim por diante. Para ser compartilhável, o código deve ser reentrante. A natureza somente-de-leitura do código compartilhado não deve ser confiada à precisão do código; o sistema operacional deve impor essa propriedade.
Exemplo Páginas Compartilhadas 
Estrutura de Tabela de Páginas 
Iremos explorar agora algumas das técnicas mais comuns para estruturação da tabela de páginas,
incluindo:
Paginação hierárquica;
Tabelas de páginas com hash (tabela de dispersão);
Tabelas de páginas invertidas (Segmentação). 
Paginação Hierárquica 
A maioria dos sistemas de computação modernos suporta um grande espaço de endereçamento lógico. Em um ambiente assim, a própria tabela de páginas torna-se excessivamente grande e ineficiente.
Paginação Hierárquica 
Uma forma de solucionar esse problema é usar um algoritmo de paginação em 2 níveis, em que a própria tabela de páginas também seja paginada. Já que paginamos a tabela de páginas, o número da página também é dividido em um número de páginas (índice) e em seguida dividimos a própria página em índices, afim de encontrarmos o conteúdo desejável. No entanto, devido a essa enorme quantidade de paginações, esse tipo de paginação não é apropriado para 64 bits.
Tabelas de páginas com hash 
Uma abordagem comum para a manipulação de espaços de endereçamentos maiores que 32 bits é usar uma tabela de páginas com hash, com o valor do hash sendo o número da página virtual. Cada entrada da tabela com hash contém uma lista encadeada de elementos que são mapeados para a mesma locação por uma função hash, para manipular colisões.
Tabelas de páginas com hash 
Cada elemento é composto por 3(três) campos: O número da página da virtual, o valor do quadro de página mapeado e um ponteiro para o próximo. No entanto, uma das desvantagens desse método é que cada tabela de páginas pode ser composta de milhões de entradas e, consequentemente, ocupando uma grande quantidade de memória física que teria o objetivo de administrar a própria memória física. 
Paginação invertida (Segmentação)
Método que seria uma solução melhor para a paginação com hash.
 
Técnica que permite gerenciar a memória baseada em segmentos.
Explora a separação de áreas específicas de um processo
Código, variáveis, pilha
Cada segmento possui um identificador e tamanho
Paginação invertida (Segmentação)
Um aspecto importante do gerenciamento da memória que se tornou inevitável com a paginação é a separação entre a visão que o usuário tem da memória e a memória física real. A segmentação é um esquema de gerenciamento da memória que dá suporte a visão que o usuário tem da memória. Um espaço de armazenamento de endereçamento lógico é um conjunto de segmentos. Cada segmento tem um nome e um tamanho. Os endereços especificam tanto o nome do segmento quanto o deslocamento dentro do segmento.
Paginação invertida (Segmentação) 
Paginação invertida (Segmentação) 
Paginação invertida (Segmentação) 
Em C o compilador pode criar segmentos separados para os elementos a seguir, por exemplo:
O código (fonte)
Global variables
Heap (fila de prioridade)
Arquiteturas Intel de 32 e 64 Bits
A arquitetura de chips Intel tem dominado o panorama dos computadores pessoais há vários anos.
Tanto o intel 8086 como o 8088 são chips de 16 bits e foram baseados em arquitetura segmentada.
Depois, a Intel produziu uma série de chips de 32 bits o IA-32 que incluía a família de processadores Pentium de 32 bits. A arquitetura IA-32 dava suporte tanto à paginação quanto à segmentação. Mais recentemente, a Intel produziu uma série de chips de 64 bits baseados na arquitetura x86-64.
Arquitetura IA-32
É dividido em dois componentes segmentação e paginação.
A CPU gera endereços lógicos que são fornecidos à unidade de segmentação. A unidade de segmentação produz um endereço linear para cada endereço lógico. O endereço linear é então fornecido à unidade de paginação que gera o endereço físico na memória principal.
Segmentação no IA-32
A arquitetura IA-32 permite que um segmento tenha, no máximo, 4 GB, e o número máximo de segmentos por processo é 16 K.
A primeira é composta de até 8 K de segmentos que são exclusivos desse processo.
A segunda é composta de até 8 K de segmentos que são compartilhados entre todos os processos.
Paginação no IA-32
A arquitetura IA-32 permite um tamanho de página de 4 KB ou 4 MB. 
Para melhorar a eficiência de uso da memória física, as tabelas de páginas do IA-32 podem ser transferidas para disco. 
Com a descoberta das limitações da memória de 4 GB das arquiteturas 32 bits, a Intel adotou uma extensão do endereço de página (PAE), que permite esses processadores acessarem um espaço de endereçamento físico maior que 4 GB. 
x86-64
Atualmente, a arquitetura x86-64 fornece um endereço virtual de 48 bits com suporte a tamanhos de página de 4 KB, 2 MB ou 1 GB usando quatro níveis de hierarquia de paginação.
Com a utilização da PAE, os endereços virtuais têm 48 bits, mas suportam até 52 bits de endereços físicos. 
Exemplo: Arquitetura ARM 
Um fato relevante é que, enquanto a Intel projeta e fabrica os chips, a ARM somente os projeta. Em seguida, ela licencia seus projetos para fabricantes de chips. A Apple obteve licença da ARM para usar seu projeto nos dispositivos móveis iPhone e iPad, e vários smartphones baseados no Android também usam processadores ARM. A arquitetura ARM de 32 bits suporta os seguintes tamanhos de página:
Exemplo: Arquitetura ARM 
1-	Páginas de 4 KB e 16 KB
2-	Páginas de 1 MB e 16 MB (denominadas seções)
-Caio Macedo
Exemplo: Arquitetura ARM 
O sistema de paginação em uso depende de uma página ou uma seção estar sendo referenciada. A paginação de um nível é usada para seções de 1 MB e 16 MB; a paginação de dois níveis é usada para páginas de 4 KB e 16 KB. A tradução de endereços com a MMU ARM é mostrada na figura acima.
A arquitetura ARM também suporta dois níveis de TLBs. No nível mais externo estão dois micros TLBs — um TLB separado para dados e outro para instruções. O micro TLB também dá suporte a ASIDs. No nível interno fica um único TLB principal. A tradução de endereços começa no nível do micro TLB. Em caso de um erro, o TLB principal é verificado. Se os dois TLBs gerarem erros, uma pesquisa de tabela de páginas deve ser executada em hardware.
Bibliografia e Referências
SILBERSCHATZ, Abraham; Galvin P. Baer; Gagne Greg. Fundamentos de Sistemas Operacionais. 9 ed. Rio de Janeiro: LTC, 2015.

Teste o Premium para desbloquear

Aproveite todos os benefícios por 3 dias sem pagar! 😉
Já tem cadastro?

Outros materiais