SUCHE MIT Google
Web virtualuniversity.ch
HOME DIDAKTIK ECDL ELEKTRONIK GUIDES HR MANAGEMENT MATHEMATIK SOFTWARE TELEKOM
DIENSTE
Anmeldung
Newsletter abonnieren
Sag's einem Freund!
VirtualUniversity als Startseite
Zu den Favoriten hinzufügen
Feedback Formular
e-Learning für Lehrer
Spenden
Autoren login
KURSE SUCHEN
Kurse veröffentlichen

Suche nach Datum:

Suche mit Schlüsselwort:

Suche nach Land:

Suche nach Kategorie:
PARTNER
ausbildung24.ch - Ausbildungsportal, Seminare, Kursen... 

 
HTMLopen.de - Alles was ein Webmaster braucht

 
PCopen.de - PC LAN Netze und Netzwerke - alles was ein IT Profi und Systemtechnicker braucht

SOFTWARE
                                       #include <stdio.h>
                                       #include <stdlib.h>
                                       #include <unistd.h>
                                       
                                       int main(void)
                                         {
                                         pid_t  pid;
                                         pid = getpid();
                                         printf ("Meine PID = %d\n", pid) ;
                                       
                                         pid = getppid();
                                         printf ("Meine Eltern-PID = %d\n", pid) ;
                                         return 0;
                                         }
                                       

Das Programm aus diesem Listing definiert eine Variable vom Typ pid_t. Die Werte, die von den Funktionen getpid() und getppid() zurückgegeben werden, werden dann ausgegeben. Wenn Sie das Programm mehrmals im gleichen Konsolenfenster ausführen, erhalten Sie jedes Mal eine andere Prozess-ID, während die ID für den Elternprozess immer die gleiche bleibt.

Mit fork() andere Prozesse starten

Linux und andere Mitglieder der Unix-Familie verfügen über eine Standardmethode zum Starten anderer Prozesse, die auf der Funktion fork() basiert. Ebenso wie getpid() liefert fork() eine Prozess-ID zurück und ist in der Header-Datei unistd.h definiert. Ihr Prototyp sieht wie folgt aus:
                                       pid_t fork(void);
                                       
Tritt kein Fehler auf, erzeugt fork() einen neuen Prozess, der mit dem aufrufenden Prozess identisch ist. Sowohl der alte als auch der neue Prozess werden danach - ab der Anweisung hinter dem fork()-Aufruf - parallel ausgeführt. Obwohl beide Prozesse das gleiche Programm ausführen, verfügen sie über eigene Kopien aller Daten und Variablen. Eine dieser Variablen ist der Rückgabewert von fork().
  • Im Kindprozess ist der Wert 0.
  • Im Elternprozess ist es der Wert der Prozess-ID des Kindprozesses.
  • Wenn fork() scheitert, wird -1 zurückgegeben.
Nach dem Aufruf von fork() sind die Daten beider Programme getrennt, so daß weder der Kind- noch der Elternprozess in der Lage ist, irgendwelche Variablen oder Daten im jeweils anderen Prozess zu manipulieren.

Beispiel: Mit Hilfe von fork() einen neuen Prozess erzeugen.

                                       #include <stdio.h>
                                       #include <stdlib.h>
                                       #include <unistd.h>
                                       int main(void)
                                         {
                                         pid_t  pid;
                                         int x = 22;
                                       
                                         pid = fork();
                                         if (pid < 0)
                                           {
                                           printf("Fehler: fork()-Rsultat %d.\n", pid);
                                           exit(1);
                                           }
                                         if (pid == 0)
                                           {
                                           printf("Kind: PID = %u. Eltern-PID = %u\n",
                                                   getpid(), getppid());
                                           printf("Kind: xalt = %d\n", x);
                                           x = 11;
                                           printf("Kind: xneu = %d\n", x);
                                           sleep(2);
                                           puts ("Kind: Beendet.");
                                           exit(42);
                                           }
                                         else
                                           {
                                           printf("Eltern: PID = %u. Kind-PID = %u\n",
                                                   getpid(), pid);
                                           puts("Eltern:  60 Sekunden Pause.");
                                           sleep(60);
                                           puts("Eltern: wieder wach.");
                                           printf("Eltern: x = %d\n", x);
                                           }
                                       
                                         return 0;
                                         }
                                       

