Pesquisei no Google e encontrei muitas pessoas defendendo o uso de kmalloc
, já que é garantido que você obterá blocos físicos contíguos de memória. No entanto, também parece que kmalloc
pode falhar se um bloco físico contíguo que você deseja não puder ser encontrado.
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 simplesmente usar vmalloc
?
Finalmente, se eu fosse alocar memória durante o tratamento de uma chamada de sistema, devo especificar GFP_ATOMIC
? Uma chamada de sistema é executada em um contexto atômico?
GFP_ATOMIC
A alocação é de alta prioridade e não é suspensa. Este é o sinalizador a ser usado em manipuladores de interrupção, metades inferiores e outras situações onde você não consegue dormir.
GFP_KERNEL
Esta é uma alocação normal e pode bloquear. Este é o sinalizador a ser usado no código de contexto do processo quando é seguro dormir.
fonte
vmalloc
é mais rápido com Kernel 5.2 (Q2 2019)Respostas:
Você só precisa se preocupar em usar memória fisicamente contígua se o buffer for acessado por um dispositivo DMA em um barramento endereçado fisicamente (como PCI). O problema é que muitas chamadas de sistema não têm como saber se seu buffer será passado para um dispositivo DMA: uma vez que você passa o buffer para outro subsistema do kernel, você realmente não pode saber para onde ele está indo. Mesmo que o kernel não use o buffer para DMA hoje, um desenvolvimento futuro pode fazer isso.
vmalloc geralmente é mais lento que kmalloc, porque pode ter que remapear o espaço do buffer em um intervalo virtualmente contíguo. kmalloc nunca remapeia, embora se não for chamado com GFP_ATOMIC kmalloc pode bloquear.
kmalloc é limitado no tamanho do buffer que pode fornecer: 128 KBytes *) . Se você precisa de um buffer muito grande, deve usar o vmalloc ou algum outro mecanismo, como reservar muita memória na inicialização.
Para uma chamada de sistema, você não precisa passar GFP_ATOMIC para kmalloc (), você pode usar GFP_KERNEL. Você não é um manipulador de interrupções: o código do aplicativo entra no contexto do kernel por meio de uma armadilha, não é uma interrupção.
fonte
Resposta curta: baixe os drivers de dispositivos Linux e leia o capítulo sobre gerenciamento de memória.
Sério, existem muitos problemas sutis relacionados ao gerenciamento de memória do kernel que você precisa entender - eu gasto muito do meu tempo depurando problemas com ele.
vmalloc () é muito raramente usado, porque o kernel raramente usa memória virtual. kmalloc () é o que normalmente é usado, mas você precisa saber quais são as consequências dos diferentes sinalizadores e precisa de uma estratégia para lidar com o que acontece quando ele falha - particularmente se você estiver em um manipulador de interrupções, como sugeriu.
fonte
O Linux Kernel Development por Robert Love (Capítulo 12, página 244 na 3ª edição) responde a isso de forma muito clara.
Sim, a memória fisicamente contígua não é necessária em muitos dos casos. O principal motivo para kmalloc ser usado mais do que vmalloc no kernel é o desempenho. O livro explica, quando grandes blocos de memória são alocados usando vmalloc, o kernel precisa mapear os blocos fisicamente não contíguos (páginas) em uma única região de memória virtual contígua. Como a memória é virtualmente contígua e fisicamente não contígua, vários mapeamentos de endereço virtual para físico terão que ser adicionados à tabela de páginas. E no pior caso, haverá (tamanho do buffer / tamanho da página) número de mapeamentos adicionados à tabela de páginas.
Isso também aumenta a pressão sobre o TLB (as entradas de cache que armazenam mapeamentos de endereço virtual para físico recentes) ao acessar esse buffer. Isso pode levar a uma surra .
fonte
As funções
kmalloc()
&vmalloc()
são uma interface simples para obter memória do kernel em blocos do tamanho de bytes.A
kmalloc()
função garante que as páginas sejam fisicamente contíguas (e virtualmente contíguas).A
vmalloc()
função funciona de maneira semelhantekmalloc()
, exceto que aloca memória que é apenas virtualmente contígua e não necessariamente fisicamente contígua.fonte
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 para eu não poder simplesmente usar o vmalloc?
Do Google's "I'm Feeling Lucky" em
vmalloc
:kmalloc é a forma preferida, desde que você não precise de áreas muito grandes. O problema é que, se você quiser fazer DMA de / para algum dispositivo de hardware, precisará usar kmalloc e provavelmente precisará de um pedaço maior. A solução é alocar memória o mais rápido possível, antes que a memória seja fragmentada.
fonte
Em um sistema de 32 bits, kmalloc () retorna o endereço lógico do kernel (embora seja um endereço virtual) que possui o mapeamento direto (na verdade, com deslocamento constante) para o endereço físico. Esse mapeamento direto garante que obtenhamos um pedaço físico contíguo de RAM. Adequado para DMA, onde fornecemos apenas o ponteiro inicial e esperamos um mapeamento físico contíguo depois disso para nossa operação.
vmalloc () retorna o endereço virtual do kernel que, por sua vez, pode não ter um mapeamento contíguo na RAM física. Útil para grande alocação de memória e nos casos em que não nos importamos que a memória alocada para nosso processo seja contínua também na RAM física.
fonte
Uma das outras diferenças é que kmalloc retornará um endereço lógico (caso contrário, você especificará GPF_HIGHMEM). Os endereços lógicos são colocados em "memória baixa" (no primeiro gigabyte de memória física) e são mapeados diretamente para endereços físicos (use a macro __pa para convertê-los). Essa propriedade implica que a memória kmalloced é memória contínua.
Por outro lado, o Vmalloc é capaz de retornar endereços virtuais de "memória alta". Esses endereços não podem ser convertidos em endereços físicos de forma direta (você deve usar a função virt_to_page).
fonte