Was ist der Unterschied zwischen vmalloc und kmalloc?

113

Ich habe herumgegoogelt und festgestellt, dass die meisten Leute die Verwendung von befürworten kmalloc, da Sie garantiert zusammenhängende physische Speicherblöcke erhalten. Es scheint jedoch auch so, als ob kmalloces fehlschlagen kann, wenn ein zusammenhängender physischer Block, den Sie möchten, nicht gefunden werden kann.
Was sind die Vorteile eines zusammenhängenden Speicherblocks? Warum sollte ich in einem Systemaufruf einen zusammenhängenden physischen Speicherblock benötigen ? Gibt es einen Grund, den ich nicht einfach benutzen könnte ? Wenn ich schließlich während der Bearbeitung eines Systemaufrufs Speicher zuweisen sollte, sollte ich angeben ? Wird ein Systemaufruf in einem atomaren Kontext ausgeführt?vmalloc
GFP_ATOMIC

GFP_ATOMIC
Die Zuweisung hat hohe Priorität und schläft nicht. Dies ist das Flag, das in Interrupt-Handlern, unteren Hälften und anderen Situationen verwendet wird, in denen Sie nicht schlafen können.

GFP_KERNEL Dies ist eine normale Zuordnung und kann blockieren. Dies ist das Flag, das im Prozesskontextcode verwendet werden soll, wenn der Schlaf sicher ist.

Freier Speicher
quelle
Ein guter Artikel über vmalloc und kmalloc http://learnlinuxconcepts.blogspot.in/2014/02/linux-memory-management.html
JIN007
4
Dieser Artikel behauptet Unsinn wie: "Im Allgemeinen hat eine 32-Bit-Architektur eine Seitengröße von 4 KB und eine 64-Bit-Architektur eine Seitengröße von 8 KB." Ich habe es nicht vollständig gelesen, aber ich würde es nicht "gut" nennen oder einem Wort davon vertrauen.
Alexandro Sánchez
1
Hinweis (semi-verwandt): vmallocist schneller mit Kernel 5.2 (Q2 2019)
VonC

Antworten:

96

Sie müssen sich nur um die Verwendung eines physisch zusammenhängenden Speichers kümmern, wenn ein DMA-Gerät auf einem physisch adressierten Bus (wie PCI) auf den Puffer zugreift. Das Problem ist, dass viele Systemaufrufe nicht wissen können, ob ihr Puffer irgendwann an ein DMA-Gerät übergeben wird: Sobald Sie den Puffer an ein anderes Kernel-Subsystem übergeben, können Sie wirklich nicht wissen, wohin er gehen wird. Selbst wenn der Kernel den Puffer heute nicht für DMA verwendet , könnte eine zukünftige Entwicklung dies tun.

vmalloc ist häufig langsamer als kmalloc, da der Pufferraum möglicherweise in einen praktisch zusammenhängenden Bereich neu zugeordnet werden muss. kmalloc wird nie neu zugeordnet, aber wenn es nicht mit GFP_ATOMIC aufgerufen wird, kann kmalloc blockieren.

kmalloc ist in der Größe des Puffers begrenzt, den es bereitstellen kann: 128 KByte *) . Wenn Sie einen wirklich großen Puffer benötigen, müssen Sie vmalloc oder einen anderen Mechanismus verwenden, z. B. das Reservieren von hohem Speicher beim Booten.

*) Dies galt für frühere Kernel. Auf neueren Kerneln (ich habe dies auf 2.6.33.2 getestet) beträgt die maximale Größe eines einzelnen kmalloc bis zu 4 MB! (Ich habe einen ziemlich detaillierten Beitrag dazu geschrieben .) - Kaiwan

Für einen Systemaufruf müssen Sie GFP_ATOMIC nicht an kmalloc () übergeben, sondern können GFP_KERNEL verwenden. Sie sind kein Interrupt-Handler: Der Anwendungscode gelangt über einen Trap in den Kernel-Kontext, es handelt sich nicht um einen Interrupt.

DGentry
quelle
1
Ich dachte, Systemaufrufe wurden durch Auslösen von int $ 0x80 eingegeben? (dh eine Unterbrechung)?
FreeMemory
2
int $ 0x80 ist ein Software-Interrupt, der auch als Trap bezeichnet wird. Unter Interrupt-Handlern versteht man einen Hardware-Interrupt, beispielsweise wenn der Benutzer eine Taste drückt oder die Bewegungen bewegt.
Branan
Systemaufrufe sind für Benutzerraum zu Kernel-Space-Übergängen ... kmalloc wird nur im Kernel-Kontext verwendet?
AIB
3
@FreeMemory: int $ 0x80 ist x86-spezifisch und dann auch eine alte Methode, die von sysenter / syscall (auf x86) ersetzt wird.
Jørgensen
18

Kurze Antwort: Laden Sie die Linux-Gerätetreiber herunter und lesen Sie das Kapitel zur Speicherverwaltung.

Im Ernst, es gibt viele subtile Probleme im Zusammenhang mit der Kernel-Speicherverwaltung, die Sie verstehen müssen - ich verbringe viel Zeit damit, Probleme damit zu debuggen.

vmalloc () wird sehr selten verwendet, da der Kernel selten virtuellen Speicher verwendet. kmalloc () wird normalerweise verwendet, aber Sie müssen die Konsequenzen der verschiedenen Flags kennen und eine Strategie benötigen, um zu behandeln, was passiert, wenn es fehlschlägt - insbesondere, wenn Sie sich in einem Interrupt-Handler befinden, wie Sie vorgeschlagen haben.