Ausgabe:

                                       Eltern: PID = 1535. Kind-PID = 1536
                                       Eltern:  60 Sekunden Pause.
                                       Kind: PID = 1536. Eltern-PID = 1535
                                       Kind: xalt = 22
                                       Kind: xneu = 11
                                       Kind: Beendet.
                                       Eltern: wieder wach.
                                       Eltern: x = 22
                                       

Anhand des Rückgabewertes von fork() wird festgestellt, ob ein Fehler aufgetreten ist. Sind keine Fehler aufgetreten, werden zwei Prozesse ausgeführt. Im Kindprozess ist der Wert von pid 0, im Elternprozess enthält die Variable eine Prozess-ID im Bereich zwischen 1 und 32767. Die if-Anweisung wird von beiden Prozessen ausgewertet. Der Kindprozess führt danach den Block nach dem if aus, der Elternprozess den Block nach dem else.

An der Programmausgabe können Sie erkennen, daß der Elternprozess nach dem fork()-Aufruf eine Meldung ausgibt und sich dann schlafen legt. Parallel wird der Kindprozess weiter ausgeführt. Als erstes gibt er seine eigene PID und die seines Elternprozesses aus. Als Nächstes gibt der Kindprozess den Wert der Variablen x aus, ändert den Wert und gibt ihn erneut aus. Schließlich geht auch er für 2 Sekunden Pause. Da der Elternprozess 60 Sekunden schläft, wacht der Kindprozess vor seinem Eltern auf und gibt eine Meldung aus. Dann beendet er sich und gibt den Wert 42 zurück. 60 Sekunden später erwacht der Elternprozess von seinem eigenen sleep()-Aufruf, gibt den Wert der Variablen x aus und beendet sich ebenfalls.

Zombie-Prozesse

Das obige Programm enthält allerdings auch einen dicken Fehler, der in bestimmten Situationen Probleme verursachen kann. Um zu verstehen, worin dieser Fehler besteht, führen Sie das Programm noch einmal im Hintergrund aus. Wenn die "Kind: Beendet"-Meldung erscheint, rufen Sie den Befehl ps u auf und betrachten den Eintrag des Kindprozesses:
                                       ...
                                       
                                       jpl   1714  0.0  0.0     0    0 pts/5  Z    Jan27  0:00 [kind <defunct>]
                                       ...
                                       
Der Kind-Prozess wird als erloschen (defunct) gemeldet. In der STAT-Spalte dieses Prozesses steht ein Z, was bedeutet, daß es sich um einen so genannten "Zombie"-Prozess handelt.

Prozesse verwenden zum Beenden die return-Anweisung oder rufen die Funktion exit() mit einem Wert auf, der an das Betriebssystem zurückgeliefert wird. Das Betriebssystem lässt den Prozess so lange in seiner Prozesstabelle eingetragen, bis entweder der Elternprozess des Prozesses den zurückgelieferten Wert liest oder der Elternprozess selbst beendet wird. Ein Zombie-Prozess ist in diesem Sinne ein Prozess, der zwar beendet wurde, dessen Elternprozess den Exit-Wert des Kindes aber noch nicht gelesen hat. Erst wenn der Elternprozess beendet wird, wird auch der Zombie-Prozess aus der Prozesstabelle des Betriebssystems entfernt.

Es gibt mehrere Wege, die Entstehung von Zombie-Prozessen zu verhindern. Am häufigsten wird die Systemfunktion wait() verwendet (Header-Datei sys/wait.h):

                                       pid_t wait(int *status);
                                       
