Rheinwerk Computing < openbook > Rheinwerk Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger.

Inhaltsverzeichnis
Vorwort
Vorwort des Gutachters
1 Einstieg in C
2 Das erste Programm
3 Grundlagen
4 Formatierte Ein-/Ausgabe mit »scanf()« und »printf()«
5 Basisdatentypen
6 Operatoren
7 Typumwandlung
8 Kontrollstrukturen
9 Funktionen
10 Präprozessor-Direktiven
11 Arrays
12 Zeiger (Pointer)
13 Kommandozeilenargumente
14 Dynamische Speicherverwaltung
15 Strukturen
16 Ein-/Ausgabe-Funktionen
17 Attribute von Dateien und das Arbeiten mit Verzeichnissen (nicht ANSI C)
18 Arbeiten mit variabel langen Argumentlisten – <stdarg.h>
19 Zeitroutinen
20 Weitere Headerdateien und ihre Funktionen (ANSI C)
21 Dynamische Datenstrukturen
22 Algorithmen
23 CGI mit C
24 MySQL und C
25 Netzwerkprogrammierung und Cross–Plattform-Entwicklung
26 Paralleles Rechnen
27 Sicheres Programmieren
28 Wie geht’s jetzt weiter?
A Operatoren
B Die C-Standard-Bibliothek
Stichwort

Buch bestellen
Ihre Meinung?

Spacer
<< zurück
C von A bis Z von Jürgen Wolf
Das umfassende Handbuch
Buch: C von A bis Z

C von A bis Z
3., aktualisierte und erweiterte Auflage, geb., mit CD und Referenzkarte
1.190 S., 39,90 Euro
Rheinwerk Computing
ISBN 978-3-8362-1411-7
Pfeil 20 Weitere Headerdateien und ihre Funktionen (ANSI C)
Pfeil 20.1 <assert.h> – Testmöglichkeiten und Fehlersuche
Pfeil 20.2 <ctype.h> – Zeichenklassifizierung und Umwandlung
Pfeil 20.3 Mathematische Funktionen – <math.h>, <tgmath.h> und <complex.h>
Pfeil 20.3.1 Funktionen für reelle und komplexe Gleitpunkttypen
Pfeil 20.3.2 Funktionen nur für reelle Gleitpunkttypen
Pfeil 20.3.3 Funktionen nur für komplexe Gleitpunkttypen
Pfeil 20.3.4 Typengenerische Makros – <tgmath.h>
Pfeil 20.3.5 Gleitpunktwerte klassifizieren
Pfeil 20.3.6 Makro zum Vergleichen von reellen Zahlen
Pfeil 20.3.7 Zugriff auf die Gleitpunkt-Umgebung – <fenv.h>
Pfeil 20.4 <stdlib.h>
Pfeil 20.4.1 Programmbeendigung – »exit()«, »_exit()«, »atexit()« und »abort()«
Pfeil 20.4.2 Strings in numerische Werte konvertieren
Pfeil 20.4.3 Bessere Alternative – Strings in numerische Werte konvertieren
Pfeil 20.4.4 Zufallszahlen
Pfeil 20.4.5 Absolutwerte, der Quotient und der Rest von Divisionen
Pfeil 20.4.6 Suchen und Sortieren – »qsort()« und »bsearch()«
Pfeil 20.4.7 system()
Pfeil 20.5 <locale.h> – länderspezifische Eigenheiten
Pfeil 20.6 Nicht-lokale Sprünge – <setjmp.h>
Pfeil 20.7 <signal.h>
Pfeil 20.8 <string.h> – die »mem…«-Funktionen zur Speichermanipulation
Pfeil 20.8.1 »memchr()« – Suche nach einzelnen Zeichen
Pfeil 20.8.2 »memcmp()« – bestimmte Anzahl von Bytes vergleichen
Pfeil 20.8.3 »memcpy()« – bestimmte Anzahl von Bytes kopieren
Pfeil 20.8.4 »memmove()« – bestimmte Anzahl von Bytes kopieren
Pfeil 20.8.5 »memset()« – Speicherbereich mit bestimmten Zeichen auffüllen


Rheinwerk Computing - Zum Seitenanfang

20.7 <signal.h> topZur vorigen Überschrift

Signale sind nicht vorhersehbare Ereignisse, die zu einem nicht vorhersagbaren Zeitpunkt auftreten können, also asynchrone Ereignisse. Nach dem ANSI-C-Standard gibt es folgende Signale, die vorkommen können:


Tabelle 20.15 Makros für Fehlersignale

Name Bedeutung
SIGABRT

Dieses Signal signalisiert, dass sich das Programm abnormal beendet hat (abort()).

