PIC'de malloc kullanımı


10

Bir PIC'de nasıl kullanabilir malloc()ve free()işlevleri kullanabilirim ? stdlib.hBaşlığı kontrol ettim ve onlardan bahsetmedim. MCC18 kullanıyorum.

Bunları kimse kullanmak zorunda mıydı?

Onlara ihtiyacım var çünkü Windows XP'den PIC'ye bir kütüphane taşıyorum. Taşıma rehberi şöyle diyor

İşletim Sisteminin özel işlevlerini PIC işlevlerine uyarla

Ama malloc()ve free()fonksiyonlarının nasıl "tercüme edileceğini" bilmiyorum .


4
Mümkünse statik ayırmayı kullanmaya çalışın.
Nick T

1
Neden? Sorun gerçekten oldukça büyük bir kütüphanenin alt katmanı (platforma özel bir) ve ne için kullandıkları hakkında hiçbir fikrim yok birçok fonksiyon yazıyorum .. ve nasıl değiştirmek için hiçbir fikrim yok static to static ..
stef

11
<4KB RAM'li bir PIC mikrodenetleyici, uygulamanız için yanlış olabilir. PC'de bir bağlantı noktasına başlamadan önce PC kitaplığınızın bellek kullanımını ölçün. ARM Cortex-M3 gibi daha iyi bir şeyle daha iyi olabilirsiniz. Temel kural: taşıdığınız kod tabanı anlaşılamayacak kadar büyükse, bir PIC'ye sığmaz.
Toby Jaffey

Windows sürücüleri (ve genel olarak uygulamalar) esasen bir 'sınırsız RAM' paradigması ile yazılır, çünkü fiziksel RAM tükenirse, sanal bellek takas edilebilir. Kütüphanenin ne yaptığına bağlı olarak, 4kB'den çok daha fazla tüketebilir PIC18F87J11'nizde mevcuttur. Sürücünün ne kadar bellek kullanacağını ölçemeyeceğinizden şüpheleniyorum.
Adam Lawrence

Başka bir potansiyel sorun: Win32 int 32 bit, MCC18 derleyicisiyle ise sadece 16 bit. Dikkatli olmazsanız garip taşma sorunları yaşayabilirsiniz.
Adam Lawrence

Yanıtlar:


8

Birçok uygulamada, kişinin bellek ayırması gerekir, ancak sonradan ayrılan bir şeyi tutarken hiçbir şey boşaltmaya gerek yoktur. Böyle bir sistemde, tek yapmanız gereken, mevcut tüm RAM'i kullanarak bir dizi tanımlamak, o dizinin başlangıcına bir işaretçi ayarlamak ve daha sonra güzel bir kolay malloc işlevi kullanmak için bağlayıcıyı kullanmaktır:

char * next_alloc;
void * malloc (int boyutu)
{
    char * this_alloc;
    this_alloc = sonraki_alloc;
    eğer ((END_OF_ALLOC_SPACE - this_alloc) <boyut)
      dönüş -1;
    next_alloc + = boyut;
    this_alloc döndür;
}
geçersiz (void * ptr)
{
    eğer (ptr)
        next_alloc = (karakter *) ptr;
}

Güzel ve kolay ve herhangi bir sayıda tahsis için sadece iki bayt toplam yükü. Bir blokta free () çağrısı, o bloğu ve sonraki her şeyi yeniden yerleştirir.

Biraz daha karmaşık ayırma düzenleri, biri belleğin alt kısmından yukarı doğru hareket eden ve biri belleğin üstünden aşağı doğru giden iki işaretçi kullanılarak ele alınabilir. Yığındaki veriler homojense ve dışarıdaki tüm referansların nerede olduğunu bilirse, sıkıştırıcı bir çöp toplayıcı kullanmak da mümkündür.


Olasılıklar hakkında eksiksiz bilgi için, electronic.stackexchange.com/questions/7850/…
gavioto20

14

malloc()mikrodenetleyicilerde genellikle "kötü bir şey" olarak kabul edilir. Ancak, kesinlikle ihtiyacınız varsa, üçüncü taraf bir sürüm bulmak isteyeceksiniz.