Diese Funktion hat eine int-Variablenparameter und liefert einen Wert vom Typ pid_t zurück. Wenn die Funktion aufgerufen wird, hält sie die Ausführung des Elternprozesses so lange an, bis ein Kindprozess beendet wird. Tritt dieser Fall ein oder liegt ein Kindprozess als Zombie-Prozess vor, liefert wait() die Prozess-ID des Kindes zurück und kopiert den Exit-Wert des Kindprozesses in die status-Variable. Wenn Sie an dem Rückgabewert des Kindprozesses nicht interessiert sind, übergeben wait() den Wert NULL. Gibt es keinen Kindprozess, liefert wait() den Wert -1 zurück.

Beispiel: Mit wait() Zombie-Prozesse verhindern.

                                       #include <stdio.h>
                                       #include <stdlib.h>
                                       #include <unistd.h>
                                       #include <sys/types.h>
                                       #include <sys/wait.h>
                                       
                                       int main(void)
                                         {
                                         pid_t  pid;
                                         int    status;
                                       
                                         pid = fork();
                                         if (pid < 0)
                                           {
                                           printf("Fehler: fork()-Rsultat %d.\n", pid);
                                           exit(1);
                                           }
                                         if (pid == 0)
                                           {
                                           printf("Kind: PID = %u. Eltern-PID = %u\n",
                                                   getpid(), getppid());
                                           sleep(1);
                                           puts ("Kind: Beendet.");
                                           exit(42);
                                           }
                                         else
                                           {
                                            printf("Eltern: PID = %u. Kind-PID = %u\n",
                                                    getpid(), pid);
                                            puts("Eltern:  10 Sekunden Pause.");
                                            sleep(10);
                                            puts("Eltern: wieder wach.")
                                            pid = wait(&status);
                                            printf("Eltern: Kind mit PID %u ", pid);
                                            if (WIFEXITED(status) != 0)
                                              printf("wurde mit Status %d beendet\n",WEXITSTATUS(status));
                                            else
                                              printf("wurde mit Fehler beendet.\n");
                                            }
                                       
                                         return 0;
                                         }
                                       
                                       

Dieses Listing entspricht weitgehend dem vorhergehenden Programm. Der Hauptunterschied liegt darin, daß der Elternprozess nach dem Erwachen die Funktion wait() aufruft. Da der Kindprozess schon vorher beendet wurde, kehrt wait() sofort nach dem Aufruf zurück und setzt die Variable pid auf die Prozess-ID des beendeten Kindprozesses. Des Weiteren kopiert die Funktion den Exit-Wert des Prozesses in die Variable status, deren Adresse der Funktion als Argument übergeben wurde. Der Elternprozess gibt die Prozess-ID des Kindes aus und verwendet die Makros, WIFEXITED() and WEXITSTATUS(), die in sys/wait.h definiert sind, um den Rückgabestatus des Kindprozesses abzufragen und ebenfalls auszugeben. Auf der Manpage zur wait()-Funktion können Sie nachlesen, daß diese Makros dafür sorgen, daß nur 8-Bit-Werte (1 bis 255) als Exit-Status zurückgeliefert werden.

Die wait()-Funktion ist offensichtlich recht nützlich, wenn man weiß, daß der Kindprozess bereits beendet wurde. Sollte dies nicht der Fall sein, hält die wait()-Funktion den Elternprozess so lange an, bis der Kindprozess beendet wird. Wenn dieses Verhalten nicht gewünscht, kann man die waitpid()-Funktion verwenden, die in der Header-Datei sys/wait.h definiert ist:

                                       pid_t waitpid(pid_t pid, int *status, int options);
                                       
Mit waitpid() können Sie auf einen bestimmten Prozess (spezifiziert durch seine Prozess-ID) oder einen beliebigen Kindprozess (falls für pid der Wert -1 übergeben wird) warten. Der Exit-Status des Kindprozesses wird im zweiten Argument zurückgeliefert. Dem letzten Parameter, options, kann man eine der Konstanten WNOHANG, WUNTRACED oder 0 (waitpid() verhält sich dann wie wait()) übergeben. Die erste dieser Konstanten ist die interessanteste, da sie dafür sorgt, daß waitpid() sofort mit einem Wert von 0 - einer ungültigen Prozess-ID - zurückkehrt, wenn kein Kindprozess beendet wurde. Der Elternprozess kann dann mit der Ausführung fortfahren und waitpid() zu einem späteren Zeitpunkt wieder aufrufen.

