Alguém pode explicar esse diagrama sobre a alocação de placas?


10

Estou tentando entender como a Alocação de placas funciona e por que é diferente ou melhor que a paginação comum.

Eu encontrei este diagrama que acredito que seria útil se tivesse mais explicações.

Algumas perguntas:

  • O que os itens de 3 KB e 7 KB representam? Eles devem estar relacionados de alguma forma? Por que eles são embalados dessa maneira?
  • Na coluna caches, os caches são as caixas cinza ou as caixas branca / azul dentro das caixas cinza? As caixas cinza são um pacote de caches?
  • As lajes são apenas as caixas azuis ou as "Páginas Físicas Contíguas" inteiras são uma laje?

Eu realmente aprecio alguma ajuda. Obrigado!

Alocação de placas

Respostas:


15

Eu posso ver porque você está confuso. O diagrama é um pouco confuso e pode estar incorreto.

Primeiro, vamos pensar por que um kernel precisa de um alocador de memória abaixo do nível das páginas. Provavelmente, isso já é algo que você já conhece, mas vou analisá-lo em detalhes.

As páginas são a "unidade" típica das operações de memória. Quando um aplicativo de espaço do usuário aloca memória, ou mapeia um arquivo de memória, ou algo assim, normalmente obtém um múltiplo do tamanho da página da máquina. Existem algumas exceções notáveis; O Windows usa 64k como unidade de alocação de memória virtual, independentemente do tamanho da página da CPU. No entanto, vamos pensar dessa maneira.

Em uma CPU moderna, no que diz respeito ao código do espaço do usuário, ela possui um espaço de endereço plano. Na verdade, isso é uma ilusão fornecida pelo sistema de memória virtual. O sistema operacional fornece páginas de qualquer lugar na RAM (ou possivelmente nem mesmo na RAM, no caso de memória trocada ou arquivos mapeados na memória) e as mapeia em um espaço de endereço virtual contíguo.

O ponto de tudo isso é que, além de alguns casos especiais para o próprio sistema operacional (talvez buffers DMA, talvez algumas estruturas de dados especiais configuradas no momento da inicialização, oh e a própria imagem do kernel), o kernel do sistema operacional provavelmente nunca precisará gerenciar qualquer bloco de RAM maior que uma página. Isso simplifica enormemente as coisas, porque significa que, no que diz respeito às páginas, toda alocação e desalocação é do mesmo tamanho. Também elimina efetivamente a fragmentação externa no nível macro.

No entanto, os kernels também precisam implementar algumas estruturas de dados próprias e, para isso, precisam de um tipo diferente de alocador de memória. Essas estruturas de dados geralmente podem ser consideradas como uma coleção de objetos individuais (por exemplo, um objeto pode ser um "encadeamento" ou um "mutex"). O tamanho desses objetos geralmente é muito menor que o tamanho de uma página.

Assim, por exemplo, um objeto que representa as credenciais de segurança de um processo (pense no ID do usuário e ID do grupo no POSIX, digamos) pode ter apenas 16 bytes ou mais, enquanto um "processo" ou "encadeamento" pode ter até 1 KB de tamanho. Claramente, você não deseja usar uma página inteira para esses pequenos registros; portanto, a idéia é implementar um alocador na parte superior das páginas.

O sistema de alocação de nível inferior precisa atender a muitos dos mesmos problemas que o alocador em nível de página: ele deve ser razoavelmente rápido (inclusive em sistemas com vários núcleos), você deseja minimizar a fragmentação e assim por diante. Mais importante, porém, deve ser sintonizável e configurável, dependendo do tipo de estrutura de dados que você está armazenando.

Algumas estruturas de dados são inerentemente "semelhantes a cache". Por exemplo, muitos sistemas operacionais mantêm um cache de nomes de caminho para objetos do sistema de arquivos para evitar longas cadeias de pesquisa de diretório (chamadas de "cache de nome" ou "cache de namei" no Unix-speak). Esses objetos são necessários apenas para desempenho, não para correção, então você pode (em teoria) esquecer uma página inteira cheia de entradas se a memória estiver fraca e você precisar liberar um quadro de página rapidamente.

Outras estruturas de dados podem ser trocadas para o disco se a memória estiver fraca e você não precisar delas em breve. Mas você não quer fazer isso com estruturas de dados que controlam a troca ou o sistema de memória virtual!

Algumas estruturas de dados podem ser movimentadas na memória sem penalidade (por exemplo, se ninguém se referir a elas com um ponteiro); portanto, elas podem se compactar para evitar a fragmentação, se necessário.

Portanto, a idéia principal do alocador de laje é que uma página deve armazenar apenas estruturas de dados do mesmo "tipo". Isso marca todas as caixas: cada objeto em uma página é do mesmo tamanho, portanto não há fragmentação externa. Objetos do mesmo "tipo" têm os mesmos requisitos de desempenho e a mesma semântica.

Aliás, é uma história semelhante com alocação. Para alguns tipos de objetos, provavelmente não há problema em esperar se não houver memória disponível imediatamente para alocar esse objeto. Um objeto que representa um arquivo aberto pode ser um exemplo; abrir um arquivo é uma operação dispendiosa na melhor das hipóteses, portanto, esperar um pouco mais não vai doer tanto.

