Frage

Ich bin Programmierung in C für RAM-Mikrocontroller mit RTOS eingebettet beschränkt.

ich meinen Code zu kurz Funktionen regelmäßig brechen, aber jeder Funktionsaufruf erfordern, um mehr Stapelspeicher. Jede Aufgabe muss seinen Stack, und dies ist einer der bedeutenden Speicherkonsumenten im Projekt.

Gibt es eine Alternative den Code gut organisiert und lesbar zu halten, noch die Erinnerung bewahren?

War es hilfreich?

Lösung

Versuchen Sie, den Call-Stack flacher zu machen, so dass anstelle von a() b() ruft die c() ruft die d() nennt, haben a() Anruf b(), c() und d() selbst.

Wenn eine Funktion nur einmal referenziert wird, markieren Sie es inline (vorausgesetzt, Ihr Compiler dies unterstützt).

Andere Tipps

Es gibt 3 Komponenten auf Ihren Stack-Verbrauch:

  • Function Call Rückkehr Adressen
  • Function Call Parameter
  • Automatische (local) Variablen

Der Schlüssel Ihres Stackverbrauch möglichst gering zu halten ist Parameterübergabe und automatische Variablen zu minimieren. Der Platzbedarf der eigentlichen Funktionsaufruf selbst ist eher minimal.

Parameter

Eine Möglichkeit, die Parameter Problem zu beheben ist, eine Struktur zu übergeben (über Zeiger) anstelle einer großen Anzahl von Parametern ab.


foo(int a, int b, int c, int d)
{
...
   bar(int a, int b);
}

Sie hierzu statt:


struct my_params {
   int a;
   int b;
   int c;
   int d;
};
foo(struct my_params* p)
{
   ...
   bar(p);
};

Diese Strategie ist gut, wenn Sie eine Menge von Parametern überliefern. Wenn die Parameter alle verschieden sind, dann ist es vielleicht nicht gut für Sie arbeiten. Sie würden mit einer großen Struktur am Ende geführt wird um, dass viele verschiedene Parameter enthält.

Automatische Variablen (Einheimische)

Dies sind in der Regel der größte Verbraucher von Stapelspeicherplatz sein.

  • Arrays sind die Killer. Sie nicht definiert Arrays in Ihren lokalen Funktionen!
  • Minimieren Sie die Anzahl der lokalen Variablen.
  • Verwenden Sie die kleinste Art notwendig.
  • Wenn Neueintritt kein Problem ist, können Sie Modul statische Variablen verwenden.

Beachten Sie, dass, wenn Sie einfach alle lokalen Variablen aus lokalen Bereich bewegen Umfang zu Modul haben Sie jeden Raum nicht gespeichert. Sie gehandelt Stapelspeicher für Datensegment Raum.

Einige RTOS Support Thread-Lokalspeicher, der "globalen" Speicher auf einer Basis pro Thread zuordnet. Dies könnte Ihnen ermöglichen, mehrere unabhängige globale Variablen auf einer pro Aufgabe Basis zu haben, aber dies wird Ihr Code nicht so einfach machen.

Für den Fall, Sie vielen Hauptspeicher ersparen können, sondern nur einen kleinen Fetzen Stapel, schlage ich vor, die Bewertung statische Zuordnungen.

In C, alle Variablen in einer Funktion deklariert werden „automatisch verwaltet“, was bedeutet, dass sie auf dem Stapel zugeordnet sind.

Qualifikations die Erklärungen als „statisch“ speichert sie im Hauptspeicher statt auf dem Stapel. Sie verhalten sich im Grunde wie globale Variablen, aber immer noch können Sie die schlechten Gewohnheiten zu vermeiden, die mit überbeanspruchend Globals kommen. Sie können einen guten Fall machen für die Deklaration von großen, langlebigen Puffer / Variablen als statische Druck auf den Stapel zu reduzieren.

Beachten Sie, dass dies nicht gut funktioniert / überhaupt, wenn Ihre Anwendung multithreaded ist oder wenn Sie Rekursion.

Einschalten Optimierung, speziell aggressiven inlining. Der Compiler sollte in der Lage sein, Methoden Inline Anrufe zu minimieren. Je nach Compiler und die Optimierung Schalter Sie verwenden, Kennzeichnung einige Methoden wie inline helfen kann (oder es kann ignoriert werden).

Mit GCC, versuchen Sie, die "-finline-Funktionen" (oder O3) Flagge und möglicherweise das "-finline-limit = n" Flag.

Ein Trick, den ich irgendwo Inorder lesen Sie die Stapel Anforderungen des Codes in einem eingebetteten Setup zu bewerten ist der Stapelspeicher zu Beginn mit einem bekannten Muster (DEAD in hex ist mein Favorit) und lassen Sie das System Lauf für ein füllen während.

