Qual'è la differenza tra vmalloc e kmalloc?


113

Ho cercato su Google e ho scoperto che la maggior parte delle persone ne sostiene l'uso kmalloc, poiché è garantito che avrai blocchi fisici di memoria contigui. Tuttavia, sembra anche che kmallocpossa fallire se un blocco fisico contiguo che desideri non può essere trovato.
Quali sono i vantaggi di avere un blocco di memoria contiguo? In particolare, perché dovrei avere un blocco fisico di memoria contiguo in una chiamata di sistema ? C'è qualche motivo per cui non potrei semplicemente usare vmalloc?
Infine, se dovessi allocare memoria durante la gestione di una chiamata di sistema, dovrei specificare GFP_ATOMIC? Una chiamata di sistema viene eseguita in un contesto atomico?

GFP_ATOMIC
L'assegnazione è ad alta priorità e non dorme. Questa è la bandiera da usare nei gestori di interrupt, nelle metà inferiori e in altre situazioni in cui non puoi dormire.

GFP_KERNEL Questa è un'allocazione normale e potrebbe bloccarsi. Questo è il flag da utilizzare nel codice di contesto del processo quando è sicuro dormire.



4
Quell'articolo sostiene sciocchezze come: "Generalmente un'architettura a 32 bit ha una dimensione di pagina di 4 KB e un'architettura a 64 bit ha una dimensione di pagina di 8 KB". Non l'ho letto completamente, ma non lo chiamerei "buono", né mi fiderei nemmeno di una parola.
Alexandro Sánchez

1
Nota (semi-correlata): vmallocè più veloce con Kernel 5.2 (Q2 2019)
VonC

Risposte:


96

Devi solo preoccuparti di utilizzare la memoria fisicamente contigua se il buffer sarà accessibile da un dispositivo DMA su un bus indirizzato fisicamente (come PCI). Il problema è che molte chiamate di sistema non hanno modo di sapere se il loro buffer verrà eventualmente passato a un dispositivo DMA: una volta passato il buffer a un altro sottosistema del kernel, non puoi davvero sapere dove andrà a finire. Anche se il kernel non usa il buffer per DMA oggi, uno sviluppo futuro potrebbe farlo.

vmalloc è spesso più lento di kmalloc, perché potrebbe dover rimappare lo spazio del buffer in un intervallo virtualmente contiguo. kmalloc non rimappa mai, anche se se non chiamato con GFP_ATOMIC kmalloc può bloccare.

kmalloc è limitato nella dimensione del buffer che può fornire: 128 KByte *) . Se hai bisogno di un buffer molto grande, devi usare vmalloc o qualche altro meccanismo come riservare una memoria elevata all'avvio.

