Pergunta

Eu pesquisei ao redor e encontrou a maioria das pessoas que defendem o uso de kmalloc, como você está garantido para obter blocos físicos contíguos de memória. No entanto, também parece que kmalloc pode falhar se um contígua física bloco que você quer não pode ser encontrado.
Quais são as vantagens de ter um bloco contíguo de memória? Especificamente, por que eu precisaria ter uma contígua física bloco de memória em um sistema de chamada ? Existe alguma razão que eu não poderia usar apenas vmalloc
Finalmente, se eu fosse para alocar memória durante a manipulação de uma chamada de sistema, devo especificar GFP_ATOMIC? É uma chamada de sistema executado em um contexto atômica?

GFP_ATOMIC
A alocação é de alta prioridade e não dorme. Esta é a bandeira de usar em manipuladores de interrupção, fundo metades e outras situações onde você não consigo dormir.

GFP_KERNEL Este é um bloco de alocação e força normal. Esta é a bandeira de usar em código contexto do processo quando é seguro para dormir.

Foi útil?

Solução

Você só precisa se preocupar sobre o uso de memória fisicamente contígua se o buffer será acessado por um dispositivo DMA em um fisicamente endereçada ônibus (como PCI). O problema é que muitas chamadas do sistema não têm nenhuma maneira de saber se o seu tampão acabará por ser passado para um dispositivo DMA: uma vez que você passar o buffer para outro subsistema de kernel, você realmente não pode saber onde está indo. Mesmo se o kernel não usar o buffer de DMA hoje, um desenvolvimento futuro pode fazê-lo.

vmalloc é muitas vezes mais lento do que kmalloc, porque ele pode ter de reconfigurar o espaço de memória intermédia para uma gama praticamente contíguas. kmalloc não remaps, embora se não for chamado com GFP_ATOMIC kmalloc pode bloquear.

kmalloc é limitada no tamanho do tampão que pode fornecer: 128 Kbytes *) . Se precisar de uma realmente grande buffer, você tem que usar vmalloc ou algum outro mecanismo, como a reserva de memória alta na inicialização.

*) Isto foi verdade em kernels anteriores. Em kernels recentes (Eu testei isso em 2.6.33.2), o tamanho máximo de um único kmalloc é de até 4 MB! (Eu escrevi um bastante pós detalhados nesta ) -. Kaiwan

Para uma chamada de sistema que você não precisa para passar GFP_ATOMIC para kmalloc (), você pode usar GFP_KERNEL. Você não é um manipulador de interrupção:. O código do aplicativo entra no contexto do kernel por meio de uma armadilha, não é uma interrupção

Outras dicas

Resposta curta:. Baixar Linux e ler o capítulo sobre gerenciamento de memória

A sério, há uma série de questões sutis relacionados ao gerenciamento de memória do kernel que você precisa entender -. Eu passo muito do meu tempo depurar problemas com ele

vmalloc () é muito raramente utilizado, porque o kernel raramente utiliza a memória virtual. kmalloc () é o que é normalmente usado, mas você tem que saber quais são as consequências das diferentes bandeiras são e você precisa de uma estratégia para lidar com o que acontece quando ele falhar - especialmente se você estiver em um manipulador de interrupção, como você sugeriu.

Linux Kernel Development por Robert Love (Capítulo 12, página 244 em 3ª edição) responde a esta forma muito clara.

Sim, fisicamente memória contígua não é necessária em muitos dos casos. Principal razão para kmalloc sendo usado mais de vmalloc no kernel é o desempenho. O livro explica, quando grandes pedaços de memória são alocados usando vmalloc, kernel tem de mapear os pedaços fisicamente não contíguas (páginas) em uma única região de memória virtual contígua. Como a memória é praticamente contíguos e fisicamente não contíguas, vários mapeamentos de endereço virtual para físico terá de ser adicionado à tabela da página. E na pior das hipóteses, haverá (tamanho do buffer de tamanho / página) número de mapeamentos adicionados à tabela de páginas.

Isso também aumenta a pressão sobre TLB (as entradas de cache armazenar recente virtual para mapeamento de endereços físicos) ao acessar esse buffer. Isso pode levar a surra .

As funções kmalloc() & vmalloc() são uma interface simples para obter a memória do kernel em pedaços de tamanho de byte.

  1. A função kmalloc() garantias de que as páginas estão fisicamente contígua (e praticamente contíguos).

  2. A função vmalloc() funciona de forma semelhante ao kmalloc(), exceto que ele aloca memória que é apenas virtualmente contíguo e não necessariamente fisicamente contígua.

Quais são as vantagens de ter um bloco contíguo de memória? Especificamente, por que eu precisaria ter um bloco físico contíguo de memória em uma chamada de sistema? Existe alguma razão que eu não poderia usar apenas vmalloc?

De "Estou com sorte" do Google sobre vmalloc:

kmalloc é a maneira preferida, contanto que você não precisa de muito grandes áreas. O problema é que, se você quer fazer DMA de / para algum dispositivo de hardware, você vai precisar usar kmalloc, e você provavelmente vai precisar pedaço maior. A solução é alocar memória o mais rápido possível, antes memória é fragmentada.

Em um sistema de 32 bits, kmalloc () retorna o endereço lógico do kernel (é um endereço virtual embora) que tem o mapeamento direto (na verdade, com constante deslocamento) para o endereço físico. Este direto garante mapeamento que nós temos um pedaço físico contíguo de RAM. Adequado para DMA onde damos apenas o ponteiro inicial e esperar um mapeamento físico contíguo, posteriormente, para a nossa operação.

vmalloc () retorna o endereço virtual do kernel que por sua vez não pode estar tendo um mapeamento contígua na RAM física. Útil para alocação de memória grande e nos casos em que não se preocupam com que a memória alocada para o nosso processo é contínuo também na RAM física.

Uma das outras diferenças é kmalloc voltará endereço lógico (mais você especificar GPF_HIGHMEM). endereços lógicos são colocados em "falta de memória" (no primeiro gigabyte de memória física) e são mapeados diretamente para endereços físicos (uso __pa macro para convertê-lo). memória Esta propriedade implica kmalloced é a memória contínua.

Por outro lado, vmalloc é capaz de retornar endereços virtuais a partir de "memória alta". Esses endereços não podem ser convertidos em endereços físicos de forma direta (você tem que usar a função virt_to_page).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top