Hallo, hier möchte ich mal ein kleines Projekt vorstellen, das seit längerem bei mir in der "Schublade" liegt. Habe vor ca. 2 Jahren damit angefangen und es vor ca. 1 Jahr pausiert (mangels Zeit oder so). Werde vermutlich demnächst daran weiterarbeiten. Es handelt sich um ein (mangels Features noch nicht wirklich sinnvoll benutzbares) Multitasking Betriebssystem für ARM7 Prozessoren (ohne MMU) mit POSIX-API (jedoch natürlich nicht vollständig). Es hat doch recht viele Features deswegen, so denke ich, ist es für den Ein oder Anderen sicher einen Blick wert. An Prozessoren unterstützt es den LPC2478, entwickelt habe ich es unter dem in http://gsg-elektronik.de/?id=64 vorgestelltem Board, auf dem es unverändert läuft. Ich habe stets großen Wert darauf gelegt, dass es sich ohne viel Aufwand auf andere Systeme der ARM7 Architektur portieren lässt (dabei kann ich auch gerne behilflich sein). Es besteht aus einem Kernel, der im Flash der CPU sitzt, oder zumindest direkt vom Bootloader ausgeführt wird, und Userspace-Programmen, die auf einer ext2-formatierten SD Karte sind (als ELF) und vom Kernel ausgeführt werden. An Userspace-Programmen sind bisher nur /bin/sh (eine sehr rudimentäre Shell, damit der Benutzer (z.B. über die UART) sagen kann, was er will), /bin/top (ein Programm um Prozesslisten und weitere Informationen vom Scheduler abzurufen), und /sbin/init (das wie in POSIX definiert einige Userspace-seitige Initialisierungen übernimmt und eine Shell ausführt). Die libc implementiert nicht wenige Funktionen für Userspace Programme, die ich nun aufliste. Nicht in POSIX spezifizierte sind in Klammern. fcntl: open poll: poll sched: sched_yield, (sched_info, sched_list) signal: kill, sigaction, raise, signal stdio: fclose, fopen, fread, fwrite, putchar, fputs, puts, perror, printf, sprintf, fprintf, vfprintf, vsprintf stdlib: atexit, exit, _Exit, malloc, calloc, free, realloc, (alloca), abort, qsort, strtol, atoi string: memcpy, memmove, memset, strchr, strcmp, strcpy, strdup, strlen, strncmp, strerror unistd: _exit, fork, execve, close, read, write, getpid, getppid, setsid sys/mman: mmap, munmap sys/wait: waitpid, wait (teils jedoch eher unvollständige Implementationen, nicht selten aufgrund Limitierungen des Kernels) Eher eine Vielfalt an interessanten Features bietet dagegen der Kernel: - Bei Absturz eines Programms Anzeige der GPRs, eines Function Call Stacktrace, bei Userspace-Programmen inklusive Symbolnamen - Triviale Sicherheitsfeatures wie z.B. Überprüfen von Userspace-Pointern bei Syscalls, Nullen frischer Userspace Pages, ... - Support des Hardware Watchdog Timer um System automatisch neu zu booten falls es abstürzt - MMC/SD-Treiber (jedoch Software-MCI, über GPIOs direkt oder SPI) - UART (als Konsole) - Im Kernel einkompiliertes Dateisystem (damals zum Testen entwickelt, bevor Unterstützung für SD-Karten vorhanden war) - IBM PC Partitionstabelle im MBR - Dateisysteme ext2 und minix - VFS unterstützt "Baum" an Mounts (so wie z.B. bei Linux), z.B. kann /mnt auf anderes Dateisystem verweißen als das Komplement von /mnt im root-Verzeichnis - Effiziente APIs im Kernel zum einfachen Hinzufügen neuer Dateisystemtreiber, Gerätetreiber, etc. - ELF Unterstützung inkl. Symboltable, Anpassung der GOT (Zwangsweise, da das Multitasking-Prinzip sonst nicht umsetzbar wäre) - Falls vorhanden, können LEDs genutzt werden, um CPU-Auslastung (und weiteres) anzuzeigen - Speicherverwaltung die mehrere Speicherareale nutzen kann (um sowohl internen als auch externen Speicher zu nutzen) - Scheduler, der einiges an Statistik sammelt (Ausführungszeiten, somit CPU-Auslastung; Load Averages); einen Algorithmus für kurze Interrupt-Response-Zeiten hat; POSIX-poll() Funktionen für effizientes Warten; Unterstützung für Signale - Session/Terminal-Unterstützung (jedoch eher rudimentär) Das Multitasking ist wegen der fehlenden MMU nicht effizient exakt nach POSIX implementierbar, jedoch hinreichend für eigentlich alle Anwendungen. fork() legt, natürlich, keinen neuen Address-Space an (geht ja nicht). Der alte Address-Space wird also beibehalten, solange bis mit execve() ein neues Programm für diesen Prozess ausgeführt wird. fork() legt also eher eine Art Thread an, als einen Prozess (Eigentlich etwas zwischen Thread und Prozess, da z.B. Filedescriptors geklont werden). Das ist das genutzte Prinzip des Multitaskings. Es fehlt sämtliches an Dokumentation, schwer zu "bedienen" dürfte es dennoch nicht sein. In misc/ befindet sich ein Skript um eine ARM-Toolchain zu erstellen. Das ist eigentlich alles was man braucht um es zu kompilieren. Zum Kompilieren des Kernels muss man zumindest die sys/conf anpassen, dann "make buildkernel" ausführen. Die libc sowie die Userspace-Programme sind mit "make buildworld" zu kompilieren. "make installworld" kopiert sie in ein Verzeichnis, dessen Inhalt man direkt in das root-Dateisystem für das Betriebssystem kopieren kann (also auf die SD-Karte). Vielleicht bringt es ja was. Für Fragen und Ähnliches bin ich gerne da. Gruß, Euer Alex
Für wen oder was hast du das geschrieben?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.