RT-Thread è un sistema operativo in tempo reale open source utilizzato per la programmazione di dispositivi Internet of Things (IoT). FinSH è il componente della riga di comando di RT-Thread e fornisce una serie di interfacce operative che consentono agli utenti di contattare un dispositivo dalla riga di comando. Viene utilizzato principalmente per eseguire il debug o visualizzare le informazioni di sistema.
Di solito, il debug di sviluppo viene visualizzato utilizzando i debugger hardware e printf
registri. In alcuni casi, tuttavia, questi due metodi non sono molto utili perché sono astratti da ciò che è in esecuzione e possono essere difficili da analizzare. RT-Thread è un sistema multi-thread, tuttavia, utile quando si desidera conoscere lo stato di un thread in esecuzione o lo stato corrente di un sistema di controllo manuale. Poiché è multi-thread, puoi avere una shell interattiva, quindi puoi inserire comandi, chiamare una funzione direttamente sul dispositivo per ottenere le informazioni di cui hai bisogno o controllare il comportamento del programma. Questo può sembrare normale per te se sei abituato solo a sistemi operativi moderni come Linux o BSD, ma per gli hacker hardware questo è un lusso profondo e ben lontano dal collegare i cavi seriali direttamente alle schede per intravedere gli errori.
FinSH ha due modalità:
- Una modalità interprete in linguaggio C, nota come stile c
- Una modalità a riga di comando tradizionale, nota come
msh
(shell del modulo)
Nella modalità di interpretazione del linguaggio C, FinSH può analizzare le espressioni che eseguono la maggior parte del linguaggio C e accedere a funzioni e variabili globali sul sistema utilizzando chiamate di funzione. Può anche creare variabili dalla riga di comando.
In msh
modalità, FinSH funziona in modo simile alle shell tradizionali come Bash.
Lo standard dei comandi GNU
Più risorse Linux
- Comandi Linux cheat sheet
- Cheat sheet sui comandi avanzati di Linux
- Corso online gratuito:Panoramica tecnica RHEL
- Cheat sheet della rete Linux
- Cheat sheet di SELinux
- Cheat sheet dei comandi comuni di Linux
- Cosa sono i container Linux?
- I nostri ultimi articoli su Linux
Durante lo sviluppo di FinSH, abbiamo appreso che prima di poter scrivere un'applicazione a riga di comando, è necessario acquisire familiarità con gli standard a riga di comando GNU. Questo framework di pratiche standard aiuta a portare familiarità a un'interfaccia, che aiuta gli sviluppatori a sentirsi a proprio agio e produttivi durante l'utilizzo.
Un comando GNU completo è composto da quattro parti principali:
- Nome comando (eseguibile): Il nome del programma a riga di comando
- Sottocomando: Il nome della sottofunzione del programma di comando
- Opzioni: Opzioni di configurazione per la funzione di sottocomando
- Argomenti: Gli argomenti corrispondenti per le opzioni di configurazione della funzione di sottocomando
Puoi vederlo in azione con qualsiasi comando. Prendendo Git come esempio:
git reset --hard HEAD~1
Che si suddivide come:
Il comando eseguibile è git , il sottocomando è reimposta , l'opzione utilizzata è --head e l'argomento è HEAD~1 .
Un altro esempio:
systemctl enable --now firewalld
Il comando eseguibile è systemctl , il sottocomando è abilita , l'opzione è --ora e l'argomento è firewalld .
Immagina di voler scrivere un programma a riga di comando conforme agli standard GNU utilizzando RT-Thread. FinSH ha tutto ciò di cui hai bisogno ed eseguirà il tuo codice come previsto. Meglio ancora, puoi fare affidamento su questa conformità in modo da poter trasferire con sicurezza i tuoi programmi Linux preferiti.
Scrivi un elegante programma da riga di comando
Ecco un esempio di RT-Thread che esegue un comando che gli sviluppatori di RT-Thread utilizzano ogni giorno.
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
Come puoi vedere, sembra familiare e si comporta come la maggior parte delle applicazioni POSIX che potresti già eseguire su Linux o BSD. Viene fornita assistenza quando viene utilizzata una sintassi errata o insufficiente, sono supportate sia le opzioni lunghe che quelle brevi e l'interfaccia utente generale è familiare a chiunque abbia utilizzato un terminale Unix.
Tipi di opzioni
Esistono molti tipi diversi di opzioni e possono essere divise in due categorie principali in base alla lunghezza:
- Opzioni brevi: Sono costituiti da un trattino più una singola lettera, ad esempio il
-h
opzione inpkgs -h
- Opzioni lunghe: Consiste di due trattini più parole o lettere, ad esempio il
--target
opzione inscons- --target-mdk5
Puoi dividere queste opzioni in tre categorie, determinate dal fatto che abbiano o meno argomenti:
- Nessun argomento: L'opzione non può essere seguita da argomenti
- Gli argomenti devono essere inclusi: L'opzione deve essere seguita da argomenti
- Argomenti facoltativi: Gli argomenti dopo l'opzione sono consentiti ma non obbligatori
Come ti aspetteresti dalla maggior parte dei comandi Linux, l'analisi delle opzioni FinSH è piuttosto flessibile. Può distinguere un'opzione da un argomento basato su uno spazio o un segno di uguale come delimitatore, o semplicemente estraendo l'opzione stessa e assumendo che quello che segue sia l'argomento (in altre parole, nessun delimitatore):
wavplay -v 50
wavplay -v50
wavplay --vol=50
Utilizzo di optparse
Se hai mai scritto un'applicazione a riga di comando, potresti sapere che generalmente esiste una libreria o un modulo per il tuo linguaggio preferito chiamato optparse. Viene fornito ai programmatori in modo che le opzioni (come -v o --verboso ) immesso come parte di un comando può essere analizzato in relazione al resto del comando. È ciò che aiuta il tuo codice a riconoscere un'opzione da un sottocomando o da un argomento.
Quando si scrive un comando per FinSH, optparse
il pacchetto prevede questo formato:
MSH_CMD_EXPORT_ALIAS(pkgs, pkgs, this is test cmd.);
Puoi implementare le opzioni usando la forma lunga o corta, o entrambe. Ad esempio:
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}
};
Dopo aver creato le opzioni, scrivi il comando e le istruzioni per ciascuna opzione e i suoi argomenti:
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");
}
Il passaggio successivo è l'analisi. Sebbene non sia ancora possibile implementare le sue funzioni, il framework del codice analizzato è lo stesso:
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;
}
Ecco il file head della funzione:
#include "optparse.h"
#include "finsh.h"
Quindi, compila e scarica su un dispositivo.
Hacking hardware
L'hardware di programmazione può sembrare intimidatorio, ma con l'IoT sta diventando sempre più comune. Non tutto può o deve essere eseguito su un Raspberry Pi, ma con RT-Thread puoi mantenere una sensazione familiare di Linux, grazie a FinSH.
Se sei curioso di scrivere codice su bare metal, prova RT-Thread.