Beispiel: Mit waitpid() Zombie-Prozesse verhindern.

                                       #include <stdio.h>
                                       #include <stdlib.h>
                                       #include <unistd.h>
                                       #include <sys/types.h>
                                       #include <sys/wait.h>
                                       
                                       int main(void)
                                         {
                                         pid_t  pid;
                                         int    status;
                                       
                                         pid = fork();
                                         if (pid < 0)
                                           {
                                           printf("Fehler: fork()-Rsultat %d.\n", pid);
                                           exit(1);
                                           }
                                         if (pid == 0)
                                           {
                                           printf("Kind: PID = %u. Eltern-PID = %u\n",
                                                   getpid(), getppid());
                                           sleep(10);
                                           puts ("Kind: Beendet.");
                                           exit(66);
                                           }
                                         else
                                           {
                                           printf("Eltern: PID = %u. Kind-PID = %u\n",
                                                   getpid(), pid);
                                           while ((pid = waitpid (-1, &status,  WNOHANG)) == 0)
                                             {
                                             printf("Eltern: Kein Kind beendet.");
                                             puts(" 1 Sekunde Pause.");
                                             sleep(1);
                                             }
                                           printf("Eltern: Kind mit PID %u ", pid);
                                           if (WIFEXITED(status) != 0)
                                             printf("wurde mit Status %d beendet\n", WEXITSTATUS(status));
                                           else
                                             printf("wurde mit Fehler beendet.\n");
                                           }
                                       
                                         return 0;
                                         }
                                       

Einen Prozess durch einen anderen ersetzen

Die fork()-Funktion ist nur ein Teil der Lösung; der zweite Teil besteht darin, einen laufenden Prozess durch einen anderen zu ersetzen. Unter Linux/Unix gibt es gleich eine ganze Reihe von Systemfunktionen, die so genannte exec-Familie, mit denen man einen Prozess unter Beibehaltung der Prozess- ID auf ein anderes Programm umschalten kann. In der exec-Manpage finden Sie ausführliche Informationen zu den verschiedenen Mitgliedern der exec-Familie. Wir werden uns jetzt auf die Funktion execl() konzentrieren, die in der Header-Datei unistd.h wie folgt definiert ist:
                                       int execl( const char *path, const char *arg, ...);
                                       
Diese Funktion kehrt nur dann zurück, wenn ein Fehler auftritt. Andernfalls wird der aufrufende Prozess vollständig durch den neuen Prozess ersetzt. Den Programmnamen des Prozesses, der den aufrufenden Prozess ersetzen soll, übergibt man im Argument zu path, etwaige Kommandozeile-Parameter werden danach übergeben. Im Unterschied zu Funktionen wie printf() ist execl() darauf angewiesen, daß man als letztes Argument einen NULL-Zeiger übergibt, der das Ende der Argumentenliste anzeigt.

Der zweite an execl() übergebene Parameter ist nicht der erste Kommandozeilen-Parameter, der an das aufzurufende Programm (spezifiziert in path) übergeben wird. Vielmehr ist er der Name, unter dem der neue Prozess in der vom ps-Befehl erzeugten Prozessliste aufgeführt wird. Der erste Parameter, der an das (in path spezifizierte) Programm übergeben wird, ist also tatsächlich der dritte Parameter von execl(). Wenn Sie beispielsweise das Programm /bin/ls mit dem Parameter -lisa aufrufen wollen und möchten, daß das Programm in der Prozessliste unter dem Namen "verz" aufgerufen wird, würden Sie execl() wie folgt aufrufen:

                                       execl("/bin/ls", "verz", "-lisa", NULL);
Dieser Aufruf würde den aktuellen Prozess durch einen Prozess ersetzen, der dem Aufruf von /bin/ls -lisa von der Befehlszeile entspricht.

