Gömülü sistemdeki tek bir dizi için yığının büyük bir miktarını ayırmanın bir dezavantajı var mı?


12

Genellikle bazı verilerin genel, statik veya yığın üzerinde olması gerektiğine karar vermekte sorunum yok (Burada dinamik ayırma yok, bu yüzden yığın kullanımı yok). Ben aynı zamanda / A Böyle birkaç Q okudum bu bir ama sistem belleği ile karşılaştırıldığında çok büyük veri, büyük miktarda içerdiğinden sorum daha özeldir.

Geliştirmeye çalıştığım mevcut bir kod üzerinde çalışıyorum (tasarım, olası sorunlar, performanslar, vb.). Bu kod eski bir 8 bit MCU'da sadece 4KB RAM ile çalışır . Bu kodda neredeyse 1KB (evet, 4KB RAM sisteminde 1KB) bir dizi kullanımı ile karşı karşıyayım . Bu dizinin her baytı kullanılır, bu soru değildir. Sorun, bu dizinin bildirildiği dosyada statik bir dizi olmasıdır, bu nedenle yaşam döngüsü bir programla aynıdır (yani sonsuz olarak kabul edilebilir).

Ancak, kodu okuduktan sonra, bu dizinin sonsuz bir yaşam döngüsüne ihtiyaç duymadığını öğrendim, tamamen prosedürel bir şekilde inşa edildi ve ele alındı, bu yüzden sadece kullanıldığı işlevde bildirebilmeliyiz, bu şekilde yığında olacak ve bu nedenle bu 1KB RAM'i kurtaracağız.

Şimdi soru: Bu iyi bir fikir olur mu? Tasarım açısından, sonsuz / küresel bir yaşam döngüsüne ihtiyaç duymuyorsa, yığına aittir. Ama hey, bu 4KB'den 1KB , RAM'in% 25'ini böyle ayırmanın bir dezavantajı yok mu? (yığının% 50'si veya daha fazlası olabilir)

Birisi bu tür bir durumla biraz tecrübe paylaşabilir mi veya birisi bu diziyi yığına koymamak için geçerli bir neden düşünebilir mi? Teknik dezavantajları ve tasarım hakkındaki yorumları arıyorum.

Bilinçli olduğum tek şey, bu işleve girerken aslında 1KB yığın boşluğum olduğundan emin olmam gerekiyor. Belki ilgilenmem gereken tek şey budur, belki değil.


4
"Bu nedenle 1 KB RAM'i kaydedin" yazdınız. Ne için saklýyorsun? Bu 1KB, dizi için ihtiyacınız olduğunda kullanılabilir olmalıdır, neden statik bir ayırma yapmıyorsunuz? Dizi için gerekli olmadığında bellek için başka bir kullanımınız var mı?
kkrambo

@kkrambo Bir noktada, RAM'e daha fazla bir şey ekleyemediğimizde, statik veya yığın üzerinde bir sistemin dolu olduğunu düşünüyoruz. Bu diziyi yalnızca kullandığımız zaman yığına koyarsak, aynı anda kullanılmadıkları sürece başka bir işleve izin verir. Ancak soru tamamen yasaldır, şu anda SW'deki hiçbir şeyi değiştirmezsek, daha fazla RAM'e ihtiyacımız yoktur;)
Tim

1
Bu dizinin her zaman aynı kalan içeriğe sahip olup olmadığını veya onu kullanan işlev çağrıldığında değişip değişmediğini açıklayabilir misiniz?
Blrfl

@Blrfl İşlev her çağrıldığında değişir.
Tim

Yanıtlar:


8

Bilinçli olduğum tek şey, bu işleve girerken aslında 1KB yığın boşluğum olduğundan emin olmam gerekiyor.

Evet, bu güçlü bir kısıtlama. Statik olarak, yığın üzerinde bu kadar geniş bir alana sahip olduğunuzdan emin olmanız daha iyi olacaktır. Kod küçükse bir son kullanıyorsanız, GCC kodunuzu derlemek için, bkz bu .

BTW, bazı ucuz mikroişlemciler, "büyük" bir çağrı çerçevesini "normal" olandan daha maliyetli bir şekilde kullanabilir (örneğin, komut kümeleri yığın işaretçisinden bir baytlık ofseti tercih eder). YMMV.

Ayrıca, C ile kod yazıyorsanız ve büyük dizinizin alanının başka amaçlarla yeniden kullanılabileceğini düşünüyorsanız, bunu bir sendika üyesi (genel bir global değişken ile union) yapmayı düşünebilirsiniz . Evet, bu oldukça çirkin.

Alternatif olarak, uygulamaya uygun bazı ilkel yığın allocator kodlama düşünebiliriz (ve bir API diğerlerinden farkı olabilir mallocve free....).


1
Teşekkür ederim, aslında biraz bu tür bir cevap bekliyordum, yani bir yığın taşması ile sonuçlanmadığından emin olmak için statik olarak ayrılmış tutun. Ne yazık ki yeni bir GCC derleyici yok ve kod küçük değil.
Tim