Şanslıysanız, taşıdığınız kod bellek bloklarını yeniden kullanmaya dayanmayabilir. Bu durumda, bir RAM arabelleğine bir işaretçi döndüren ve daha sonra işaretçiyi istenen blok boyutuna göre ilerleten basit bir ayırıcı yazabilirsiniz.

Bu yaklaşımı daha önce PC kütüphanelerini mikrodenetleyicilere taşımak için başarıyla kullandım.

Aşağıda, ayırıcıyı ile kuracak my_malloc_init()ve ile bellek ayıracaksınız my_malloc(). my_free()bağımlılığı tatmin etmek için var ama aslında hiçbir şey yapmayacak. Sonunda tabii ki alanınız bitecek.

Bunu yapmak için, kodunuzun en kötü durumda bellek gereksinimini ölçmeniz (mümkünse bunu bir PC'de yapın) ve HEAP_SIZEbuna göre ayarlayın . Kütüphanenizin dinamik bellek gerektiren kısmını girmeden önce arayınmy_malloc_init() . Tekrar kullanmadan önce, hiçbir şeyin hala göstermediğinden emin olun heap.

uint8_t heap[HEAP_SIZE];
uint8_t *heap_ptr;

void my_malloc_init(void)
{
    heap_ptr = heap;
}

void *my_malloc(size_t len)
{
    uint8_t *p = heap_ptr;
    heap_ptr += len;
    if (heap_ptr >= heap + HEAP_SIZE)
        return NULL;
    else
        return p;
}

void my_free(void)
{
    // do nothing
}

(not: gerçek dünyada işaretçi hizalamasını, yani heap_ptr2 veya 4 bayt yuvarlamayı düşünmeniz gerekebilir )

Başka bir seçenek de, malloc()genellikle bir FreeList gibi sağladığından daha basit bir ayırma yapısı kullanmaktır , ancak bu, değişken boyutlu blokları ayırmanıza izin vermeyebilir.


3
Acaba malloc IS ne zaman gömülü olarak iyi bir şey olarak kabul edilir.
Kellenjb

1
Diğerlerinin söylediği gibi, programlarda dinamik ayırma istemediğinizi hala kabul ediyorum, ancak bu, bunun için harika bir yol. Gömülü için tasarlanmış üçüncü taraf malloc açık ara en iyi seçimdir. Segmentasyondan kaçınmak bir zorunluluktur. @jobyTaffey İyi yazılmış.
Kortuk

1
@Kellenjb iyi, bu tamamen yeni bir soru :-)
Toby Jaffey

1
Belirtilen öğeyi ve bundan sonra ayrılan her şeyi etkin bir şekilde serbest bırakarak, my_free iletilen değere heap_ptr ayarlamanız gerektiğini öneririm. Açıkçası, bu tür kullanıma izin veren bir sırayla bir şeyler tahsis edilmelidir, ancak bu tür desenler nadir değildir. Bir başka yararlı varyasyon, biri yukarıdan aşağıya, diğeri aşağıdan aşağıya tahsis eden iki çift tahsis / serbest fonksiyona sahip olmaktır.
supercat

13

Bu, sorunuzun cevabı değildir, ancak dinamik bellek ayırma genellikle küçük RAM ortamlarında ve bir işletim sisteminin (örneğin mikrodenetleyici dünyasında) yokluğunda kaşlarını çatır ... gömülü bir ortamda sahip olduğunuz yığın alanı genellikle yüzlerce bayt olarak ölçülen ...

Malloc ve free'i uygulamak esasen bağlantılı "serbest segment" yapılarının bir listesinin bakımıdır ve tahmin edebileceğiniz gibi, serbest segmentlerle ilişkili meta veriler, tipik olarak mevcut olan bellek miktarıyla karşılaştırıldığında önemli değildir. "" bir dinamik bellek havuzunu yönetmek önemli miktarda kullanılabilir kaynak tüketir.