Beispiel: Mit execl() einen Prozess durch einen anderen ersetzen.

                                       #include <stdio.h>
                                       #include <stdlib.h>
                                       #include <unistd.h>
                                       #include <errno.h>
                                       
                                       int main(void)
                                         {
                                         pid_t  pid ;
                                       
                                         pid = getpid();
                                         printf ("Meine PID = %u\n", pid);
                                         execl ("/bin/ps", "ps-proggie", "u", NULL);
                                         puts("Ein Fehler ist aufgetreten.");
                                         return 0;
                                         }
                                       

Beachten Sie, daß der ursprüngliche Prozess die gleiche Prozess-ID trägt wie später der neue Prozess, der ihn ersetzte.

execl() ist nicht die einzige Funktion dieser Art, es gibt eine ganze Familie mit leicht unterschiedlicher Arbeitsweise.

Alles zusammen

Die C-Funktion system() kann Kommandos an UNIX übergeben - sie vereint also fork() und exec..(). Sie erhält eine Stringkonstante (z.B. system("ls -l");) oder eine Stringvariable (z.B. char kommando[ 20]; ...; system(kommando);) als Eingabeparameter. Dieser Parameter ist das Kommando, das dann von UNIX ausgeführt wird.

system() erzeugt einen eigenen Prozeß. Dieser führt das Kommando aus, was aber keinen Effekt für den aufrufenden Prozeß hat.

Signale

Ein weiteres wichtiges Element der Unix-ähnlichen Betriebssysteme stellen - neben der Möglichkeit, neue Prozesse zu starten oder einen Prozess durch einen anderen Prozess zu ersetzen - die Signale dar, die vielfach auch als Software-Interrupts bezeichnet werden. Signale sind Meldungen, die vom Betriebssystem an einen laufenden Prozess geschickt werden. Manche Signale werden durch Fehler im Programm selbst ausgelöst, andere sind Anforderungen, die der Anwender beispielsweise über die Tastatur auslöst und die vom Betriebssystem an den laufenden Prozess weitergeleitet werden.
Alle Signale, die an ein Programm gesendet werden, verfügen über ein vordefiniertes Verhalten, das durch das Betriebssystem festgelegt wird. Einige Signale, insbesondere die Signale, die aufgrund irgendwelcher aufgetretener Fehlerbedingungen an das Programm geschickt werden, führen dazu, daß das Programm beendet und eine "Core Dump"-Datei, erzeugt wird.
In der folgenden Tabelle finden Sie eine Liste der am häufigsten unter Unix-Systemen ausgelösten Signale. Eine vollständige Liste der für Linux definierten Signale finden Sie in der Header-Datei /usr/include/bits/signum.h.

Name Wert Funktion
SIGHUP 1 Logoff
SIGINT 2 Benutzer-Interrupt (ausgelöst durch [Strg]+[C])
SIGQUIT 3 Benutzeraufforderung zum Beenden (ausgelöst durch [Strg)+[\])
SIGFPE 8 Fließkommafehler, beispielsweise Null-Division
SIGKILL 9 Prozess killen
SIGUSR1 10 Benutzerdefiniertes Signal
SIGSEGV 11 Prozess hat versucht, auf Speicher zuzugreifen, der ihm nicht zugewiesen war
SIGUSR2 12 Weiteres benutzerdefiniertes Signal
SIGALRM 14 Timer (Zeitgeber), der mit der Funktion alarm() gesetzt wurde, ist abgelaufen
SIGTERM 15 Aufforderung zum Beenden
SIGCHLD 17 Kindprozess wird aufgefordert, sich zu beenden
SIGCONT 18 Nach einem SIGSTOP- oder SIGTSTP-Signal fortfahren
SIGSTOP 19 Den Prozess anhalten
SIGTSTP 20 Prozess suspendiert, ausgelöst durch [Strg)+[Z].