Platformunuz için (belki de GCC'yi kaynak kodundan derleyerek) bir GCC derleyicisi alamıyor musunuz?
Basile Starynkevitch

2
Zaten bir tane var, gerçekten çok eski. Yeni bir tane üzerinde çalışmak benim kapsamımda değil, ne de benim programım için uygun. Ancak, güncel araçlarla bazı şeyler daha kolay olurdu.
Tim

3
Patronunuzdan size daha yeni bir GCC almasını istemek (size güncel ikili araçlar sağlayarak veya GCC'nin yeniden derlenmesi için zaman vererek) IMHO'ya değer, çünkü büyük olasılıkla daha yeni GCC biraz daha iyi optimize eder (biliyor musunuz gcc -flto -Os? ) ve biraz hafıza kazanabilirsiniz ....
Basile Starynkevitch

2
Yolda ama bu bir süre önce gelmeyecek. Zaten daha yeni araç zincirlerine sahip diğer sistemlerde -Os kullanıyorum, ancak bu -flto parametresinin farkında değildim, işaret ettiğiniz için teşekkürler. (GCC 5.4.1'de birkaç hafta önce GCC -Os ve -O1-3 parametresiyle birkaç test yaptım ve RAM her zaman aynıdı. FLASH ve MCU çalışma süresi farklıydı. Bu Q / A'da bahsettiğim ile aynı MCU'da değildi)
Tim

6

İnsanlar büyük bir yığınla temkinli olma eğilimindedir, çünkü RAM'de geriye doğru büyür ve değişkenlerin değerlerinin üzerine yazar ve açıklanamayan davranışlara yol açar. Daha da kötüleşir, çünkü mümkün olan en düşük yığın işaretçi adresini bilmeniz ve rutine girerken tahsis edilecek boyutu çıkarmanız gerekir.

Tüm bunlar, donanım bellek yönetimi (bir yığın taşması meydana geldiğinde tuzaklar veya hatalar oluşturmalıdır) veya bu tür analiz için özelliklere sahip olduğu için derleyici için bir iştir.

Aksi takdirde, RAM'inizle istediğinizi yapabilirsiniz.


4

Önceki cevapların işaret ettiği gibi, ilk önce diziye belleğe uyuyorsa statik bırakmayı da öneriyorum. Çoğu durumda, her zaman kullanılmayan değişkenler için belleği "boşa harcadığınız" anlamına gelse bile, deterministik bellek ayak izine sahip olmak çok daha önemlidir. Yığınıza büyük diziler koymak çok kolay bir şekilde dışarı fırlar ve yığın taşmaları bulunması zor ve yeniden üretilmesi zor sorunlara neden olur (yığını yığmak için MMU kullanamıyorsanız).

Bloğu sendika ile diğer bazı verilerle paylaşma önerisi IMO geçerlidir, ancak yanlış değişkenler bulursanız, bulunması zor problemler için de kaynak olabilir.

Belleğiniz bitiyorsa ve onu paylaşmak için daha kısa ömürlü değişkenler yapmanız gerekiyorsa, diziyi yığına taşımadan önce, kendi dezavantajları olmasına rağmen dinamik bellek ayırma eklemeyi düşünürüm. Bu durumda, dizi kullanılabilir belleğe kıyasla oldukça büyük göründüğü için bu bir yanıt olmayabilir.


1

Bir çeşit flash depolama alanınız varsa başka bir seçeneğiniz vardır. Verilerinizi flash'ta depolayarak ve orada okuyarak ve arayarak koç için erişim hızını değiştirebilirsiniz. Koç içine bir seferde yalnızca bir kayıt yüklemeniz gerekir. Kayıtları güncelleyebilmeniz gerekiyorsa biraz daha karmaşık olacaktır. Kesimli aşınma seviyeli bir mekanizmaya ihtiyacınız olacaktır. Bunu geçmişte yaptım ve erişimi hızlandırmak için bir indeks ekledim.


1
Bunu geçmişte de yaptım ama sorum daha çok yığına koyarsam karşılaşabileceğim problemler hakkındaydı, aslında eksik olduğumuzda RAM'in alternatifleri hakkında değil. Yine de cevap verdiğiniz için teşekkürler
Tim

1

Özellikle gömülü sistemlerle çalışırken, derleme zamanında olası arızaların çoğunun olmasını istersiniz ve çalışma zamanında hiçbir şey başarısız olmaz (yine de bunu başarabilirsek iyi olur ...).

Statik olarak tahsis edilen programınızın rasgele durumlarında ihtiyaç duyabileceğiniz büyük diziler yapmak tam olarak bunu yapar - Bağlayıcı sonunda sizi "bu RAM'e sığmaz" konusunda uyarır, oysa yığın tahsisi programınızın hata ayıklaması zor yığınla çökmesini sağlar taşmaları.

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.