Soru Posix_memalign / memalign ne yapar?


Hangi fonksiyonları anlamaya çalışıyorum memalign() ve posix_memalign() yap. Mevcut belgeleri okumak yardımcı olmadı.

Birisi bana nasıl çalıştığını ve ne için kullanıldığını anlamada yardımcı olabilir mi? Ya da belki bir kullanım örneği sunabilir?

Linux belleğinin nasıl çalıştığını anlamaya çalışıyorum, kendi basit bellek havuzumu (düşük parçalanma yığını) yazmam gerekiyor.


39
2017-07-03 13:20


Menşei


"İhtiyaç" derken, bir ev ödevi veya yazılımınız için algılanan bir gereksinimden mi bahsediyorsunuz? Eğer ikincisiyse, şüpheliyim. Standart ayırıcılar çoğu yük altında çok az parçalanmadır. - R..


Cevaplar:


Buna karşılık malloc herhangi bir hizalamaya sahip olabilen bir bellek yığını verir (tek gereksinim, uygulamanın desteklediği en büyük ilkel türün hizalanması gerektiğidir), posix_memalign İstediğiniz hizalamayı garantilemek için bir bellek hafızası verir.

Yani, örn. posix_memalign(&p, 32, 128) başlangıç ​​adresi 32'nin katları olacak şekilde garanti edilen 128 baytlık bir bellek olacaktır.

Bu, belirli bir hizalamaya uyan bellek gerektiren çeşitli düşük düzey işlemler (SSE talimatları veya DMA kullanımı gibi) için kullanışlıdır.


50
2017-07-03 13:25



Sonucu malloc sadece "herhangi bir" hizalama yok. Sistemdeki herhangi bir yerel tür için uygun şekilde hizalanması garanti edilir (int, uzun, çift, yapılar, vb.). Daha büyük hizalamaların özel amaçlar için kullanılabileceğinden emin olabilirsiniz, fakat kesinlikle uygulamaların büyük çoğunluğu için malloc'un sonucu iyi bir şekilde hizalanır. - John Zwinck
@ John: Haklısınız; ifademi değiştirmeme izin ver ... - Oliver Charlesworth
Tercih etmek için iyi bir neden var mı posix_memalign üzerinde mmaphizalanmış belleği ayıran? - Eli Bendersky
@EliBendersky posix_memalign normalde yığından bir blok ayırır. mmap her zaman işletim sistemine gider. Örneğin, çok sayıda önbellek satırı bellek bloklarını ayırmak istediğinizde posix_memalign çok tercih edilir. Tercih etmek için aynı sebep malloc üzerinde mmap. - jleahy


malloc her zaman ilkel türlerin gerektirdiği maksimum hizalamaya ayarlanmış bir bellek döndürür. Bu izin verir mallocİhtiyacınız olabilecek herhangi bir türü saklamak için bellek. Açıklamasını anlamış posix_memalignBu, adresi, hizalama olarak belirttiğiniz her şeyin bir katı olacak bir bellek konumu döndürmesidir.

Özel bir bellek havuzu yazarken bunun ne kadar yararlı olacağından emin değilim, ancak bunun nasıl uygulanabileceğine dair bir örnek vermem gerekiyor. Fark benim örneğimle, malloc_aligned ile serbest bırakılmalı free_aligned; ancak posix_memalign kullanabilirsiniz free.

#include <stdlib.h>
#include <stdio.h>

void *malloc_aligned(size_t alignment, size_t bytes)
{
    // we need to allocate enough storage for the requested bytes, some 
    // book-keeping (to store the location returned by malloc) and some extra
    // padding to allow us to find an aligned byte.  im not entirely sure if 
    // 2 * alignment is enough here, its just a guess.
    const size_t total_size = bytes + (2 * alignment) + sizeof(size_t);

    // use malloc to allocate the memory.
    char *data = malloc(sizeof(char) * total_size);

    if (data)
    {
        // store the original start of the malloc'd data.
        const void * const data_start = data;

        // dedicate enough space to the book-keeping.
        data += sizeof(size_t);

        // find a memory location with correct alignment.  the alignment minus 
        // the remainder of this mod operation is how many bytes forward we need 
        // to move to find an aligned byte.
        const size_t offset = alignment - (((size_t)data) % alignment);

        // set data to the aligned memory.
        data += offset;

        // write the book-keeping.
        size_t *book_keeping = (size_t*)(data - sizeof(size_t));
        *book_keeping = (size_t)data_start;
    }

    return data;
}

