2017-05-21 7 views
0

Ich habe diese Frage, die ich weiter unten vereinfachen:C Linux-Signale und Funktionen

#include <stdio.h> 
#include <signal.h> 

int main(void) { 
    signal(SIGALRM, &INThandler); 

    //get menu options which Im not going to put here 
    game(...stuff...); 
} 

void game(..stuff...) { 
    //do the game stuff AND set an alarm() 
} 

void INThandler(int sig) { 
    system("clear"); 
    printf("Time is up!\n"); 
    //I WANT game() TO STOP WHICH WILL EXIT TO MAIN WHERE MORE STUFF IS HAPPENING 
} 

Im Spiel() Ich habe

while(counter <= amount) 

Also ich die Variablen Zähler und Menge passieren wollte in INThandler, damit ich sie ändern kann, also ist die Bedingung falsch, jedoch wird INThandler nur aufgerufen, wenn der Alarm auf 0 steht und nicht mit Parametern aufgerufen wird. Spiel() geht weiter und ich will es nicht. Wenn es einen besseren Weg gibt, sag es mir bitte.

+0

Was ist das Problem? Wie übergebe ich Parameter oder die Funktion, die nur einmal aufgerufen wird? –

+0

Beachten Sie, dass Sie nur async-signalsichere Funktionen innerhalb eines Signal-Handlers aufrufen können. [Siehe den POSIX-Standard für eine Erklärung und die spezifizierte Liste von Funktionen, die aufgerufen werden können] (http://pubs.opengroup.org/onlinepubs/9699919799/functs/V2_chap02.html#tag_15_04_03). Und 'system()' und 'printf()' sind * nicht * async-signalsicher. Darüber hinaus fehlt Linux die POSIX-Kompatibilität, da 'fork()' auf Linux nicht async-signalsicher ist. Daher müssen Sie 'posix_spawn()' verwenden, um völlig sicher zu sein, obwohl dies für Anwendungen mit einem einzigen Thread wahrscheinlich nicht der Fall ist ein Problem mit 'fork()'. –

Antwort

1

Verwenden Sie globale Variablen für Zähler und Betrag?

0

Wenn eine Funktion aufgerufen wird und diese Funktion Variablen enthält, werden diese Variablen auf dem Stapel zugeordnet. Wenn Sie eine globale Variable definieren, wird sie stattdessen beim Laden des Programms zugewiesen. Ihr Signalhandler sollte Zugriff auf diese Variablen haben.

#include <stdio.h> 
#include <signal.h> 
#include <stdlib.h> //Also include this, needed for exit(returncode) 

int counter; //Not inside any function 
int amount; //All functions may access these 

int main(void) { 
    signal(SIGALRM, &INThandler); 

    //get menu options which Im not going to put here 
    game(...stuff...); 
} 

void game(..stuff...) { 
    //do the game stuff AND set an alarm() 
} 

void INThandler(int sig) { 
    //Do stuff with counter and amount 
    //system("clear"); I recommend that you do not use system to clear the screen, system(command) is inefficient. 
    printf("\033[H\033[JTime is up!\n"); 
    //Do that extra stuff you want to do in main here, then 
    exit(0); 
} 

Noch ein Hinweis: nach Signal (2) im Linux-Programmierhandbuch:

Die einzige tragbare Verwendung von Signal() ist ein Signal, Disposition zu SIG_DFL oder SIG_IGN einzustellen. Die Semantik, wenn signal() verwendet wird, um einen Signalhandler zu etablieren, variiert zwischen den Systemen (und POSIX.1 erlaubt explizit diese Variante); Verwenden Sie es nicht für diesen Zweck.

POSIX.1 löste die Portabilität durch Angabe von sigaction (2), bietet explizite Kontrolle der Semantik, wenn ein Signalhandler aufgerufen wird; Verwenden Sie diese Schnittstelle anstelle von signal().

Um ein Signal-Handler sigaction,

#include <signal.h> 

int main(){ 
    const struct sigaction saSIGALRM = { 
     .sa_handler = mySignalHandler, //replace this with your signal handler, it takes the same parameters as using signal() 
    }; 
    sigaction(SIGALRM, &saSIGALRM, 0); 
} 

Es ist einfacher, als es aussieht zu registrieren. Denken Sie daran, dass Computer heute wegen ineffizienter Programmierung langsam sind. Bitte, bitte, bitte, für effiziente Programme, verwenden Sie diese stattdessen.

Click here for more cool things sigaction can do, along with why not to use signal()