SIGFPE

Dieses Signal wird z. B. angezeigt bei einer Division durch 0 oder einem Überlauf einer Zahl.

SIGILL

Dieses Signal wird angezeigt, wenn ein illegaler Hardware-Befehl ausgeführt wird.

SIGINT

Dieses Signal wird an alle Prozesse geschickt, wenn die Tastenkombination (Strg) + (C) gedrückt wurde.

SIGSEGV

Wird dies angezeigt, wurde versucht, auf eine unerlaubte Speicherstelle zu schreiben oder diese zu lesen.

SIGTERM

Beendigung eines Programms


Unter Linux gibt es deutlich mehr Signale (ca. 30). Mit dem Befehl

kill -l

wird eine Liste der Signale unter Linux/UNIX ausgegeben. Tritt ein Signal auf, haben Sie folgende Möglichkeiten, darauf zu reagieren:

  • Eintragen einer selbst geschriebenen Funktion
  • Ignorieren des Signals (geht aber nicht mit SIGKILL)
  • Verwenden der voreingestellten Default-Funktion (Bei den ANSI-C-Signalen ist dies immer eine Beendigung des Programms.)

Um auf die Signale zu reagieren, existiert ein sogenanntes Signalkonzept. Dabei richtet ein Prozess einen sogenannten Signalhandler ein. Dieser Signalhandler teilt – wenn das Signal auftritt – dem Systemkern mit, was er zu tun hat. Ein solcher Handler kann mit der Funktion signal() eingerichtet werden. Hier ihre Syntax:

#include <signal.h>

void(*signal(int signr, void(*sighandler)(int)))(int);

Einen solchen Prototyp zu lesen, ist fast unmöglich. Aus diesem Grund wurde die Funktion in der Headerdatei <signal.h> wie folgt vereinfacht:

typedef void (*__p_sig_fn_t)(int);
__p_sig_fn_t signal(int, __p_sig_fn_t);

Somit sieht der Prototyp folgendermaßen aus:

signalfunktion *signal(int signalnummer,
                       signalfunktion *sighandler);

Mit dem Parameter signalnummer legen Sie die Nummer des Signals fest, für die ein Signalhandler eingerichtet werden soll. Dies ist dann eines der Signale, die Sie soeben in Tabelle 20.15 kennengelernt haben (bzw. unter Linux diejenigen, die mit kill -l aufgelistet wurden).

Für den Parameter sighandler sind zwei Konstanten in der Headerdatei <signal.h> deklariert: SIG_DFL und SIG_IGN. Mit SIG_DFL wird die Default-Aktion ausgeführt, was meist die Beendigung des Prozesses bedeutet. Ein Beispiel:

signal(SIGINT, SIG_DFL);

Falls Sie die Tastenkombination Taste Strg + Taste C drücken, wird die Default-Einstellung des Signals SIGINT ausgeführt. Und die Default-Einstellung schreibt vor, dass das Programm beendet wird. Als zweite Möglichkeit können Sie Folgendes eingeben:

signal(SIGINT, SIG_IGN);

Drücken Sie jetzt die Tastenkombination Taste Strg + Taste C, passiert gar nichts. Das Signal SIGINT wird mit der Angabe von SIG_IGN ignoriert. Als dritte Möglichkeit können Sie das Signal SIGINT abfangen und die Adresse einer eigenen Funktion übergeben, die ausgeführt werden soll, wenn die Tastenkombination Taste Strg + Taste C betätigt wurde:

signal(SIGINT,funktionsaufruf);

Jetzt wird es Zeit, dass Sie sich ansehen, wie die Funktion signal() in der Praxis eingesetzt wird:

/* signal1.c */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void sigfunc(int sig) {
   int c;

   if(sig != SIGINT)
      return;
   else {
      printf("\nWollen Sie das Programm beenden (j/n) : ");
      c=getchar();
      if(c == 'j')
         exit (EXIT_FAILURE);
      else
         return;
   }
}

int main(void) {
   int i;

   signal(SIGINT, sigfunc);
   while(1) {
      printf("Mit STRG+C beenden");
      for(i = 0; i <= 48; i++)
         printf("\b");
   }
   return EXIT_SUCCESS;
}

Mit der Anweisung

signal(SIGINT, sigfunc);

wird ein Signalhandler für das Signal SIGINT eingerichtet, der beim Auftreten dieses Signals die Funktion sigfunc aufrufen soll.

