2010-12-16 14 views
4

ich herauszufinden, wie Signale in C arbeiten Hier ist eines der Beispiele aus alten Prüfungen abgelegt:Signal in C Handhabung

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

//#include <sys/types.h> 

void handler1(int sig) { 
printf("Phantom"); 
exit(0); 
} 
int main() 
{ 
    pid_t pid1; 
    signal(SIGUSR1, handler1); //installing signal handler 
    if((pid1 = fork()) == 0) { //forking 
     printf("Ghost"); 
     exit(0); 
    } 
    kill(pid1, SIGUSR1); 
    printf("Ninja"); 
    return 0; 
} 

Bisher GCC mir zwei Antworten Ghost Ninja & Ninja Phantom gibt. Könnte es Ghost Phantom Ninja oder eine andere Kombination aus 3 Namen produzieren?

Ein Weg, ich sehe es möglicherweise drei Namen produzieren könnte, ist: Gabel, lief in Kind, Druck Ghost, Ausgang (0) => in Parent, Annahme-/Prozesssignal und von Signal-Handler Druck Phantom, tötet Kind, druckt Ninja. Aber ich bin mir nicht sicher, ob meine "Theorie" Bestand hat.

Würde auch die kill(pid1, SIGUSR1)handler() aufrufen?

Danke!

+0

Keine Antwort auf die Frage als solche, aber Sie müssen ** nie ** printf() in einem Signalhandler aufrufen. – JeremyP

Antwort

5

Lassen Sie uns diese Zeile für Zeile untersuchen. Richten Sie einen Signalhandler ein und dann fork. Das Kind druckt "Ghost" und wird beendet. Der Elternteil lässt das Kind "Phantom" drucken und beenden. Dann druckt die Eltern "Ninja".

Sie haben also wirklich eine Race Condition. Wenn die Eltern ihre SIGUSR1, bevor das Kind prints „Ghost“ feuert, dann werden Sie Phantom Ninja bekommen, oder vielleicht Ninja Phantom (tut Block töten?)

Aber, wenn Sie nicht das Signal aus in der Zeit erhalten Sie dann werde Ghost Ninja bekommen, wenn das Kind vor den Elternsignalen fertig ist. Ich glaube nicht, dass das Gegenteil möglich ist.

Nun ist es denkbar, dass das Signal genau auf Zeit sein könnte, zwischen den printf und den exit, wobei in diesem Fall Ghost würde beenden, gefolgt von Phantom dann Ninja zu schlagen - oder umgekehrt wieder, denke ich.

Es ist wirklich knifflig und empfindlich auf OS Timing.

@Everyone - nicht getestet! Fühlen Sie sich frei, mir zu widersprechen, aber ich werde ebenso interessiert sein, warum wie das OP zu wissen.

+0

"Aber wenn du das Signal nicht rechtzeitig abschalten kannst, bekommst du Ghost Ninja, wenn das Kind fertig ist, bevor die Eltern signalisieren. Ich glaube nicht, dass das Gegenteil möglich ist." Wenn das Kind aussteigt, wird der Elternteil fortfahren zu töten oder wird er zuerst das Signal vom Hundeführer akzeptieren? – newprint

1

Ermöglicht die Zeilen mit Zeilennummern zuerst markiert wie folgt:

signal(SIGUSR1, handler1); //installing signal handler ---- 1 
    if((pid1 = fork()) == 0) { //forking    ---- 2 
     printf("Ghost");        ---- 3 
     exit(0);          ---- 4 
} 
    kill(pid1, SIGUSR1);        ---- 5 
    printf("Ninja");         ---- 6 

nun mit dem obigen Code, wenn Kind zuerst und ausführt, wenn 3 zuerst ausgeführt wird, dann Kind suspendiert und Eltern beginnen Ausführen mit 5. Dies wird GhostPhantomNinja

jedoch eine bestimmte Reihenfolge kann nicht bestimmt werden.

0

Sie haben hier zwei nicht deterministische Faktoren, die beide vom Betriebssystem abhängen: Wann wird die Kontextumschaltung stattfinden und wann wird das Signal eintreffen?

Da Sie diese nicht kontrollieren können, würde ich antworten, dass jede Bestellung möglich ist. Versuchen Sie, wait() zwischen den Befehl einzufügen und sehen Sie, ob Sie die gewünschten Ergebnisse erhalten.

0
//#include <sys/types.h> 
#include<stdlib.h> 
void handler1(int sig) { 
printf("Phantom\n"); 
waitpid(-1,NULL,0); 
//sexit(0); 
} 
int main() 
{ 
    pid_t pid1; 
    signal(SIGUSR1, handler1); //installing signal handler 
     printf("my pid is %d ha ha parent..\n",getpid()); 
    //if((pid1 = fork()) == 0) { //forking 
     pid1=fork(); 
     if(pid1==0)//in childe processs 
     { 
    printf("my pid is %d ha ha child..\n",getpid()); 
     printf("Ghost\n"); 
     sleep(6); 
     exit(0); 
    } 
    else{ 
    //sleep(4); 
    kill(pid1, SIGUSR1); 
    sleep(3); 
    printf("Ninja\n"); 
    return 0; 
} 
} 
+0

probiere das aus .. nutze schlaf wie ich es benutzt habe dann verstehe wie das os funktioniert, ich meine wie der scheduler funktioniert .. –