2010-09-23 5 views
5

Ich habe versucht herauszufinden, ob dies möglich ist, so wie ich es gemacht habe oder nicht. Dieses Programm sollte einen untergeordneten Prozess forcieren, der das Drucken in STDOUT wiederholt, und das übergeordnete Element sollte beendet werden, um die Terminal-Eingabeaufforderung zurückzugeben. Das Kind sollte dann darauf warten, dass SIGINT ihm sagt, wann es geschlossen werden soll. Ich erinnere mich jedoch daran, dass SIGINT nur an Prozesse im Vordergrund gesendet wird, was erklärt, warum mein verlassenes Kind nicht von STRG + C beeinflusst wird. Gibt es eine Möglichkeit, das verlassene Kind entweder dazu zu bringen, ein vom Terminal gesendetes Signal zu empfangen, oder einen Systemaufruf im Terminal, um es in den Vordergrund zu bringen, wo es SIGINT empfangen kann? Oder ist meine Suche hoffnungslos?Problem beim Senden des Signals an den untergeordneten Prozess in C

Code:

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <sys/wait.h> 
#include <sys/types.h> 

/* signal handler for the child process */ 
void catchInt (int signum) 
{ 
printf("\nMy sincerest apologies, master\n"); 
    exit(0); 
} 

/* signal handler for the parent process */ 
void ignoreInt (int signum) 
{ 
/* prevent any extra output from being printed */ 
fflush(stdout); 
/* wait for child to apologize before replying */ 
wait(NULL); 
printf("You're welcome\n"); 
exit(0); 
} 

/* signal handler for the child's alarm */ 
void catchAlarm (int signum) 
{ 
printf("It's great to be alive\n"); 
/* reset the alarm */ 
signal(SIGALRM, catchAlarm); 
alarm(3); 
} 

int main() { 

pid_t pid; 

/* fork process */ 
pid = fork(); 
if (pid < 0) /* error handler */ 
{ 
    fprintf(stderr, "Fork Failed"); 
    exit(-1); 
} 

/* child */ 
else if (pid == 0) 
{ 
    printf("It's great to be alive\n"); 
    /* catch SIGINT and handle as the child should */ 
    signal(SIGINT, catchInt); 
    /* catch SIGALRM being sent by alarm() */ 
    signal(SIGALRM, catchAlarm); 
    /* set alarm for 3 seconds */ 
    alarm(3); 
    for (;;) 
    { 
    printf("I have 42001 children and not one comes to visit\n"); 
    usleep(500000); 
    } 
} 

/* parent */ 
else 
{ 
    /* exit to abandon child process in the background */ 
    exit(0); 
} 

return(0); 
} 

Antwort

2

Wenn Sie möchten, dass Ihr Kind SIGINT empfängt, wenn das Interrupt-Zeichen auf dem steuernden Terminal getroffen wird, muss es in der Vordergrundprozessgruppe sein. Sie können dies erreichen:

int ctty = open("/dev/tty", O_RDONLY); 
while (tcgetpgrp(ctty) == getpgrp()) 
    usleep(100000); 
setpgid(0, tcgetpgrp(ctty)); 
close(ctty); 

(Sie müssen warten, bis die Shell die Vordergrund Prozessgruppe nach den Eltern Ausfahrt ändert, obwohl - ich bin von einer besseren Art und Weise nicht sicher, dass zu tun, als in einer Schleife dreht, ., wie im Beispiel Vorschläge begrüßen ...)


PS: beachten Sie, dass der Vordergrundprozess Gruppe jederzeit ändern kann - zum Beispiel, wenn ein anderer Prozess von der Shell ausgeführt wird. Ich bin mir nicht sicher, was genau dein Endziel ist, aber vielleicht gibt es einen besseren Weg, es zu tun, was auch immer es ist.

+0

Das funktioniert eigentlich perfekt! Ich muss mehr in Prozessgruppen schauen. Vielen Dank! – JKomusin

+0

@JKomusin: Es ist nicht wirklich eine perfekt robuste Lösung, siehe Update. – caf

1

können Sie den kill Befehl verwenden, um ein Signal zu einer bestimmten Vorgangsnummer zu senden:

kill -2 12345 

Natürlich hilft es, wenn Sie Ihren Code identifiziert, welche PID zu töten (Das Kind sollte seine PID melden, wenn es mit dem Schleifen beginnt. Aber mit nur trivialen Änderungen (wie das Auslassen der unbenutzten Funktion ignoreInt() und das Melden der PID des untergeordneten Prozesses) funktionierte es wie geschrieben - und der Befehl kill hat auch daran gearbeitet.

Compressed Code:

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

static void catchInt(int signum) 
{ 
    printf("\nMy sincerest apologies, master (%d)\n", signum); 
    exit(0); 
} 

static void catchAlarm(int signum) 
{ 
    printf("It's great to be alive (%d)\n", signum); 
    signal(SIGALRM, catchAlarm); 
    alarm(3); 
} 

int main(void) 
{ 
    pid_t pid = fork(); 

    if (pid < 0) 
    { 
     fprintf(stderr, "Fork Failed"); 
     exit(-1); 
    } 
    else if (pid == 0) 
    { 
     printf("It's great to be alive (%d)\n", (int)getpid()); 
     signal(SIGINT, catchInt); 
     signal(SIGALRM, catchAlarm); 
     alarm(3); 
     for (;;) 
     { 
      printf("I have 42001 children and not one comes to visit\n"); 
      usleep(500000); 
     } 
    } 
    return(0); 
} 

Wenn Sie <sys/types.h> enthalten werden, sollte es normalerweise der erste der POSIX-Header (und damit vor <unistd.h>). Die Tatsache, dass es zuletzt aufgeführt ist, deutet darauf hin, dass Sie es überhaupt nicht brauchen sollten - aber ich erinnere mich an eine vorherige Frage, in der Sie behaupteten, dass es notwendig sei. (OTOH, gibt es keinen Aufruf zu einem der wait() Familie, so <sys/wait.h> ist nicht notwendig, und ich bin davon überzeugt, dass mäßig <sys/types.h> nicht auf den meisten modernen Systemen benötigt wird.)

+0

Haha, ich bin fast positiv meine Netbook Distribution von Ubuntu ist die Quelle meiner sys/types.h Probleme, ohne dass pid_t für mich nicht deklariert ist. Aber es gibt andere solche Header auf meinem System, also ist es nicht schockierend.Der Grund für die exzessiven Header ist, glaube ich, dass ich einfach alle meine Header kopiert habe, als ich das gemacht habe und das Fett noch nicht getrimmt habe. Danke für die Antwort, Töten funktioniert gut genug für meine Zwecke atm. – JKomusin

0

Nein, das SIGINT Signal nur in dem Vordergrund gesendet wird Prozesse , wenn es durch die Verwendung CTRLC (oder was auch immer stty hat den intr Tastendruck eingestellt) actioned wird.

Sie können ein SIGINT immer an einen bestimmten Prozess mit kill -INT 99999 senden (wobei 99999 die Prozess-ID ist).

+0

Danke, kill -INT muss erstmal fertig werden. – JKomusin

Verwandte Themen