Para outros tipos de objetos (por exemplo, um objeto que representa um evento em tempo real que deve ocorrer daqui a um certo tempo), você realmente não deseja esperar. Portanto, faz sentido que alguns tipos de objetos sejam alocados em excesso (digamos, tenham algumas páginas gratuitas de reserva) para que as solicitações possam ser atendidas sem esperar.

Basicamente, o que você está fazendo é permitir que cada tipo de objeto tenha seu próprio alocador, que pode ser configurado para as necessidades desse objeto. Esses alocadores por objeto são chamados confusamente de "caches". Você aloca um cache por tipo de objeto. (Sim, você normalmente implementaria também um "cache de caches".) Cada cache armazena apenas objetos do mesmo tipo (por exemplo, apenas estruturas de encadeamento ou apenas estruturas de espaço de endereço).

Cada cache, por sua vez, gerencia "lajes". Uma laje é um quadro de página que contém uma matriz de objetos do mesmo tipo. As lajes podem estar "cheias" (todos os objetos em uso), "vazias" (sem objetos em uso) ou "parciais" (alguns objetos em uso).

As lajes parciais são provavelmente as mais interessantes, pois o alocador de lajes mantém uma lista livre para cada laje parcial. (As lajes completas e as vazias não precisam de uma lista livre.) Os objetos são alocados primeiro das lajes parciais (e provavelmente das lajes parciais "mais cheias" primeiro) para tentar evitar a alocação de páginas desnecessárias.

O bom da alocação de laje é que todas essas opções de política de alocação (assim como a semântica de memória) podem ser ajustadas para cada tipo de objeto. Alguns caches podem reter um conjunto de lajes vazias e outros não. Alguns podem ser trocados para armazenamento secundário e outros não.

O Linux possui três tipos diferentes de alocador de laje, dependendo de você precisar ou não de compacidade, compatibilidade com cache ou velocidade bruta. Houve uma boa apresentação sobre isso há alguns anos, o que explica bem as vantagens e desvantagens.

O alocador de placas Solaris (consulte o documento para obter detalhes ) possui mais alguns detalhes para reduzir ainda mais o desempenho. Para começar, no Solaris, tudo é feito com alocação de laje, incluindo alocação de quadro de página. (Essa é a solução do Solaris para alocar objetos com mais de meia página.) Gerencia objetos menores, aninhando alocadores de laje no espaço alocado por laje.

Alguns objetos no Solaris requerem construção e destruição complexas e caras (por exemplo, objetos que possuem um bloqueio de kernel) e, portanto, podem ser "parcialmente livres" (ou seja, construídos, mas não alocados). O Solaris também otimiza a alocação de placas livres, mantendo listas gratuitas por CPU, garantindo que algumas operações sejam completamente livres de espera.

Para oferecer suporte à alocação de uso geral (por exemplo, para matrizes cujo tamanho não é conhecido no momento da compilação), a maioria dos sistemas operacionais do tipo macrokernel também possui caches que representam tamanhos de objetos em vez de tipos de objetos . O FreeBSD, por exemplo, mantém caches para objetos desconhecidos cujos tamanhos são potências de 2 bytes, de 4 a 256.

O que eu espero que você possa ver é que a alocação de laje é uma estrutura muito flexível que pode ser ajustada para as necessidades de diferentes tipos de dados. Ele não compete com a paginação, mas a complementa (embora no Solaris, os quadros de página sejam alocados com lajes).

Eu espero que isso ajude. Deixe-me saber se algo precisa de esclarecimentos.


6

A idéia abaixo do alocador de laje é que o sistema operacional precise de estruturas de dados específicas, mas um tanto padronizadas (por exemplo, PCB de processo, semáforos, metadados de arquivo etc.) que sugiram o uso de memória necessário para eles.

O algoritmo de alocador de placas fornece estoques de áreas de memória cujas dimensões e inicialização são otimizadas para essas estruturas de dados padrão. Por exemplo, como você pode ver na figura, podem existir objetos de 3kb e de 7kb. No entanto, sabemos que o kernel aloca memória apenas em múltiplos do tamanho da página.

Para evitar tempo e desperdício de memória, o sistema operacional mantém em caches diferentes conjuntos de áreas de memória que podem ser alocadas rapidamente mediante solicitação, e as dimensões do cache são diferentes para cada tipo de objeto e estrutura. No entanto, os caches não contêm e gerenciam diretamente essas áreas de memória e nem garantem que residam na memória contígua. Em vez disso, são divididos em lajes, páginas contíguas de memória, cujo número geralmente é escolhido para reduzir a fragmentação da memória. É na laje que reside as diferentes instâncias do objeto, alocadas ou livres. Se um cache estiver cheio, uma nova laje será alocada em algum lugar da memória primária e será adicionada ao cache.

Resumindo, as coisas que você pode ver na figura são exemplos de objetos que o sistema operacional sabe que têm de 3 a 7 kB de tamanho. O kernel não aloca uma memória de página especificamente para eles, pois isso aumentaria exponencialmente a fragmentação da memória, mas os "redirecionaria" para um cache (a caixa cinza). No cache, deve haver endereços que indiquem áreas fisicamente contíguas da memória, as lajes (os conjuntos de caixas branco / azul) e os objetos são finalmente alocados em uma área da laje (uma parte colorida em azul, entre livre de). áreas de memória análogas completas da mesma placa).

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.