Diğer cevaplara ek olarak, yığın ve yığın alanı arasında RAM oluşturulurken, statik olmayan sabit verilerin (örneğin, globals, fonksiyon statiği ve program genelinde dosya statik) alanını da göz önünde bulundurmanız gerektiğini eklemek isterim. C perspektifinden globaller ve muhtemelen C ++ için diğerleri.
Yığın / yığın tahsisi nasıl çalışır?
Başlangıç derleme dosyasının, bölgeyi tanımlamanın bir yolu olduğuna dikkat etmek gerekir; takım zinciri (hem yapı ortamınız hem de çalışma zamanı ortamınız) çoğunlukla, yığın uzayının başlangıcını (ilk yığın işaretçisini Vector Tablosunda depolamak için kullanılır) ve yığın uzayının başlangıcını ve sonunu (dinamik tarafından kullanılan) tanımlayan sembolleri önemser. hafıza dağıtıcısı, genellikle libc tarafından sağlanan)
OP örneğinde, sadece 2 sembol tanımlanmıştır, 1kiB'de yığın büyüklüğü ve 0B'de yığın büyüklüğü. Bu değerler aslında yığın ve yığın alanlarını üretmek için başka yerlerde kullanılır.
@Gilles örneğinde, boyutlar tanımlanmıştır ve kullanılmış montaj dosyasında, her yerden başlayarak ve boyutuna devam eden bir yığın alanı ayarlamak için, Stack_Mem sembolü ile tanımlanır ve sonunda __initial_sp etiketini ayarlar. Aynı şekilde, boşluğun Heap_Mem (0,5kiB boyutunda) sembolü olduğu, ancak başında ve sonunda etiketlerin bulunduğu yığın için (__heap_base ve __heap_limit).
Bunlar, bağlayıcı tarafından işlenir; bu, yığın belleği ve yığın alanı içinde hiçbir şey tahsis etmeyecektir, çünkü bu bellek kullanılır (Stack_Mem ve Heap_Mem sembolleri tarafından), ancak bu hatıraları ve tüm globals'ları gereken yere yerleştirebilir. Etiketler, verilen adreslerde uzunluğu olmayan semboller olur. __İnitial_sp, bağlantı zamanında doğrudan vektör tablosu için ve çalışma zamanı kodunuz tarafından __heap_base ve __heap_limit'te kullanılır. Sembollerin gerçek adresleri linker tarafından yerleştirildiği yere göre atanır.
Yukarıda belirtildiği gibi, bu sembollerin aslında bir startup.s dosyasından gelmeleri gerekmiyor. Bağlayıcı yapılandırmanızdan (Keil'deki Dağılım Yük dosyası, GNU'daki linkercript) ve yerleştirme üzerinde daha hassas taneli kontrole sahip olabilirsiniz. Örneğin, yığını RAM'in başında veya sonunda olmaya zorlayabilir ya da kürelerinizi öbeklerden uzakta veya istediğiniz şekilde uzak tutabilirsiniz. HEAP veya STACK'in, globall'lar yerleştirildikten sonra geride kalan RAM'i işgal ettiğini bile belirleyebilirsiniz. DİKKAT, diğer belleğinizin azaltacağı daha fazla statik değişken eklemek konusunda dikkatli olmanız gerekir.
Bununla birlikte, her bir araç zinciri farklıdır ve yapılandırma dosyasını nasıl yazacağınızı ve dinamik bellek ayırıcınızın hangi sembolleri kullanacağını kendi ortamınızın dokümantasyonundan elde etmeniz gerekecektir.
Yığın Boyutlandırma
Yığın boyutunun nasıl belirleneceği ile ilgili olarak, birçok takım zinciri, programınızın fonksiyon çağrısı ağaçlarını analiz ederek size maksimum yığın derinliği verebilir, özyineleme veya fonksiyon işaretçileri kullanmazsanız. Bunları kullanırsanız, yığın büyüklüğünü tahmin edip kardinal değerlerle önceden doldurma (belki ana sistemden önce giriş fonksiyonu aracılığıyla) ve ardından programınızın bir süre boyunca çalışıp çalışmadığını kontrol edin (maksimum değerin olduğu yer) son). Programınızı sınırlarını tam olarak uyguladıysanız, yığını küçültüp küçültemeyeceğinizi veya programınız çökerse veya kardinal değer kalmadıysa yığını arttırmanız ve yeniden denemeniz gerekeceğini oldukça doğru bir şekilde bilirsiniz.
Yığın Boyutlandırma
Yığın boyutunu belirlemek biraz daha uygulamaya bağlıdır. Başlatma sırasında yalnızca dinamik ayırma yaparsanız, başlangıç kodunuzda gereken boşluğu ekleyebilirsiniz (artı bellek yönetimi için bazı ek yükler). Hafıza yöneticinizin kaynağına erişiminiz varsa, ek yükün tam olarak ne olduğunu bilirsiniz ve muhtemelen kullanım bilgisini vermek için hafızayı dolaşmak için kod bile yazabilirsiniz. Dinamik çalışma zamanı belleği gerektiren uygulamalar için (örneğin, gelen ethernet çerçeveleri için arabellek ayırma) önerebileceğim en iyi şey yığın boyutunuzu dikkatlice bilemek ve Yığın'a yığın ve statikten sonra kalan her şeyi vermektir.
Son not (RTOS)
OP'nin sorusu yalın metal olarak etiketlendi, ancak RTOS'lar için bir not eklemek istiyorum. Genelde (her zaman?) Her görev / süreç / iş parçacığı (sadece burada basitlik için burada görev yazacağım), görev oluşturulduğunda bir yığın boyutu atanır, görev yığınlarına ek olarak, küçük bir işletim sistemi olabilir. yığın (kesintiler ve benzeri için kullanılır)
Görev muhasebe yapıları ve yığınlar bir yerden tahsis edilmek zorundadır ve bu genellikle uygulamanızın genel yığın alanından olacaktır. Bu durumlarda, başlangıç yığın boyutunuz çoğu zaman önemli olmaz, çünkü işletim sistemi yalnızca başlatma sırasında kullanır. Örneğin, bağlantı sırasında TÜM kalan boşluğun HEAP'a tahsis edildiğini ve ilk yığın göstergesinin yığının sonuna gelmek üzere yığının sonuna yerleştirileceğini, işletim sisteminin yığının başından başlayarak başlayacağını bilerek gördüm ve OS yığını, initial_sp yığınını terk etmeden hemen önce tahsis eder. Ardından, tüm alan görev yığınlarını ve diğer dinamik olarak ayrılmış belleği tahsis etmek için kullanılır.