Nach einem normalen Lauf, lesen Sie den Stapelspeicher und sehen, wie viel von dem Stapelspeicher hat im Laufe des Betriebs nicht ersetzt. Design, um atleast 150% davon zu verlassen, um alle obsure Codepfade in Angriff zu nehmen, die nicht ausgeübt worden sein könnten.

Können Sie einige Ihrer lokalen Variablen von Globals ersetzen? Arrays können insbesondere auffressen Stapel.

Wenn es die Situation erlaubt Sie zwischen einigen diejenigen zwischen Funktionen einige Globals zu teilen, gibt es eine Chance, dass Sie Ihr Gedächtnis Fußdruck reduzieren.

Die Trade-off Kosten Komplexität erhöht und eine größere Gefahr von unerwünschten Nebenwirkungen zwischen den Funktionen vs einem möglicherweise kleineren Speicher Fußdruck.

Welche Art von Variablen haben Sie in Ihren Funktionen haben? Welche Größen und Grenzen reden wir?

Abhängig von Ihrem Compiler, und wie aggressiv Ihre Optimierungsmöglichkeiten sind, werden Sie Stackverbrauch für jede Funktion haben rufen Sie. So beginnen mit Ihnen wahrscheinlich die Tiefe Ihrer Funktionsaufrufe begrenzen müssen. Einige Compiler tun Verwendung springt anstatt Zweige für einfache Funktionen, die Stack-Verbrauch reduzieren. Natürlich können Sie das gleiche tun, indem Sie, sagen wir, einen Assembler Makro auf Ihre Funktionen zu springen, anstatt einer direkten Funktionsaufruf.

Wie in anderen Antworten erwähnt, inlining ist eine Option zur Verfügung, obwohl das auf Kosten von mehr Codegröße kommen wird.

Der andere Bereich, den Stapel isst ist die lokalen Parameter. Dieser Bereich Sie eine gewisse Kontrolle zu tun haben über. Mit Hilfe von (Dateiebene) Statik wird Stack Zuweisung an den Kosten Ihrer statischen RAM-Zuweisung vermeiden. Globals ebenfalls.

(wirklich) Extremfall können Sie mit einem Abkommen zur Funktionen kommen, die eine feste Anzahl von globalen Variablen als Zwischenspeicher anstelle von Einheimischen auf dem Stapel verwendet. Der schwierige Bit sorgt dafür, dass keine der Funktionen, die die gleichen Globals verwenden immer zur gleichen Zeit aufgerufen. (Daher die Konvention)

Wenn Sie brauchen, um Stapelspeicher zu bewahren sollten Sie entweder einen besseren Compiler oder mehr Speicher.

Ihre Software wird in der Regel wachsen (neue Funktionen, ...), also wenn Sie durch das Denken über ein Projekt starten haben, wie Stapelspeicher zu bewahren es von Anfang an zum Scheitern verurteilt ist.

Ja, das kann ein RTOS wirklich auffressen RAM für die Task-Stack-Nutzung. Meine Erfahrung ist, dass als neuer Benutzer eines RTOS, gibt es eine Tendenz, mehr Aufgaben als nötig zu verwenden.

Für ein eingebettetes System eines RTOS verwenden, kann RAM ein kostbares Gut sein. Um RAM zu erhalten, für die einfachen Funktionen kann es immer noch wirksam sein, um verschiedene Funktionen innerhalb einer Aufgabe zu implementieren, in Round-Robin-ausgeführt wird, mit einem kooperativen Multitasking-Design. So reduziert Gesamtzahl der Aufgaben.

Ich denke, man kann ein Problem werden, sich vorzustellen, die es gibt hier tut. Die meisten Compiler eigentlich nichts tun, wenn sie automaticic Variablen auf dem Stapel „zuweisen“.

Der Stapel wird zugewiesen vor „main ()“ ausgeführt wird. Wenn Sie Funktion b () aus der Funktion a () die Adresse des Speicherbereiches unmittelbar nach den letzten Variablen durch einen Aufruf wird verwendet, übergibt b (). Dies wird den Beginn der b () 's Stapel, wenn b () ruft dann Funktion c () dann c Stack beginnt nach der letzten automatischen Variablen von b () definiert.

Beachten Sie, dass der Stapelspeicher bereits vorhanden ist und zugeordnet ist, dass keine Initialisierung beteiligt Platz und die einzige Verarbeitung erfolgt ist, einen Stapelzeiger übergeben.

Die einzige Zeit, wird dies ein Problem sein würde, in der alle drei Funktionen große Mengen an Speicher verwenden den Stapel dann die Erinnerung an allen drei Funktionen accomadate hat. Versuchen Funktionen zu halten, die große Mengen an Speicher an der Unterseite des Aufrufstapel zuzuteilen d.h. nicht eine andere Funktion von ihnen nennen.

Ein weiterer Trick für Speicher constained Systeme ist der Speicher aufgeteilt Teile einer Funktion in separate Selbst hogging Funktionen enthalten sind.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top