Lightweight (Teilmenge) der Standard-C-Bibliothek (ANSI-C-Bibliothek)

Ich portiere die Standard-C-Bibliothek für Bare-Metal-Betriebssysteme (ARM Cortex-M4, ARM GCC). Ich möchte Funktionen wie strlen, sprintf (und vielleicht eine Speicherzuweisung) usw. haben.

Ich habe PDCLib und Newlib portiert. Newlib ist nicht leicht (und versuchen Sie, Dateioperationen usw. zu implementieren). PDCLib befindet sich nicht in aktiver Entwicklung.

Also, ich will genau Microlib . Aber es ist nicht für GCC und Closed Source.

Gibt es hierfür Alternativen? Und gibt es einige "Bare-Metal-Teilmengen" der Standard-C-Bibliothek?

Ich hatte gute Ergebnisse mit newlib-nano. Wenn Sie kleinere wollen, fürchte ich, müssen Sie den Keil-Weg gehen und das große Geld bezahlen.

Antworten (2)

Wenn ich eine wirklich leichte (und/oder Thread-sichere) Bibliothek haben möchte, schreibe ich normalerweise meine eigene. Es ist nicht schwer zu tun.

Da Sie über einen "Speicherzuordner" sprechen, lassen Sie mich vorschlagen, dass ein malloc()/free-Paar trivial zu schreiben ist - vielleicht ein paar Dutzend Zeilen:

#define STATUSFREE 0
#define STATUSUSED 1
struct tag {
    struct tag * next;
    int status;
};
struct tag * heap;
void free( void * p ) {
    struct tag * ptag= ((struct tag *)p) - 1;
        ptag->status= STATUSFREE;
}
void * malloc( size_t s ) {
    struct tag *ptag, *pnext;
        for ( ptag= heap; ptag != NULL; ptag= ptag->next )
            if (ptag->status == STATUSFREE) {
                for ( pnext= ptag->next; pnext->status == STATUSFREE; pnext= pnext->next )
                    ;
                if ( s <= (size_t) (((char *) pnext) - (char *) (ptag+1)) ) {
                    if ( s <= (size_t) (((char *) pnext) - (char *) (ptag+2)) ) {
                        ptag->next= (struct tag *) (s + (char *) (ptag+1));
                        ptag->next->status= STATUSFREE;
                        ptag->next->next= pnext;
                    } else
                        ptag->next= pnext;
                    ptag->status= STATUSUSED;
                    return ptag+1;
                }
                ptag->next= pnext;
            }
    return NULL;
}

Sie initialisieren es auf folgende Weise. Richten Sie zunächst einen festen Speicherblock mit einer Standard-Array-Zuweisung wie dieser ein:

static char mspace[1000];

Das kann in ein Modul gesteckt werden, das Sie schreiben. Es sollte natürlich als statische Lebensdauer zugewiesen werden.

Dann machst du woanders (wie in main()) Folgendes:

((struct tag *) &mspace[0])->status= STATUSFREE;
((struct tag *) &mspace[0])->next= &((struct tag *) &mspace[sizeof(mspace)])[-1];
((struct tag *) &mspace[sizeof(mspace)])[-1].status= STATUSUSED;
((struct tag *) &mspace[sizeof(mspace)])[-1].next= NULL;
heap= (struct tag *) &mspace[0];

Es ist sehr schnell und sehr einfach.

strlen() ist natürlich viel einfacher und dafür finden Sie alle Arten von Implementierungen im Web.

Der Rest? Ich würde empfehlen, dass Sie diese auch schreiben. Ein sehr, sehr hilfreiches Buch hier ist "The Standard C Library" von PJ Plauger (einer der Gründer von Whitesmiths LTD - Compiler Company). Holen Sie sich einfach eine Kopie. Sie werden es nicht bereuen. Es deckt Dinge wie sprintf() für Sie ab, was viel komplizierter ist und möglicherweise die Behandlung mit Gleitkommawerten bei der Konvertierung für die Ausgabe beinhaltet. (Wenn Sie sprintf() neu erstellen, werden Sie als Ergebnis davon viel Code einschleppen – aber es wird nur benötigt, wenn Sie eine so leistungsstarke Bibliotheksfunktion wünschen.)

Vielen Dank! Haben Sie Repositories (denn gut gepflegter Code mit Tests ist auch gut :-))?
@Kuraga Da ich seit Jahrzehnten Embedded-Arbeiten mache, einschließlich des Schreibens des gesamten Betriebssystemcodes (den ich jetzt oft in zwei Tagen oder weniger auf einem bestimmten System von Grund auf neu schreiben kann), habe ich viel Quellcode von verschiedenen Projekte, die ich hier behalte. Wenn ich etwas brauche, durchsuche ich die Projekte und extrahiere die Teile, die ich brauche. Jede Bibliothek ist jedoch für das Projekt benutzerdefiniert. Der Grund liegt zum Teil darin, dass einige meiner Arbeiten medizinischer Natur sind und JEDE Codezeile gründlich überprüft werden muss. Das Einwerfen von unbenutztem Code ist "schlecht". Ich verwende fast nie die C-Bibliotheken von Compilern.
@Kuraga Code, den ich schreibe, funktioniert in einigen Fällen noch nach 30 Jahren. Ausgefüllte Bewerbungen schreibe ich einfach. Ich habe einen Anruf von einem Kunden erhalten, der meine Software seit 20 Jahren bei Zehntausenden seiner eigenen Kunden verwendet und mich anruft, um mir mitzuteilen, dass bei all dem kein einziger bestätigter Fehler in meinem Code gefunden wurde Zeit. Aber ich hatte einfach nicht die Zeit, meinen Code zu organisieren und zu dokumentieren, damit andere ihn gut verwenden können. Das erfordert viel zusätzliche Anstrengung UND Denkzeit, um sicherzustellen, dass ich alles weitergebe, was für andere erforderlich wäre, um es zu verwenden.
Warum sollten Sie sich überhaupt mit malloc beschäftigen, wenn es doch um Bare-Metal-Embedded-Systeme geht? malloc macht keinen Sinn, siehe this .
@Lundin Meine Antwort bezog sich auf eine bestimmte Frage des OP. Stellen Sie dem OP Ihre Frage.
@jonk Niemand außer dir hat Malloc erwähnt. Das Ausrollen Ihrer eigenen Bibliothek ist eine mögliche Antwort auf die Frage des OP, aber es gibt keinen Grund, warum Sie Funktionen aus der Standardbibliothek implementieren würden, die in Bare-Metal-Embedded-Systemen keinen Sinn machen.
@Lundin Ich habe "Speicherzuweisung" als suggestiv interpretiert.

Sie sollten einen Blick auf musl werfen .

Es ist leicht und Open Source und für eingebettete Anwendungen vorgesehen.
Ich weiß nicht, ob das genau deinen Anforderungen entspricht.

Danke für die Antwort! Nein, es ist Linux-abhängig, aber kein Bare Metal.
@ Kuraga Entschuldigung ...