*) Questo era vero per i kernel precedenti. Sui kernel recenti (l'ho testato su 2.6.33.2), la dimensione massima di un singolo kmalloc è fino a 4 MB! (Ho scritto un post abbastanza dettagliato su questo .) - kaiwan

Per una chiamata di sistema non è necessario passare GFP_ATOMIC a kmalloc (), puoi usare GFP_KERNEL. Non sei un gestore di interrupt: il codice dell'applicazione entra nel contesto del kernel tramite una trappola, non è un interrupt.


1
Pensavo che le chiamate di sistema fossero state inserite attivando int $ 0x80? (cioè un interrupt)?
FreeMemory

2
int $ 0x80 è un interrupt software, chiamato anche trap. Ciò che si intende per gestori di interrupt è un interrupt hardware, ad esempio quando l'utente preme un tasto o sposta le mosse.
Branan

Le chiamate di sistema sono per le transizioni dallo spazio utente allo spazio kernel ... kmalloc viene utilizzato solo nel contesto del kernel ??
AIB

3
@FreeMemory: int $ 0x80 è specifico per x86, quindi è anche un vecchio metodo sostituito da sysenter / syscall (su x86).
jørgensen

18

Risposta breve: scarica i driver del dispositivo Linux e leggi il capitolo sulla gestione della memoria.

Seriamente, ci sono molti problemi sottili relativi alla gestione della memoria del kernel che devi capire: passo molto del mio tempo a eseguire il debug dei problemi con esso.

vmalloc () è usato molto raramente, perché il kernel usa raramente la memoria virtuale. kmalloc () è ciò che viene tipicamente utilizzato, ma devi sapere quali sono le conseguenze dei diversi flag e hai bisogno di una strategia per affrontare ciò che accade quando fallisce, in particolare se sei in un gestore di interrupt, come hai suggerito.


1
"perché il kernel usa raramente la memoria virtuale", perché è così?
Trey

Perché generalmente non si desidera il blocco del kernel mentre attende che il kernel esegua lo scambio di memoria dentro o fuori dalla memoria del disco ...
Mike Heinz

No, la memoria del kernel allocata con vmalloc non viene mai scambiata. È possibile sostituire solo la memoria dello spazio utente. Lo spazio degli indirizzi del kernel non è intercambiabile e vmalloc alloca nello spazio degli indirizzi del kernel.
user2679859

13

Linux Kernel Development di Robert Love (Capitolo 12, pagina 244 nella 3a edizione) risponde molto chiaramente.

Sì, la memoria fisicamente contigua non è richiesta in molti dei casi. Il motivo principale per cui kmalloc viene utilizzato più di vmalloc nel kernel sono le prestazioni. Il libro spiega che, quando grandi blocchi di memoria vengono allocati utilizzando vmalloc, il kernel deve mappare i blocchi (pagine) fisicamente non contigui in una singola regione di memoria virtuale contigua. Poiché la memoria è virtualmente contigua e fisicamente non contigua, sarà necessario aggiungere diverse mappature di indirizzi da virtuale a fisico alla tabella delle pagine. E nel peggiore dei casi, ci sarà (dimensione del buffer / dimensione della pagina) numero di mappature aggiunte alla tabella delle pagine.

Ciò aggiunge anche pressione sul TLB (le voci della cache che memorizzano le recenti mappature degli indirizzi virtuali e fisici) quando si accede a questo buffer. Questo può portare a picchiare .


11

Le funzioni kmalloc()& vmalloc()sono una semplice interfaccia per ottenere la memoria del kernel in blocchi di dimensioni di byte.

  1. La kmalloc()funzione garantisce che le pagine siano fisicamente contigue (e virtualmente contigue).

  2. La vmalloc()funzione funziona in modo simile a kmalloc(), tranne che alloca memoria che è solo virtualmente contigua e non necessariamente fisicamente contigua.


4

Quali sono i vantaggi di avere un blocco di memoria contiguo? In particolare, perché dovrei avere un blocco fisico di memoria contiguo in una chiamata di sistema? C'è qualche motivo per cui non posso usare vmalloc?

Da "Mi sento fortunato" di Google in poi vmalloc :

kmalloc è il modo preferito, a patto di non aver bisogno di aree molto grandi. Il problema è che, se vuoi eseguire DMA da / a qualche dispositivo hardware, dovrai usare kmalloc e probabilmente avrai bisogno di un pezzo più grande. La soluzione è allocare la memoria il prima possibile, prima che la memoria venga frammentata.


Vedi, l'ho letto e non ha senso per me. Capisco l'utilizzo di kmalloc per grandi aree; ma per piccole allocazioni, perché non utilizzare vmalloc per evitare di frammentare la memoria fisica?
FreeMemory

Perché dovresti fidarti del kernel per fare ciò che è meglio; se pensa che sia meglio allocare un singolo blocco, lo farà. vmalloc è solo per quando è assolutamente necessario avere un pezzo contiguo.
Dark Shikari,

Immagino che abbia senso, ma sembra controintuitivo. kmalloc suona come dovrebbe essere usato quando le prestazioni sono di primaria importanza (cioè non posso essere afflitto da IO del disco). Inoltre, che dire di GFP_ATOMIC?
FreeMemory

2

Su un sistema a 32 bit, kmalloc () restituisce l'indirizzo logico del kernel (è un indirizzo virtuale) che ha la mappatura diretta (in realtà con offset costante) all'indirizzo fisico. Questa mappatura diretta assicura che otteniamo una porzione fisica contigua di RAM. Adatto per DMA in cui forniamo solo il puntatore iniziale e ci aspettiamo una mappatura fisica contigua in seguito per la nostra operazione.

vmalloc () restituisce l'indirizzo virtuale del kernel che a sua volta potrebbe non avere una mappatura contigua sulla RAM fisica. Utile per allocazioni di memoria di grandi dimensioni e nei casi in cui non ci interessa che la memoria allocata al nostro processo sia continua anche nella RAM fisica.


1

Una delle altre differenze è che kmalloc restituirà l'indirizzo logico (altrimenti specifichi GPF_HIGHMEM). Gli indirizzi logici sono posti in "memoria insufficiente" (nel primo gigabyte di memoria fisica) e sono mappati direttamente agli indirizzi fisici (usa la macro __pa per convertirlo). Questa proprietà implica che la memoria allocata a km è memoria continua.

D'altra parte, Vmalloc è in grado di restituire indirizzi virtuali da "memoria elevata". Questi indirizzi non possono essere convertiti in indirizzi fisici in modo diretto (devi usare la funzione virt_to_page).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.