Linux çekirdeğinden bir bellek bloğunu nasıl saklayabilirim?


25

İşletim sistemi müdahalesi olmadan, yalnızca bunun için ayrılmış bir bellek bloğuna ihtiyaç duyan bir cihazım var. BIOS veya işletim sistemine bir bellek bloğunun saklandığını ve kullanmaması gerektiğini söylemenin bir yolu var mı?

Bu cihazı bir openSUSE makinesinde kullanıyorum.

Yanıtlar:


23

İstediğinize DMA deniyor. Bu hafızayı rezerve etmek için bir sürücü yazmanız gerekir.

Evet, işletim sisteminin müdahale etmesini istemediğinizi söylediğinizi ve bir sürücü işletim sisteminin bir parçası haline geldiğini söylemiştiniz, ancak bir sürücünün rezervasyonunun olmaması durumunda, çekirdek tüm hafızanın kendisine ait olduğuna inanmaktadır. (Çekirdeğe, Aaron'un cevabına göre hafıza bloğunu yok saymasını söylemediğiniz sürece.)

Rubini, Corbet ve Kroah-Hartmann'ın " Linux Aygıt Sürücüleri, 3 / e " nin 15. Bölümü (PDF) DMA ve ilgili konuları içermektedir.

Bunun bir HTML sürümünü istiyorsanız , bölümün ikinci baskısını çevrimiçi başka bir yerde buldum . 2. basımın, çekirdeği 2.4 yeniyken ortaya çıkmış olan on yıldan daha eski olduğuna dikkat edin. O günden bu yana çekirdeğin bellek yönetimi alt sistemi üzerinde çok fazla çalışma oldu, bu yüzden artık pek de geçerli olmayabilir.


DMA ile hangi fiziksel adreslerin kullanılacağını seçebilir miyim? Çekirdek bana bitişik bir bellek bloğu verecek mi? Her zaman kullanılabilir olma garantisi var mı?
Nathan Fellman

1
Sorularınız, size işaret ettiğim PDF sayfasının 442.
Warren Young

24

İşletim sisteminin tamamen görmezden gelmesini istiyorsanız, " memmap." Tuşunu kullanarak bir bellek deliği açmanız gerekir . Bu referansa bakınız . Örneğin, 2GB bariyerinde 512M istiyorsanız memmap=512M$2G, çekirdek komut satırınıza " " ekleyebilirsiniz .

dmesgÇalmak için bitişik bir delik bulmak için kontrol etmeniz gerekir, böylece herhangi bir cihaza baskı yapmazsınız; anakart + kartlarına özgüdür.

İşleri yapmanın önerilen yolu bu değildir - bkz. Warren Young'ın nasıl yapılacağına dair cevabı (çekirdek sürücüleri + DMA). İstediğiniz soruyu tam olarak cevaplıyorum. Bunu son kullanıcılar için yapmayı planlıyorsanız, bunu onlara yaparsanız sizden nefret edecekler ... güven bana, bu cevabı bilmemin tek nedeni bu.


Düzenleme: Grub2 w / grubby kullanıyorsanız (örneğin CentOS 7), $ 'dan kaçtığınızdan emin olmanız gerekir . Daha \önce bir tane olmalı $. Örnek:

$ sudo -v
$ sudo grubby --update-kernel=ALL --args=memmap='128M\\$0x57EF0000'
$ sudo grubby --info $(sudo grubby --default-kernel) | grep memmap
args="ro crashkernel=auto ... memmap=128M\$0x57EF0000"

1
Cevabınız doğrudan sorumu cevaplasa da, Warren'ın cevabı bu konuyu çözmenin daha iyi bir yolu gibi görünüyor. :-)
Nathan Fellman

1
@WarrenYoung Bununla ne yapmanız gerektiği hakkında hiçbir fikrim yok. Örneğimle " uint8_t *ptr = 0x8000000" olduğunu tahmin ediyorum ? Ya da bu segfault olabilir ... Huh, gerçekten bilmiyorum. Yine cevabı biliyordum, çünkü 4G işaretinin altına manuel olarak bir tampon ayırmak ve daha sonra o sürücünün nerede olduğunu söylemek zorunda kaldığım kötü tasarlanmış bir PCI kartın son kullanıcısıydım; Kullanıcılardan mümkün olmayabilir.
Aaron D. Marasco

2
Sırıtmak için, biraz daha derine baktım ve ihtiyacın var gibi görünüyor MMAP_FIXED | MMAP_ANON. Oynamak için burada özel bir DMA cihazı olmadan, OP'nin istediğini gerçekten yapıp yapmadığını söyleyemem, ancak GRUB'da söylediğimde CentOS kutum 512 MB'lık bana 8 MB'lık bir blok verdi memmap=8M$512M. Kök erişimi bile gerektirmiyor, çünkü olabileceğinden korktum. Fakat bu doğru olanı yapsa bile, hala kesinti ve bununla başa çıkmak için bir sürücüye ihtiyaç duyacağınızı düşünüyorum.
Warren Young

3
@ AaronD.Marasco: Hayır, mmap()'d' sayfalar kullanıcı kodu görünmeden önce sıfırlanır. Güvenlik için yapılır, böylece veriler bir işlemden diğerine sızmaz. Sürücü kullanmak için başka bir neden, çünkü sürücünün yükleme zamanında DMA arabelleğinin içeriğini korumanız gerekebilir. Oh ve bu arada, keyfi olarak yerleştirilmiş mmap()çağrı, memmapçekirdek önyükleme seçeneği olmadan bile başarılı oluyor , en azından hiç kimse sorduğunuz yerde hafıza kullanmıyorsa. Önyükleme seçeneği şüphesiz başarı şansını arttırır, ancak kesin olarak gerekli değildir.
Warren Young,

1
@ AaronD.Marasco hmm, tamam. ilginç. Bu bağlantı için teşekkür ederim, iyi bir okuma.
Woodrow Barlow

5

ARM tabanlı Linux'ta çekirdekten bir bellek bloğu ayırmak için reserved-memory, aygıt ağacı (dts) dosyanızdaki bir düğümü de kullanabilirsiniz . Çekirdek dokümantasyonunda ( buraya bakın ) bir örnek var:

memory {
    reg = <0x40000000 0x40000000>;
};

reserved-memory {
    #address-cells = <1>;
    #size-cells = <1>;
    ranges;

    /* global autoconfigured region for contiguous allocations */
    linux,cma {
        compatible = "shared-dma-pool";
        reusable;
        size = <0x4000000>;
        alignment = <0x2000>;
        linux,cma-default;
    };

    display_reserved: framebuffer@78000000 {
        reg = <0x78000000 0x800000>;
    };

    multimedia_reserved: multimedia@77000000 {
        compatible = "acme,multimedia-memory";
        reg = <0x77000000 0x4000000>;
    };
};

0

Geçerli ayarınızı kontrol etmek için önce bu komutu girin:

sysctl vm.min_free_kbytes

Ayarlanan değeri değiştirmek için düzenleyin /etc/sysctl.conf. Çizgiyi ara:

vm.min_free_kbytes=12888

Eğer yoksa, oluşturun (istediğiniz değerle birlikte). Aşağıdaki değerler kabul edilebilir:

8192
12288
16384
20480

8M son derece muhafazakardır; rahatlıkla 16M de oturabilir. Değeri değiştirdikten sonra, bunu çalıştırın ve yeniden başlatma gerekmez:

sudo sysctl -p

2
Lütfen yayınlarınızı boş bırakmayın; silin veya bir moderatörün sizin için kaldırması için işaretleyin.
jasonwryan
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.