RT-Thread ist ein Open-Source-Echtzeitbetriebssystem, das zum Programmieren von Geräten für das Internet der Dinge (IoT) verwendet wird. FinSH ist die Befehlszeilenkomponente von RT-Thread und bietet eine Reihe von Betriebsschnittstellen, mit denen Benutzer ein Gerät über die Befehlszeile kontaktieren können. Es wird hauptsächlich zum Debuggen oder Anzeigen von Systeminformationen verwendet.
Üblicherweise wird das Entwicklungs-Debugging mit Hilfe von Hardware-Debuggern und printf
angezeigt Protokolle. In einigen Fällen sind diese beiden Methoden jedoch nicht sehr nützlich, da sie von dem abstrahieren, was ausgeführt wird, und sie können schwierig zu analysieren sein. RT-Thread ist jedoch ein Multi-Thread-System, was hilfreich ist, wenn Sie den Status eines laufenden Threads oder den aktuellen Status eines manuellen Steuersystems wissen möchten. Da es Multithreading ist, können Sie eine interaktive Shell haben, sodass Sie Befehle eingeben, eine Funktion direkt auf dem Gerät aufrufen können, um die benötigten Informationen zu erhalten, oder das Verhalten des Programms steuern können. Dies mag Ihnen gewöhnlich erscheinen, wenn Sie nur an moderne Betriebssysteme wie Linux oder BSD gewöhnt sind, aber für Hardware-Hacker ist dies ein großer Luxus und weit entfernt davon, serielle Kabel direkt auf Platinen zu verdrahten, um einen Blick auf Fehler zu werfen.
FinSH hat zwei Modi:
- Ein C-Sprachinterpretermodus, bekannt als C-Stil
- Ein traditioneller Befehlszeilenmodus, bekannt als
msh
(Modul-Shell)
Im C-Sprachinterpretationsmodus kann FinSH Ausdrücke parsen, die die meisten C-Sprachen ausführen, und über Funktionsaufrufe auf Funktionen und globale Variablen im System zugreifen. Es kann auch Variablen über die Befehlszeile erstellen.
In msh
Modus funktioniert FinSH ähnlich wie traditionelle Shells wie Bash.
Der GNU-Befehlsstandard
Weitere Linux-Ressourcen
- Spickzettel für Linux-Befehle
- Spickzettel für fortgeschrittene Linux-Befehle
- Kostenloser Online-Kurs:RHEL Technical Overview
- Spickzettel für Linux-Netzwerke
- SELinux-Spickzettel
- Spickzettel für allgemeine Linux-Befehle
- Was sind Linux-Container?
- Unsere neuesten Linux-Artikel
Bei der Entwicklung von FinSH haben wir gelernt, dass Sie sich mit den GNU-Befehlszeilenstandards vertraut machen müssen, bevor Sie eine Befehlszeilenanwendung schreiben können. Dieser Rahmen aus Standardverfahren trägt dazu bei, eine Benutzeroberfläche vertraut zu machen, sodass sich Entwickler bei der Verwendung wohl und produktiv fühlen.
Ein vollständiger GNU-Befehl besteht aus vier Hauptteilen:
- Befehlsname (ausführbar): Der Name des Kommandozeilenprogramms
- Unterbefehl: Der Unterfunktionsname des Befehlsprogramms
- Optionen: Konfigurationsoptionen für die Unterbefehlsfunktion
- Argumente: Die entsprechenden Argumente für die Konfigurationsoptionen des Unterbefehls function
Sie können dies mit jedem Befehl in Aktion sehen. Am Beispiel von Git:
git reset --hard HEAD~1
Was sich wie folgt aufschlüsselt:
Der ausführbare Befehl ist git , lautet der Unterbefehl reset , die verwendete Option ist --head , und das Argument ist HEAD~1 .
Ein weiteres Beispiel:
systemctl enable --now firewalld
Der ausführbare Befehl ist systemctl , der Unterbefehl ist enable , die Option ist --now , und das Argument ist firewalld .
Stellen Sie sich vor, Sie möchten mit RT-Thread ein Befehlszeilenprogramm schreiben, das den GNU-Standards entspricht. FinSH hat alles, was Sie brauchen, und führt Ihren Code wie erwartet aus. Besser noch, Sie können sich auf diese Konformität verlassen, sodass Sie Ihre bevorzugten Linux-Programme getrost portieren können.
Schreibe ein elegantes Kommandozeilenprogramm
Hier ist ein Beispiel dafür, wie RT-Thread einen Befehl ausführt, den RT-Thread-Entwickler jeden Tag verwenden.
usage: env.py package [-h] [--force-update] [--update] [--list] [--wizard]
[--upgrade] [--printenv]
optional arguments:
-h, --help show this help message and exit
--force-update force update and clean packages, install or remove the
packages by your settings in menuconfig
--update update packages, install or remove the packages by your
settings in menuconfig
--list list target packages
--wizard create a new package with wizard
--upgrade upgrade local packages list and ENV scripts from git repo
--printenv print environmental variables to check
Wie Sie sehen können, sieht es vertraut aus und verhält sich wie die meisten POSIX-Anwendungen, die Sie möglicherweise bereits unter Linux oder BSD ausführen. Hilfe wird bereitgestellt, wenn eine falsche oder unzureichende Syntax verwendet wird, sowohl lange als auch kurze Optionen werden unterstützt, und die allgemeine Benutzeroberfläche ist jedem vertraut, der ein Unix-Terminal verwendet hat.
Arten von Optionen
Es gibt viele verschiedene Arten von Optionen, die nach Länge in zwei Hauptkategorien unterteilt werden können:
- Kurze Optionen: Bestehen aus einem Bindestrich und einem einzelnen Buchstaben, z. B.
-h
Option inpkgs -h
- Lange Optionen: Bestehen aus zwei Bindestrichen plus Wörtern oder Buchstaben, z. B.
--target
Option inscons- --target-mdk5
Sie können diese Optionen in drei Kategorien einteilen, die dadurch bestimmt werden, ob sie Argumente haben:
- Keine Argumente: Der Option dürfen keine Argumente folgen
- Argumente müssen enthalten sein: Der Option müssen Argumente folgen
- Argumente optional: Argumente nach der Option sind erlaubt, aber nicht erforderlich
Wie Sie es von den meisten Linux-Befehlen erwarten würden, ist das Analysieren von FinSH-Optionen ziemlich flexibel. Es kann eine Option von einem Argument anhand eines Leerzeichens oder Gleichheitszeichens als Trennzeichen unterscheiden oder einfach die Option selbst extrahieren und davon ausgehen, dass das Folgende das Argument ist (mit anderen Worten, überhaupt kein Trennzeichen):
wavplay -v 50
wavplay -v50
wavplay --vol=50
Optparse verwenden
Wenn Sie jemals eine Befehlszeilenanwendung geschrieben haben, wissen Sie vielleicht, dass es im Allgemeinen eine Bibliothek oder ein Modul namens optparse für die Sprache Ihrer Wahl gibt. Es wird Programmierern zur Verfügung gestellt, damit Optionen (wie -v oder --verbose ), die als Teil eines Befehls eingegeben werden, können geparst werden in Bezug auf den Rest des Befehls. Es hilft Ihrem Code, eine Option aus einem Unterbefehl oder Argument zu erkennen.
Beim Schreiben eines Befehls für FinSH wird der optparse
Paket erwartet dieses Format:
MSH_CMD_EXPORT_ALIAS(pkgs, pkgs, this is test cmd.);
Sie können Optionen in der Lang- oder Kurzform oder in beiden implementieren. Zum Beispiel:
static struct optparse_long long_opts[] =
{
{"help" , 'h', OPTPARSE_NONE}, // Long command: help, corresponding to short command h, without arguments.
{"force-update", 0 , OPTPARSE_NONE}, // Long comman: force-update, without arguments
{"update" , 0 , OPTPARSE_NONE},
{"list" , 0 , OPTPARSE_NONE},
{"wizard" , 0 , OPTPARSE_NONE},
{"upgrade" , 0 , OPTPARSE_NONE},
{"printenv" , 0 , OPTPARSE_NONE},
{ NULL , 0 , OPTPARSE_NONE}
};
Nachdem die Optionen erstellt wurden, schreiben Sie den Befehl und die Anweisungen für jede Option und ihre Argumente:
static void usage(void)
{
rt_kprintf("usage: env.py package [-h] [--force-update] [--update] [--list] [--wizard]\n");
rt_kprintf(" [--upgrade] [--printenv]\n\n");
rt_kprintf("optional arguments:\n");
rt_kprintf(" -h, --help show this help message and exit\n");
rt_kprintf(" --force-update force update and clean packages, install or remove the\n");
rt_kprintf(" packages by your settings in menuconfig\n");
rt_kprintf(" --update update packages, install or remove the packages by your\n");
rt_kprintf(" settings in menuconfig\n");
rt_kprintf(" --list list target packages\n");
rt_kprintf(" --wizard create a new package with wizard\n");
rt_kprintf(" --upgrade upgrade local packages list and ENV scripts from git repo\n");
rt_kprintf(" --printenv print environmental variables to check\n");
}
Der nächste Schritt ist das Parsen. Während Sie seine Funktionen noch nicht implementieren können, ist der Rahmen des geparsten Codes derselbe:
int pkgs(int argc, char **argv)
{
int ch;
int option_index;
struct optparse options;
if(argc == 1)
{
usage();
return RT_EOK;
}
optparse_init(&options, argv);
while((ch = optparse_long(&options, long_opts, &option_index)) != -1)
{
ch = ch;
rt_kprintf("\n");
rt_kprintf("optopt = %c\n", options.optopt);
rt_kprintf("optarg = %s\n", options.optarg);
rt_kprintf("optind = %d\n", options.optind);
rt_kprintf("option_index = %d\n", option_index);
}
rt_kprintf("\n");
return RT_EOK;
}
Hier ist die Funktionskopfdatei:
#include "optparse.h"
#include "finsh.h"
Dann kompilieren und auf ein Gerät herunterladen.
Hardware-Hacking
Das Programmieren von Hardware kann einschüchternd wirken, aber mit IoT wird es immer üblicher. Nicht alles kann oder sollte auf einem Raspberry Pi ausgeführt werden, aber mit RT-Thread können Sie dank FinSH ein vertrautes Linux-Feeling beibehalten.
Wenn Sie neugierig auf Bare-Metal-Codierung sind, probieren Sie RT-Thread aus.