Abgesehen von SIGSTOP und SIGKILL kann man das Standardverhalten jedes Signals durch Installation einer Signal-Bearbeitungsroutine anpassen. Eine Signal- Bearbeitungsroutine ist eine Funktion, die vom Programmierer implementiert wurde und die jedes Mal aufgerufen wird, wenn der Prozess ein entsprechendes Signal empfängt. Abgesehen von SIGSTOP und SIGKILL können Sie für jedes Signal aus eine eigene Signal-Bearbeitungsroutine einrichten. Eine Funktion, die als Signal-Bearbeitungsroutine fungieren soll, muss einen einzigen Parameter vom Typ int und einen void-Rückgabetyp definieren. Wenn ein Prozess ein Signal empfängt, wird die Signal-Bearbeitungsroutine mit der Kennnummer des Signals als Argument aufgerufen.

Um Signale abfangen und mit einer geeigneten Signal-Bearbeitungsroutine bearbeiten zu können, muss der Programmierer dem Betriebssystem mitteilen, daß es bei jedem Auftreten des betreffenden Signals für das Programm die zugehörige Signal- Bearbeitungsroutine aufrufen soll. Zwei Funktionen gibt es, mit denen man unter Unix eine Signal-Bearbeitungsroutine verändern oder untersuchen kann: signal() und sigaction(), die beide in der Header-Datei signal.h definiert sind. Die zweite Funktion, sigaction(), ist die aktuellere und wird auch häufiger eingesetzt. Sie ist wie folgt definiert:

                                       int sigaction(int signum, const struct sigaction *act,
                                                     struct sigaction *oldact);
                                       

Im Erfolgsfall liefert die Funktion 0 zurück, im Fehlerfall -1. Der erste Parameter von sigaction() ist die Nummer des Signals, dessen Verhalten Sie verändern oder untersuchen wollen. Man übergibt dem Parameter aber nicht die tatsächliche Signal-Nummer, sondern die zugehörige symbolische Konstante - also beispielsweise SIGINT statt der Zahl 2. Der zweite und der dritte Parameter sind Zeiger auf eine sigaction-Struktur. Diese Struktur ist in signal.h definiert:

                                       struct sigaction
                                         {   
                                         void (*sa_handler)(int);
                                         sigset_t sa_mask;
                                         int sa_flags;
                                         void (*sa_restorer)(void);
                                         }
                                       

Indem Sie dem zweiten Parameter der sigaction()-Funktion einen Zeiger auf eine korrekt eingerichtete sigaction-Struktur übergeben, können Sie das Verhalten für das zugehörige Signal verändern. Indem Sie einen Zeiger auf eine solche Struktur als dritten Parameter übergeben, fordern Sie die sigaction()-Funktion auf, die Daten, die das aktuelle Verhalten zu dem Signal bestimmen, in die übergebene sigaction-Struktur zu kopieren. Beiden Parametern kann man auch NULL- Zeiger übergeben.

Es ist also möglich, das aktuelle Verhalten zu ändern, sowie das aktuelle Verhalten zu untersuchen, ohne es zu ändern, das aktuelle Verhalten zu untersuchen und vor dem Ändern abzuspeichern, so daß es später wieder hergestellt werden kann.

  • Das Verhalten ändern: sigaction(SIGINT, &neueaktion, NULL);
  • Das Verhalten untersuchen: sigaction(SIGINT, NULL, &alteaktion);
  • Kopie des aktuellen Verhaltens anlegen und neues Verhalten einrichten: sigaction(SIGINT, &neueaktion, &alteaktion);
Bei dem ersten Element der sigaction-Struktur, sa_handler, handelt es sich um einen Zeiger auf eine Funktion, die ein int-Argument übernimmt. Dieses Element dient als Zeiger auf die Funktion, die als Signal-Bearbeitungsroutine für das zu bearbeitende Signal fungieren soll. Sie können diesem Strukturelement auch die symbolischen Konstanten SIG_DFL oder SIG_IGN zuweisen. SIG_DFL stellt das Standardverhalten für das Signal wieder her, SIG_IGN bewirkt, daß das Signal ignoriert wird. Für das sa_flags-Element gibt es eine ganze Reihe möglicher Einstellungen, die uns aber nicht weiter interessieren sollen; wir werden das Element in den Beispielen jeweils auf 0 setzen. Über das sa_mask- Element kann man angeben, welche anderen Signale während der Ausführung der Signal-Bearbeitungsroutine blockiert werden sollen. Meist wird dieses Strukturelement mit Hilfe der Funktion sigemptyset() gesetzt, die in signal.h wie folgt definiert ist:
                                       int sigemptyset(sigset_t *set);
                                       