Meta veri yükünün çok küçük olduğu uygulamalar vardır. Tahsis edilmiş bir blok için yalnızca boyutuna ihtiyacınız vardır. Kullanılmayan bloklar için bağlantılı liste işaretçileri, oldukça makul minimum blok boyutlarında bile genellikle ücretsiz olarak kullanılabilir.
Monica

Mikrodenetleyici kullanan küçük, uzun çalışan sistemlerle ilgili sorun genellikle meta verilerle ilgili değil, bellek parçalanmasıyla ilgilidir. Daha da kötüsü, kodunuzda yapılan küçük değişiklikler, daha önce hiç bulunmadığı durumlarda bellek parçalanmasına neden olabilir, böylece aniden programınızın "çok erken" çalışmasını durduracak masum görünümlü bir değişiklik yapabilirsiniz.
Monica

11

Bilmiyorum eğer C18 standart kütüphane destekler mallocve freeancak Mikroçip Uygulaması Not AN914 gösterileri kendi uygulamak nasıl.

Her durumda, Thomas ve diğer posterler, çok küçük RAM alanlarıyla PIC'lerde dinamik bellek kullanmanın tehlikeyle dolu olduğunu öne sürdüler . Daha gelişmiş sanal bellek eksikliği nedeniyle bitişik alanınız hızla tükenebilirTam işletim sistemlerinin size sağladığı yöneticilerinin da başarısız tahsislere ve çökmelere neden olur. Daha da kötüsü, deterministik olmayabilir ve muhtemelen hata ayıklamak için bir acı olacaktır.

Yaptığınız şey çalışma zamanında gerçekten dinamik olarak belirlenirse (çoğu gömülü şey için nadirdir) ve sadece birkaç özel durumda yer ayırmanız gerekiyorsa , görebiliyor mallocve freekabul edilebilir olabiliyordum .


Bitişik alanın tükenmesi, yani yığın parçalanması, adres alanınızın ne kadar büyük olduğundan ve sanal belleğinizin olup olmadığından tamamen bağımsız bir sorundur. Daha düşük yığın parçalanması için boşa harcanan bazı RAM'leri takas etmek isteyebilirsiniz, ancak sonunda uzun süren bir sistemde yığın alanının bitmemesi konusunda hiçbir garantiniz yoktur. Buradaki küçük ve büyük sistemler arasındaki tek fark, diskin çökmeye başlamasının (disk disk belleği VM'si olan sistemlerde) veya ayırıcının NULL (katıştırılmış öğelerde) döndürmesi için geçen süredir.
Monica

@KubaOber: Belirli bir boyuttaki RAM'in, aynı anda tahsis edilmesi için belirli (daha küçük) miktardan daha fazla RAM'e ihtiyaç duymayan herhangi bir tahsisat ve serbest bırakma işlem dizisini işleyebileceğini garanti etmek genellikle mümkündür. Gömülü sistemlerde sorun, en kötü durumda bile garantili başarının, parçalanma olmadan gerekenden çok daha fazla RAM gerektirmesidir.
supercat

@supercat Haklısın. Gerçekten aşırı derecede dramatiktim. Bu garantilerin resmi kanıtları vardır.
Monica

2

PIC, bellek açısından ne kadar büyük?

malloc bellek ayırmanın çok verimsiz bir yoludur. Bununla ilgili sorun, belleğin sık sık serbest kalma ve malloklarla parçalanabilmesidir ve sadece birkaç kilobayt bellekle, ayırma başarısızlıkları çok yaygındır. Daha küçük bir çip veya daha erken bir PIC18 kullanıyorsanız, Microchip'in uygulanması çok zor (veya bazı durumlarda imkansız bile) olduğu veya olması için yeterince kullanılmadığı için malloc desteği yoktur. buna değer. Bahsetmiyorum, ama aynı zamanda oldukça yavaş, zaten mevcut olan bir statik tamponu kullanmak için 1 döngüye ve bir malloc yapmak için 100'lerden 1000'e kadar döngüye bakıyorsunuz.