Ein einfaches Beispiel bietet auch das Erstellen einer eigenen kleinen Shell. Die einzelnen Shellbefehle werden in einer Endlosschleife abgearbeitet. Mit der Tastenkombination Taste Strg + Taste C lösen Sie dabei einen Neustart der Shell aus. Dieser Sprung (Neustart) wird mit den Funktionen der Headerdatei <setjmp.h> realisiert. Hier sehen Sie das Beispiel dazu:

/* a_simple_shell.c */
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
#define MAX 255
#define OK 0

jmp_buf restart;

void ctrlc(int sig) {
   signal(sig, ctrlc);
   /* zurück zur Kommandozeile */
   longjmp(restart, 1);
   return;
}

int main(void) {
   char *command;
   /* Installiere den Signalhandler. */
   signal(SIGINT, ctrlc);

   if(setjmp(restart) != 0)
      printf("\n\nShell neu gestartet ...\n\n");
   else
      printf("\n\nShell gestartet ...\n\n");

   for (;;) {   /* Hier können Sie machen, was Sie wollen. */
      char puffer[MAX];
      printf("$~> ");
      fgets(puffer, MAX, stdin);
      command = strtok(puffer, "\n");

      if( strcmp(command, "test") == OK )
         printf("Ihr Befehl lautete \"test\"\n");
      else if( strcmp(command, "help") == OK )
         printf("Brauchen Sie Hilfe?\n");
      /* usw. eine Menge mehr Shellbefehle ... */
      else if( strcmp(command, "exit") == OK )
         exit (EXIT_SUCCESS);
      else {
         printf("\nUnbekannter Shellbefehl\n");
         printf("Bekannte Befehle: test, help, exit\n\n");
      }
   }
   return EXIT_SUCCESS;
}

Dies ist eine einfache Schnittstelle einer eigenen Shell. Logischerweise müssen Sie statt der Ausgabe von Texten Ihre selbst geschriebenen Funktionen implementieren.

Hier sehen Sie ein weiteres Beispiel zu signal() mit dem Signal SIGABRT:

/* sigabort.c */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void sigfunc(int sig) {
   if(sig == SIGABRT)
      printf("Demonstration von SIGABRT\n");
}

int main(void) {
   signal(SIGABRT, sigfunc);
   abort();
   return EXIT_SUCCESS;
}

Um zu testen, ob der Aufruf der Funktion signal() überhaupt erfolgreich war, befindet sich in der Headerdatei <signal.h> der Fehlercode SIG_ERR, der mit dem Wert –1 definiert ist. Wollen Sie also die Funktion signal() auf Fehler überprüfen, sollte dies so aussehen:

if( signal(SIGINT,sigfunc) == SIG_ERR)
   {  /* Fehler beim Aufruf von signal */

Es ist auch möglich, mit der Funktion raise()ein Signal an ein ausführendes Programm zu senden. Die Syntax der Funktion lautet:

int raise(int signr);

Damit können Sie ein Signal mit der signr an das Programm senden. Ein kurzes Beispiel:

/* raise_signal.c */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void sigfunc(int sig) {
   if(sig == SIGINT)
      printf("SIGINT wurde ausgeloest\n");
}

int main(void) {
   signal(SIGINT,sigfunc);
   printf("Mit ENTER SIGINT ausloesen\n");
   getchar();
   /* SIGINT auslösen */
   raise(SIGINT);
   return EXIT_SUCCESS;
}

Unter Linux/UNIX verwendet man allerdings in der Praxis ein etwas anderes Signalkonzept, da die signal()-Funktion von ANSI C hier einige Schwächen besitzt. Mehr dazu können Sie wieder meinem Buch »Linux-UNIX-Programmierung« entnehmen, das Sie auch auf meiner Webseite zum Online-Lesen vorfinden.



Ihr Kommentar

Wie hat Ihnen das <openbook> gefallen? Wir freuen uns immer über Ihre freundlichen und kritischen Rückmeldungen. >> Zum Feedback-Formular
<< zurück
  
  Zum Katalog
Zum Katalog: C von A bis Z

 C von A bis Z
Jetzt bestellen


 Ihre Meinung?
Wie hat Ihnen das <openbook> gefallen?
Ihre Meinung

 Buchtipps
Zum Katalog: C/C++






 C/C++


Zum Katalog: Einstieg in C






 Einstieg in C


Zum Katalog: Schrödinger programmiert C++






 Schrödinger
 programmiert C++


Zum Katalog: C++ Handbuch






 C++ Handbuch


Zum Katalog: IT-Handbuch für Fachinformatiker






 IT-Handbuch für
 Fachinformatiker


 Shopping
Versandkostenfrei bestellen in Deutschland und Österreich
InfoInfo




Copyright © Rheinwerk Verlag GmbH 2009
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Rheinwerk Computing]

Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de