Mike Heinz
quelle
1
"Weil der Kernel selten virtuellen Speicher verwendet", warum ist das so?
Trey
Weil Sie im Allgemeinen nicht wollen, dass der Kernelblock, während er darauf wartet, dass der Kernel Speicher in oder aus dem Festplattenspeicher
Mike Heinz
Nein, der mit vmalloc zugewiesene Kernelspeicher wird niemals ausgetauscht. Es kann nur der Benutzerbereichsspeicher ausgetauscht werden. Der Kernel-Adressraum ist nicht austauschbar, und vmalloc wird im Adressraum des Kernels zugewiesen.
user2679859
13

Die Linux-Kernel-Entwicklung von Robert Love (Kapitel 12, Seite 244 in der 3. Ausgabe) beantwortet dies sehr deutlich.

Ja, in vielen Fällen ist kein physisch zusammenhängender Speicher erforderlich. Der Hauptgrund dafür, dass kmalloc im Kernel häufiger als vmalloc verwendet wird, ist die Leistung. Das Buch erklärt, dass der Kernel, wenn große Speicherblöcke mit vmalloc zugewiesen werden, die physisch nicht zusammenhängenden Blöcke (Seiten) einem einzelnen zusammenhängenden virtuellen Speicherbereich zuordnen muss. Da der Speicher praktisch zusammenhängend und physisch nicht zusammenhängend ist, müssen der Seitentabelle mehrere Zuordnungen von virtuellen zu physischen Adressen hinzugefügt werden. Und im schlimmsten Fall wird der Seitentabelle eine Anzahl von Zuordnungen hinzugefügt (Größe des Puffers / Seitengröße) .

Dies erhöht auch den Druck auf TLB (die Cache-Einträge, in denen die letzten Zuordnungen von virtuellen zu physischen Adressen gespeichert sind), wenn auf diesen Puffer zugegriffen wird. Dies kann zu Schlägen führen .

Codetwiddler
quelle
11

Die kmalloc()& vmalloc()-Funktionen sind eine einfache Schnittstelle zum Abrufen des Kernelspeichers in Byte-großen Blöcken.

  1. Die kmalloc()Funktion garantiert, dass die Seiten physisch zusammenhängend (und praktisch zusammenhängend) sind.

  2. Die vmalloc()Funktion funktioniert ähnlich wie, kmalloc()weist jedoch Speicher zu, der nur praktisch zusammenhängend und nicht unbedingt physisch zusammenhängend ist.

Yogeesh HT
quelle
4

Was sind die Vorteile eines zusammenhängenden Speicherblocks? Warum sollte ich in einem Systemaufruf einen zusammenhängenden physischen Speicherblock benötigen? Gibt es einen Grund, warum ich vmalloc nicht einfach verwenden konnte?

Ab Googles "Ich fühle mich glücklich" vmalloc:

kmalloc ist der bevorzugte Weg, solange Sie keine sehr großen Flächen benötigen. Das Problem ist, wenn Sie DMA von / zu einem Hardwaregerät ausführen möchten, müssen Sie kmalloc verwenden, und Sie benötigen wahrscheinlich einen größeren Block. Die Lösung besteht darin, Speicher so schnell wie möglich zuzuweisen, bevor der Speicher fragmentiert wird.

Dunkler Shikari
quelle
Ich habe das gelesen und es macht für mich keinen Sinn. Ich verstehe die Verwendung von kmalloc für große Gebiete. Verwenden Sie für kleine Zuordnungen vmalloc, um eine Fragmentierung des physischen Speichers zu vermeiden.
FreeMemory
Weil Sie darauf vertrauen sollten, dass der Kernel das Beste tut; Wenn es der Meinung ist, dass die Zuweisung eines einzelnen Blocks besser ist, wird es dies tun. vmalloc ist nur für den Fall gedacht, dass Sie unbedingt einen zusammenhängenden Block haben müssen .
Dark Shikari
Ich denke, das macht Sinn, aber es scheint nicht intuitiv zu sein. kmalloc klingt so, als ob es verwendet werden sollte, wenn die Leistung von größter Bedeutung ist (dh ich kann nicht von Festplatten-E / A geplagt werden). Und was ist mit GFP_ATOMIC?
FreeMemory
2

Auf einem 32-Bit-System gibt kmalloc () die logische Kerneladresse (es ist jedoch eine virtuelle Adresse) zurück, die die direkte Zuordnung (tatsächlich mit konstantem Versatz) zur physischen Adresse aufweist. Diese direkte Zuordnung stellt sicher, dass wir einen zusammenhängenden physischen Teil des Arbeitsspeichers erhalten. Geeignet für DMA, wo wir nur den Anfangszeiger angeben und danach eine zusammenhängende physische Zuordnung für unseren Betrieb erwarten.

vmalloc () gibt die virtuelle Kerneladresse zurück, die wiederum möglicherweise keine zusammenhängende Zuordnung zum physischen RAM aufweist. Nützlich für große Speicherzuweisungen und in Fällen, in denen es uns egal ist, dass der unserem Prozess zugewiesene Speicher auch im physischen RAM kontinuierlich ist.

a.saurabh
quelle
1

Einer der anderen Unterschiede ist, dass kmalloc die logische Adresse zurückgibt (andernfalls geben Sie GPF_HIGHMEM an). Logische Adressen werden im "niedrigen Speicher" (im ersten Gigabyte des physischen Speichers) abgelegt und direkt physischen Adressen zugeordnet (verwenden Sie das Makro __pa, um sie zu konvertieren). Diese Eigenschaft impliziert, dass der zugewiesene km-Speicher ein kontinuierlicher Speicher ist.

Andererseits kann Vmalloc virtuelle Adressen aus "hohem Speicher" zurückgeben. Diese Adressen können nicht direkt in physische Adressen konvertiert werden (Sie müssen die Funktion virt_to_page verwenden).

Jérôme Pouiller
quelle