Vmalloc ve kmalloc arasındaki fark nedir?


114

Etrafta dolaştım ve kmallocbitişik fiziksel bellek blokları elde edeceğiniz garantili olduğundan, çoğu insanın kullanımını savunan buldum . Bununla birlikte, istediğiniz kmallocbitişik bir fiziksel blok bulunamazsa başarısız olabilir gibi görünüyor .
Bitişik bir bellek bloğuna sahip olmanın avantajları nelerdir? Özellikle, neden bir sistem çağrısında bitişik fiziksel bellek bloğuna ihtiyacım olsun ki ? Kullanmamam için herhangi bir sebep var mı ? Son olarak, bir sistem çağrısının işlenmesi sırasında bellek ayıracak olsaydım, belirtmeli miyim? Bir sistem çağrısı atomik bağlamda mı yürütülür?vmalloc
GFP_ATOMIC

GFP_ATOMIC
Tahsis, yüksek önceliklidir ve uyumaz. Bu, kesinti işleyicilerinde, alt yarılarda ve uyuyamadığınız diğer durumlarda kullanılacak bayraktır.

GFP_KERNEL Bu normal bir tahsisattır ve bloke olabilir. Bu, uyumak için güvenli olduğunda işlem bağlam kodunda kullanılacak bayraktır.



4
Bu makale, "Genellikle 32 bit mimarinin 4KB sayfa boyutuna ve 64 bit mimarinin 8KB sayfa boyutuna sahip olduğu" gibi saçmalıklar iddia ediyor. Tam olarak okumadım, ama ona "iyi" demem, hatta ondan bir kelimeye bile güvenmem.
Alexandro Sánchez

1
Not (yarı ilişkili): vmallocKernel 5.2 ile daha hızlı (Q2 2019)
VonC

Yanıtlar:


96

Arabelleğe fiziksel olarak adreslenmiş bir veri yolundaki (PCI gibi) bir DMA aygıtı tarafından erişilecekse, yalnızca fiziksel olarak bitişik belleği kullanma konusunda endişelenmeniz gerekir. Sorun şu ki, birçok sistem çağrısı, tamponlarının sonunda bir DMA cihazına geçip geçmeyeceğini bilmenin bir yolu yok: tamponu başka bir çekirdek alt sistemine ilettiğinizde, gerçekten nereye gideceğini bilemezsiniz. Çekirdek bugün DMA için arabelleği kullanmasa bile , gelecekteki bir geliştirme bunu yapabilir.

vmalloc, genellikle kmalloc'tan daha yavaştır, çünkü tampon alanını hemen hemen bitişik bir aralığa yeniden eşleştirmek zorunda kalabilir. kmalloc asla yeniden eşleme yapmaz, ancak GFP_ATOMIC ile çağrılmazsa kmalloc engelleyebilir.

kmalloc sağlayabileceği arabellek boyutu ile sınırlıdır: 128 KBayt *) . Gerçekten büyük bir arabelleğe ihtiyacınız varsa, vmalloc veya önyükleme sırasında yüksek bellek ayırmak gibi başka bir mekanizma kullanmanız gerekir.