Statik olarak ayırmak istiyorsanız, siz sprintf işlevleriniz için bir tampon (varsa, yaklaşık 128 bayt), SD kartınız için bir tampon (varsa) vb. Malloc ihtiyacını ortadan kaldırana kadar oluşturun. İdeal olarak, sadece kesinlikle ihtiyacınız olan yerde kullanırsınız ve statik ayırma ile kurtulamazsınız, ancak bu durumlar genellikle nadirdir ve belki de daha büyük / daha güçlü mikrodenetleyicilere bakmanız gerektiğinin bir işaretidir.

PIC18'de bir "işletim sistemi" geliştiriyor / taşıyorsanız ve mikrodenetleyicileri destekliyorsa, muhtemelen statik ayırma desteği vardır. Örneğin, SQLite3 statik ayırmayı destekler - büyük bir arabellek dizisi tahsis edersiniz ve mikro denetleyiciler için olmasa bile mümkün olduğunda bunu kullanır. Değilse, küçük bir PIC18 için tasarlandığından emin misiniz?


Ne demek istediğini anlıyorum .. 128K ram'a sahip PIC18F87J11 kullanıyorum, yeterli olabilir mi?
stef

Stefano, bu çipte 3.904 bayt RAM var. 128K program flash belleği vardır.
W5VO

@Stefao Salati - 3.8KB küçük.
Thomas O

Doğru özür dilerim ... sence zaten yeterli olabilir mi?
stef

@Stefano Salati, özür dilemene gerek yok. Bence gerçekten iteceksin. Çalışabilir, ancak performanstan ve boş belleğinizden bir parça çıkarır.
Thomas O

2

Gömülü yazılımınızı düşünüyorsanız malloc()ve free()uC / OS-II ve OSMemGet()ve OSMemPut(). malloc()Rastgele bir bellek bloğu atamanıza izin verirken , OSMem*()önceden ayrılmış bir havuzdan size sabit boyutlu bir blok verin. Bu yaklaşımı malloc(), statik tahsinin esnekliği ve sağlamlığı arasında iyi bir denge buluyorum .


0

AFAIK, bunu doğru bir şekilde yapabilmek için gerçekten bir çeşit bellek yönetim birimi (MMU) olan bir cihaza bakmanız gerekiyor. PIC18 serisi için dinamik ayırma mekanizmaları mevcut olsa da, gerçekten o kadar sağlam olmayacaklar - ve PIC18 serisinin sınırlarını zorlayan bellenim üzerinde çalışan biri olarak konuşurken, almayacağınızı söyleyebilirim. tüm ek yükü bir bellek yöneticisine harcarsanız, orada büyük bir uygulama.

Daha iyi çözüm: ne yaptığını ve neden dinamik ayırmaya ihtiyaç duyduğunu anlamaya çalışın. Statik ayırmayla çalışacak şekilde yeniden çarpanlara ekleyemeyeceğinize bakın. (Bu mümkün olmayabilir - eğer kütüphane / uygulama serbestçe ölçeklenen bir şey yapacak şekilde tasarlanmışsa veya kabul edebileceği girdi miktarı sınırlarına sahip değilse.) Ama bazen, eğer gerçekten ne yapmaya çalıştığınız konusunda, bunun yerine statik ayırmayı kullanmanın (hatta muhtemelen oldukça kolay) olduğunu görebilirsiniz.


1
Yanılıyorsun. MMU, harici bellekle (muhtemelen PIC'deki 4kB'den daha fazla) arabirim oluşturmanıza olanak tanır. MMU içeren ve içermeyen dinamik ve statik ayırmada çok az fark vardır. Sanal belleğe girmeye başladığınızda bir fark vardır, ancak bu sadece teğetsel olarak malloc ile ilgilidir.
Kevin Vermeer

1
Erken Macintosh programcıları, erken Macintosh bilgisayarlarında MMU bulunmamasına rağmen, malloc () ve free () (veya Pascal eşdeğerlerini) oldukça sık kullandılar. Malloc () kullanarak "doğru" bir MMU gerektirdiği fikri benim için yanlış görünüyor.
davidcary
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.