Suche…
Syntax
- Alarm ohne Vorzeichen (Sekunden ohne Vorzeichen);
- int kill (pid_t pid, int sig);
Parameter
| Funktion, Parameter, Rückgabewert | Beschreibung | 
|---|---|
| alarm() | Funktionsname | 
| unsigned seconds | Sekunden zum Auslösen eines Alarms oder 0 zum Abbrechen eines anstehenden Alarms | 
| > = 0 | 0, wenn kein anderer Alarm anstehend war, andernfalls die Anzahl der Sekunden, die der anstehende Alarm noch offen war. Diese Funktion wird nicht fehlschlagen. | 
| - | - | 
| kill() | Funktionsname | 
| pid_t pid | . | 
| int sig | 0 oder Signal-ID | 
| 0, -1 | Bei Erfolg wird 0 zurückgegeben, -1 bei Fehler mit der Einstellung errnoaufEINVAL,EPERModerESRCH. | 
SIGALARM mit der Standardaktion auslösen
 Mit Hilfe des alarm kann der Benutzer SIGALARM Signal SIGALARM nach einem festgelegten Intervall SIGALARM wird. Wenn der Benutzer für dieses Signal keinen expliziten Signalhandler blockiert, ignoriert oder angegeben hat, wird die Standardaktion für dieses Signal bei Ankunft ausgeführt. Pro Spezifikation Standardaktion für SIGALARM ist es, den Prozess zu beenden: 
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char** argv)
{
    printf("Hello!\n");
    // Set the alarm for five second
    alarm(5); // Per POSIX, this cannot fail
    // Now sleep for 15 seconds
    for (int i = 1; i <= 15; i++)
    {
        printf("%d\n", i);
        sleep(1);
    }
    // And print the message before successful exit
    printf("Goodbye!\n");
    return EXIT_SUCCESS;
}
Dies gibt aus:
Hello!
1
2
3
4
5
[2]    35086 alarm      ./a.out
Festlegen des Signal-Handlers mithilfe von Sig- ting und Anheben von Signalen mithilfe von Raise
 Damit ein Programm auf ein bestimmtes Signal reagieren kann, kann der benutzerdefinierte Signalhandler mit sigaction Standardaktion mit sigaction installiert werden. sigaction erhält drei Argumente - Signal zu handeln, Zeiger auf sigaction_t Struktur , die, wenn nicht NULL , beschreibt neues Verhalten und Zeiger auf sigaction_t das, wenn sie nicht NULL mit dem alten Verhalten gefüllt wird (so kann man es wiederherstellen). Das Erhöhen der Signale in demselben Prozess kann mit der raise . Wenn mehr Kontrolle erforderlich ist (um das Signal an einen anderen Prozess zu senden, können kill oder pthread_kill verwendet werden, die die pthread_kill ID oder die Thread-ID akzeptieren). 
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Signals are numbered from 1, signal 0 doesn't exist
volatile sig_atomic_t last_received_signal = 0;
// Signal handler, will set the global variable
// to indicate what is the last signal received.
// There should be as less work as possible inside
// signal handler routine, and one must take care only
// to call reentrant functions (in case of signal arriving
// while program is already executing same function)
void signal_catcher(int signo, siginfo_t *info, void *context)
{
    last_received_signal = info->si_signo;
}
int main (int argc, char** argv)
{
    // Setup a signal handler for SIGUSR1 and SIGUSR2
    struct sigaction act;
    memset(&act, 0, sizeof act);
    // sigact structure holding old configuration
    // (will be filled by sigaction):
    struct sigaction old_1;
    memset(&old_1, 0, sizeof old_1);
    struct sigaction old_2;
    memset(&old_2, 0, sizeof old_2);
    act.sa_sigaction = signal_catcher;
    // When passing sa_sigaction, SA_SIGINFO flag
    // must be specified. Otherwise, function pointed
    // by act.sa_handler will be invoked
    act.sa_flags = SA_SIGINFO;
    if (0 != sigaction(SIGUSR1, &act, &old_1))
    {
        perror("sigaction () failed installing SIGUSR1 handler");
        return EXIT_FAILURE;
    }
    if (0 != sigaction(SIGUSR2, &act, &old_2))
    {
        perror("sigaction() failed installing SIGUSR2 handler");
        return EXIT_FAILURE;
    }
    // Main body of "work" during which two signals
    // will be raised, after 5 and 10 seconds, and which
    // will print last received signal
    for (int i = 1; i <= 15; i++)
    {
        if (i == 5)
        {
            if (0 != raise(SIGUSR1))
            {
                perror("Can't raise SIGUSR1");
                return EXIT_FAILURE;
            }
        }
        if (i == 10)
        {
            if (0 != raise(SIGUSR2))
            {
                perror("Can't raise SIGUSR2");
                return EXIT_FAILURE;
            }
        }
        printf("Tick #%d, last caught signal: %d\n",
            i, last_received_signal);
        sleep(1);
    }
    // Restore old signal handlers
    if (0 != sigaction(SIGUSR1, &old_1, NULL))
    {
        perror("sigaction() failed restoring SIGUSR1 handler");
        return EXIT_FAILURE;
    }
    if (0 != sigaction(SIGUSR2, &old_2, NULL))
    {
        perror("sigaction() failed restoring SIGUSR2 handler");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}
Dies gibt aus:
Tick #1, last caught signal: 0
Tick #2, last caught signal: 0
Tick #3, last caught signal: 0
Tick #4, last caught signal: 0
Tick #5, last caught signal: 30
Tick #6, last caught signal: 30
Tick #7, last caught signal: 30
Tick #8, last caught signal: 30
Tick #9, last caught signal: 30
Tick #10, last caught signal: 31
Tick #11, last caught signal: 31
Tick #12, last caught signal: 31
Tick #13, last caught signal: 31
Tick #14, last caught signal: 31
Tick #15, last caught signal: 31
Ein Selbstmordversuch mit kill ()
 Ein Prozess kann mit der Funktion kill() ein Signal an einen anderen Prozess senden (versuchen kill() . 
 Dazu muss der Sendeprozess die PID des Empfangsprozesses kennen. Da ein Prozess ohne Einführung eines Race nur von seiner eigenen PID (und den PIDs der untergeordneten Elemente) überzeugt werden kann, ist das einfachste Beispiel für die Verwendung von kill() Senden eines Signals an sich selbst. 
 Nachfolgend ein Beispiel für einen Prozess, der seine eigene Beendigung einleitet, indem er sich selbst ein Kill-Signal ( SIGKILL ) sendet: 
#define _POSIX_C_SOURCE 1
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
int main (void)
{
  pid_t pid = getpid(); /* Get my iown process ID. */
  kill(pid, SIGKILL); /* Send myself a KILL signal. */
  puts("Signal delivery initiated.");  /* Although not guaranteed, 
                                  practically the program never gets here. */
  pause(); /* Wait to die. */
  puts("This never gets printed.");
}
Ausgabe:
Killed
(... oder ähnliches, abhängig von der Implementierung)
Behandeln Sie SIGPIPE, das von write () generiert wird, fadensicher
 Wenn write() für eine benannte oder unbenannte Pipe oder einen Stream-Socket aufgerufen wird, dessen Leseende geschlossen ist, passieren zwei Dinge: 
-  SIGPIPESignal wird an den Prozess gesendet, derwrite()aufgerufen hat.
-  SIGPIPESignal wird an den Thread gesendet, derwrite()aufgerufen hat.
-  EPIPEFehler wird vonwrite()
 Es gibt verschiedene Möglichkeiten, mit SIGPIPE : 
-  Für Sockets kann SIGPIPEdeaktiviert werden, indem plattformspezifische Optionen wieMSG_NOSIGNALin Linux undSO_NOSIGPIPEin BSD festgelegt werden (funktioniert nur beimsend, nicht beimwrite). Das ist nicht portabel.
-  Für FIFOs ( SIGPIPEPipes) wirdSIGPIPEnicht generiert, wenn der WriterO_RDWRanstelle vonO_WRONLY, so dass dasO_RDWRimmer geöffnet ist. Dies deaktiviert jedoch auchEPIPE.
-  Wir können SIGPIPEignorieren oder einen globalen Handler setzen. Dies ist eine gute Lösung, die jedoch nicht akzeptabel ist, wenn Sie nicht die gesamte Anwendung steuern (z. B. Sie schreiben eine Bibliothek).
-  Bei aktuellen POSIX-Versionen können wir die Tatsache nutzen, dass SIGPIPEan den ThreadSIGPIPEwird, derwrite()aufgerufen hatwrite()und es unter Verwendung einer synchronen SignalverarbeitungstechnikSIGPIPE.
 Der folgende Code demonstriert die Thread-sichere SIGPIPE Handhabung für POSIX.1-2004 und höher. 
Es ist von diesem Beitrag inspiriert:
-  SIGPIPESie zuerstSIGPIPE, um die Maske des aktuellen Threads mithilfe vonpthread_sigmask()zu signalisieren.
-  Prüfen SIGPIPEmitsigpending()ob bereitsSIGPIPEsigpending().
-  Rufen Sie write(). Wenn dasSIGPIPEgeschlossen ist, wirdSIGPIPEzur Maske für anstehende Signale hinzugefügt undEPIPEwird zurückgegeben.
-  Wenn write()EPIPEhat undSIGPIPEvorwrite()nicht bereits anhängig war, entfernen Sie es mitsigtimedwait()aus der anstehendensigtimedwait().
-  pthread_sigmask()ursprüngliche Signalmaske mithilfe vonpthread_sigmask().
Quellcode:
#include <unistd.h>
#include <time.h>
#include <errno.h>
#include <sys/signal.h>
ssize_t safe_write(int fd, const void* buf, size_t bufsz)
{
    sigset_t sig_block, sig_restore, sig_pending;
    sigemptyset(&sig_block);
    sigaddset(&sig_block, SIGPIPE);
    /* Block SIGPIPE for this thread.
     *
     * This works since kernel sends SIGPIPE to the thread that called write(),
     * not to the whole process.
     */
    if (pthread_sigmask(SIG_BLOCK, &sig_block, &sig_restore) != 0) {
        return -1;
    }
    /* Check if SIGPIPE is already pending.
     */
    int sigpipe_pending = -1;
    if (sigpending(&sig_pending) != -1) {
        sigpipe_pending = sigismember(&sig_pending, SIGPIPE);
    }
    if (sigpipe_pending == -1) {
        pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
        return -1;
    }
    ssize_t ret;
    while ((ret = write(fd, buf, bufsz)) == -1) {
        if (errno != EINTR)
            break;
    }
    /* Fetch generated SIGPIPE if write() failed with EPIPE.
     *
     * However, if SIGPIPE was already pending before calling write(), it was
     * also generated and blocked by caller, and caller may expect that it can
     * fetch it later. Since signals are not queued, we don't fetch it in this
     * case.
     */
    if (ret == -1 && errno == EPIPE && sigpipe_pending == 0) {
        struct timespec ts;
        ts.tv_sec = 0;
        ts.tv_nsec = 0;
        int sig;
        while ((sig = sigtimedwait(&sig_block, 0, &ts)) == -1) {
            if (errno != EINTR)
                break;
        }
    }
    pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
    return ret;
}