*) Bu önceki çekirdekler için geçerliydi. Son çekirdeklerde (bunu 2.6.33.2'de test ettim), tek bir kmalloc'un maksimum boyutu 4 MB'a kadar! (Bunun hakkında oldukça ayrıntılı bir yazı yazdım .) - kaiwan

Bir sistem çağrısı için GFP_ATOMIC'yi kmalloc () 'a geçirmeniz gerekmez, GFP_KERNEL'i kullanabilirsiniz. Siz bir kesme işleyicisi değilsiniz: Uygulama kodu çekirdek bağlamına bir tuzak aracılığıyla girer, bu bir kesme değildir.


1
Sistem çağrılarının int $ 0x80 tetiklenerek girildiğini sanıyordum? (yani bir kesinti)?
FreeMemory

2
int $ 0x80, tuzak olarak da adlandırılan bir yazılım kesmesidir. Kesme işleyicileri ile kastedilen, kullanıcı bir tuşa bastığında veya hareketleri hareket ettirdiğinde olduğu gibi bir donanım kesintisidir.
Branan

Sistem çağrıları, kullanıcı alanından çekirdek alanı geçişlerine yöneliktir ... kmalloc yalnızca çekirdek bağlamında kullanılır?
AIB

3
@FreeMemory: int $ 0x80, x86'ya özgüdür ve daha sonra, sysenter / syscall'ın (x86'da) yerini alan eski bir yöntemdir.
jørgensen

18

Kısa cevap: Linux Aygıt Sürücülerini indirin ve bellek yönetimi hakkındaki bölümü okuyun.

Cidden, çekirdek bellek yönetimiyle ilgili anlamanız gereken pek çok ince sorun var - zamanımın çoğunu sorunları gidermek için harcıyorum.

vmalloc () çok nadiren kullanılır, çünkü çekirdek nadiren sanal bellek kullanır. kmalloc () tipik olarak kullanılan şeydir, ancak farklı bayrakların sonuçlarının ne olduğunu bilmelisiniz ve başarısız olduğunda ne olacağıyla başa çıkmak için bir stratejiye ihtiyacınız var - özellikle de önerdiğiniz gibi bir kesme işleyicisindeyseniz.


1
"çünkü çekirdek nadiren sanal bellek kullanıyor", neden öyle?
Trey

Çekirdek bloğunun, çekirdeğin disk depolaması içine veya dışına bellek değiştirmesini beklerken genellikle istemezsiniz ...
Mike Heinz

Hayır, vmalloc ile ayrılan çekirdek belleği asla değiştirilmez. Yalnızca kullanıcı alanı belleği değiştirilebilir. Çekirdek adres alanı değiştirilemez ve vmalloc, çekirdeğin adres alanını tahsis eder.
user2679859

13

Robert Love'ın yazdığı Linux Kernel Development (Bölüm 12, sayfa 244, 3. baskı) bunu çok açık bir şekilde yanıtlıyor.

Evet, çoğu durumda fiziksel olarak bitişik hafıza gerekli değildir. Kernel'de kmalloc'un vmalloc'tan daha fazla kullanılmasının ana nedeni performanstır. Kitap, büyük bellek parçaları vmalloc kullanılarak tahsis edildiğinde, çekirdeğin fiziksel olarak bitişik olmayan parçaları (sayfaları) tek bir bitişik sanal bellek bölgesine eşlemesi gerektiğini açıklıyor. Bellek hemen hemen bitişik olduğundan ve fiziksel olarak bitişik olmadığından, birkaç sanal-fiziksel adres eşlemelerinin sayfa tablosuna eklenmesi gerekecektir. Ve en kötü durumda, sayfa tablosuna (arabellek boyutu / sayfa boyutu) eşleme sayısı eklenecektir.

Bu ayrıca, bu arabelleğe erişirken TLB (son sanaldan fiziksel adrese eşleştirmeleri depolayan önbellek girişleri) üzerinde baskı oluşturur. Bu, çarpışmaya neden olabilir .


11

kmalloc()Ve vmalloc()işlevleri bayt büyüklüğünde parçalar halinde çekirdek bellek elde edilmesi için basit bir arayüz vardır.

  1. kmalloc()Fonksiyon sayfaları fiziksel olarak bitişik (ve neredeyse bitişik) olduğunu garanti eder.

  2. vmalloc()Fonksiyon için benzer bir şekilde çalışır kmalloc()bunun dışında sadece sanal olarak bitişik ve mutlaka fiziksel olarak bitişik değildir ayırdığı bellek.


4

Bitişik bir bellek bloğuna sahip olmanın avantajları nelerdir? Özellikle, neden bir sistem çağrısında bitişik fiziksel bellek bloğuna ihtiyacım olsun ki? Sadece vmalloc kullanmamam için herhangi bir sebep var mı?

Google'ın "Kendimi Şanslı Hissediyorum" sayfasından vmalloc:

Çok büyük alanlara ihtiyacınız olmadığı sürece kmalloc tercih edilen yoldur. Sorun şu ki, bazı donanım aygıtlarından / aygıtlarına DMA yapmak istiyorsanız, kmalloc kullanmanız gerekecek ve muhtemelen daha büyük parçaya ihtiyacınız olacak. Çözüm, bellek parçalanmadan önce belleği mümkün olan en kısa sürede ayırmaktır.


Bak, onu okudum ve bana mantıklı gelmiyor. Büyük alanlar için kmalloc kullanmayı anlıyorum ; ama küçük ayırmalar için, fiziksel belleği parçalamaktan kaçınmak için neden vmalloc kullanmıyorsunuz?
FreeMemory

Çünkü en iyi olanı yapmak için çekirdeğe güvenmelisiniz; tek bir yığın ayırmanın daha iyi olduğunu düşünürse, bunu yapacaktır. vmalloc yalnızca, kesinlikle bitişik bir parçaya sahip olmanız gerektiğinde içindir .
Dark Shikari

Sanırım bu mantıklı, ama mantıksız görünüyor. kmalloc, performansın çok önemli olduğu durumlarda kullanılması gerektiği gibi geliyor (yani, disk IO ile uğraşamam). Ayrıca, GFP_ATOMIC ne olacak?
FreeMemory

2

32 bitlik bir sistemde kmalloc (), fiziksel adrese doğrudan eşlemeye sahip (aslında sabit ofset ile) çekirdek mantıksal adresini (yine de sanal bir adres) döndürür. Bu doğrudan haritalama, bitişik bir fiziksel RAM yığını elde etmemizi sağlar. Yalnızca ilk işaretçiyi verdiğimiz ve daha sonra operasyonumuz için bitişik bir fiziksel haritalama beklediğimiz DMA için uygundur.

vmalloc (), çekirdek sanal adresini döndürür ve bu da fiziksel RAM'de bitişik bir eşlemeye sahip olmayabilir. Büyük bellek tahsisi için ve işlemimize ayrılan belleğin Fiziksel RAM'de de sürekli olmasını önemsemediğimiz durumlarda kullanışlıdır.


1

Diğer farklardan biri de kmalloc'un mantıksal adres döndürmesidir (aksi takdirde GPF_HIGHMEM'i belirtirsiniz). Mantıksal adresler "düşük belleğe" (fiziksel belleğin ilk gigabaytında) yerleştirilir ve doğrudan fiziksel adreslerle eşlenir (dönüştürmek için __pa makrosu kullanın). Bu özellik, km tahsisli belleğin sürekli bellek olduğunu belirtir.

Öte yandan, Vmalloc sanal adresleri "yüksek bellekten" döndürebilir. Bu adresler doğrudan fiziksel adreslere dönüştürülemez (virt_to_page işlevini kullanmanız gerekir).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.