Das letzte Element der Struktur, sa_restorer, wird heute nicht mehr verwendet.

Beispiel: Ein einfaches Beispiel zur Behandlung von Signalen.

                                       #include <stdio.h>
                                       #include <unistd.h>
                                       #include <signal.h>
                                       
                                       static int BEENDEN = 0;
                                       
                                       void  sig_bearbeiter(int sig)
                                         {
                                         printf("Signal %d empfangen. Programm wird beendet.\n", sig);
                                         BEENDEN = 1;
                                         }
                                       
                                       int main(void)
                                         {
                                         struct sigaction sig_struct;
                                       
                                         sig_struct.sa_handler = sig_bearbeiter;
                                         sigemptyset(&sig_struct.sa_mask);
                                         sig_struct.sa_flags = 0;
                                       
                                         if (sigaction(SIGINT,&sig_struct,NULL) != 0)
                                           {
                                           puts ("Fehler beim Aufruf von sigaction!") ;
                                           exit (1);
                                           }
                                       
                                         puts("Programm gestartet, beenden mit [Strg]+[C].");
                                         while (BEENDEN == 0)
                                           {
                                           puts("Programm läuft.");
                                           sleep(1);
                                           }
                                       
                                         puts("Erstmal aufraeumen.");
                                         sleeep(5);
                                         puts("Fertig!");
                                         return 0;
                                         }
                                       
Wurde die Signal-Bearbeitungsroutine korrekt eingerichtet, gibt das Programm in eine Meldung aus und tritt in die Schleife des Hauptprogramms ein. Solange die Variable BEENDEN gleich 0 ist, gibt die while-Schleife die Meldung "Programm läuft." aus und legt sich jeweils für eine Sekunde schlafen.

Wenn die Signal-Bearbeitungsroutine sig_bearbeiter() aufgerufen wird, gibt sie die Meldung "Signal 2 empfangen. Programm wird beendet." auf den Bildschirm aus und setzt danach den Wert der statischen Variablen BEENDEN auf 1. Nur das führt zum Beeenden und nicht das Betätigen von [Ctrl]+[C]. Da Programm könnte auch einfach weiterlaufen und die Benuterunterbrechung ignorieren. Hier die Ausgabe eines Beispiel-Laufs:

                                       Beenden mit [Strg]+[C].
                                       Programm läuft.
                                       Programm läuft.
                                       Programm läuft.
                                       Signal 2 empfangen. Programm wird beendet.
                                       Erstmal aufraeumen.
                                       Fertig!
                                       

DIPLOMARBEITEN UND BÜCHER

Diplomarbeiten zum Runterladen:

Suche im Katalog:
Architektur / Raumplanung
Betriebswirtschaft - Funktional
Erziehungswissenschaften
Geowissenschaften
Geschichtswissenschaften
Informatik
Kulturwissenschaften
Medien- und Kommunikationswissenschaften
Medizin
Psychologie
Physik
Rechtswissenschaft
Soziale Arbeit
Sozialwissenschaften


JOBS
HOME | E-LEARNING | SITEMAP | LOGIN AUTOREN | SUPPORT | FAQ | KONTAKT | IMPRESSUM
Virtual University in: Italiano - Français - English - Español
VirtualUniversity, WEB-SET Interactive GmbH, www.web-set.com, 6301 Zug

Partner:   Seminare7.de - PCopen.de - HTMLopen.de - WEB-SET.com - YesMMS.com - Ausbildung24.ch - Manager24.ch - Job und Karriere