void free_aligned(void *raw_data)
{
    if (raw_data)
    {
        char *data = raw_data;

        // we have to assume this memory was allocated with malloc_aligned.  
        // this means the sizeof(size_t) bytes before data are the book-keeping 
        // which points to the location we need to pass to free.
        data -= sizeof(size_t);

        // set data to the location stored in book-keeping.
        data = (char*)(*((size_t*)data));

        // free the memory.
        free(data);
    }
}

int main()
{
    char *ptr = malloc_aligned(7, 100);

    printf("is 5 byte aligned = %s\n", (((size_t)ptr) % 5) ? "no" : "yes");
    printf("is 7 byte aligned = %s\n", (((size_t)ptr) % 7) ? "no" : "yes");

    free_aligned(ptr);

    return 0;
}

9
2017-07-03 16:16



Bunun için teşekkürler! Bir şekilde hala mingw'den eksik olan, memnunun yerine, çok kullanışlı bir kod parçası. - Bart


Oli'nın cevabına ek olarak, sizi daha da önemli bir konuya yönlendirmek istiyorum.

Son x86 mimarisinde, bellekten belleğe getirilebilecek en küçük veri olan bir önbellek satırı 64 bayttır. Yapı büyüklüğünüzün 56 bayt olduğunu varsayalım, bunların büyük bir dizisi var. Bir öğeyi ararken, CPU'nun 2 bellek isteği göndermesi gerekir (önbellek ortasında olsa bile 2 istek verebilir). Bu, bellek için beklemek zorunda olduğu için performans için kötü, ve sonuçta daha yüksek bir önbellek-miss oranı veren daha fazla önbellek kullanın. Bu durumda, posix_memalign'i kullanmak yeterli değildir, ancak 64byte sınırlarında olacak şekilde yapınızı sıkıştırmalı veya sıkıştırmalısınız.

40 bayt yapısına sahip olmak sadece kötü şanstır :)


6
2018-06-26 02:49





Memalign eski (ref: man sayfası) olduğu gibi, sadece malloc () ve posix_memalign () arasındaki fark burada açıklanacaktır. malloc () 8 bayt olarak hizalanır (örneğin RHEL 32-bit için), ancak posix_memalign () için, hizalama kullanıcı tanımlıdır. Bunun kullanımını bilmek için belki de iyi bir örnek mprotect () kullanarak bellek özniteliğini ayarlıyor. Mprotect () işlevini kullanmak için, bellek işaretçisinin PAGE hizalanmış olması gerekir. Böylece, posix_memalign () öğesini sayfalar halinde hizalama olarak çağırırsanız, döndürülen işaretçi, read-write-function özniteliklerini ayarlamak için mprotect () öğesine kolayca gönderebilir. (örneğin, verileri bellek işaretçisine kopyaladıktan sonra, onu değiştirilmekten korumak için salt okunur özniteliğe ayarlayabilirsiniz). "malloc ()" ifadesinin döndürülmüş işareti burada kullanılamaz.


3
2018-01-02 14:03





Nasıl çalışır, uygulamaya bağlıdır. Fonksiyonun amacı size bir n-bayt hizalanmış bellek bloğu vermektir (bloğun başlangıç ​​adresi bir çoğudur).


2
2017-07-03 13:26





8'in katları olan malond döndürme işaretçisi, Bu, malloc bölünmüş belleğin 8 bayta sahip olduğu ve her yığının başlangıcında boş belleği kontrol ettiği anlamına gelir. 2 problem yüz var.

Daha büyük yığınlar daha fazla bellek harcar, ancak daha büyük yığın yardımı C daha hızlı bir şekilde daha fazla yığın belleği bulur. Memalign bu yığınların ne kadar büyük olduğunu değiştirebilir. Hafızayı kaydetmek istiyorsanız, chunk'ın boyutunu 2 veya 4 olarak azaltın. Uygulamanızı daha hızlı yapmak istiyorsanız, chunk'ın boyutunu 2'ye çıkarın.


-4
2017-08-02 03:24



Bu hem yanlış hem de kafa karıştırıcı. - jleahy