Ich habe noch keinen Post gefunden, der ein ähnliches Szenario behandelt:
In einem Kommandozeilen-Unix-Programm für die Sonifikation bestimmter Gleitkommadatensätze, Ich habe eine main()
, die entweder liest aus einer Datei, deren Name als Programm argumant oder stdin
Umleitung (<)
oder Daten aus einem anderen Programm (|)
, abhängig von argc
. Solange argv[1]
ein Dateiname ist, kann ich die Ausführung sanft stoppen, indem ich die Eingabetaste drücke, die programmatisch eine Bedingung zum Ausblenden des Signals einstellt, die Audiounterroutine aufreinigt und regelmäßig beendet und das Programm beendet. Ich erreiche es durch Aufruf einer Funktion für nicht blockierende kbhit()
. Definition:Stoppen eines Unix-Programms mit der Tastatur, während der umgeleiteten Eingabe, ohne SIGINT, in C
int kbhit(void)
{
struct timeval tv;
fd_set read_fd;
tv.tv_sec = 0;
tv.tv_usec= 0;
FD_ZERO(&read_fd);
FD_SET(0, &read_fd);
if(select(1, &read_fd, NULL, NULL, &tv) == -1)
return 0;
if(FD_ISSET(0, &read_fd))
return 1;
return 0;
}
Wenn jedoch Eingang umgeleitet oder geleitet wird, verhindert kbhit()
dann von der Ausführung durch die Wiedergabe in dem Moment gestoppt es begonnen hat, da es 1
zurückgibt. Ich weiß nicht, wie ich damit umgehen soll, deshalb verwende ich SIGINT, was ich nicht so elegant finde. Hier ist der Code-Schnipsel:
//... ...
bool stop = false; //global variable
//... ...
if(argc == 1) stdr = true;//flag: reading from redirected or piped stdin (simplified)
//code for reading from file or stdin, using fscanf() ...
//code for initializing and starting audio process ...
//loop, during audio callback on a separate thread ...
while((player.totalFrames < player.totalSize) && !stop){
if(!stdr){ //(= reading from file)
if (kbhit()){
stop = true;
break;
}
}else{ //(= reading from redirected stdin)
if (signal(SIGINT, sig_handler) == SIG_ERR)
printf("\ncan't catch SIGINT\n");
}
}
if(stop){ … }//code for gently fading the signal and stopping the audio process
//cleanup and termination...
//... ...
Und hier ist die Standard-Signal-Handler, die stop
setzt Bedingung true
:
void sig_handler(int s)
{
if (s == SIGINT){
if(debug)printf("\ncaught SIGINT\n");
stop = true;
}
}
Gibt es eine elegantere Möglichkeit zu:
- senden & eine Nachricht von der Tastatur abfangen, während die Eingabe umgeleitet oder piped ist, um eine Programmbereinigung nach sich selbst zu ermöglichen und zu beenden (anders als mit SIGINT wie beschrieben) über)?
Wie sieht ein Code aus, der eine solche Meldung von Coputer KeyOard (während Umleitung oder Verrohrung) zulässt? Könnten die Argumente innerhalb von
kbhit()
irgendwie neu arrangiert werden, oder man muss in eine völlig andere Richtung gehen. Ich habe keine Ahnung welche?Wenn das möglich ist, würde ich mich über einen Vorschlag freuen. Danke im Voraus!
Warum möchten Sie SIGINT nicht verwenden? Genau dafür ist es da. – Gilles
Wie Sie im Beispielcode sehen können, verwende ich ** SIGINT und es funktioniert. Ich schaue nur, ob es etwas Eleganteres gibt. – user3078414
Hinweis: Verwenden Sie keine booleschen Typen und Konstanten von Homebrew. C hat einen Standard-boolena-Typ und 'stdbool.h' definiert die Konstanten auch als Makros. Benutze es! – Olaf