Cue Column


Action Items for Self


  • PRG für Signal auszulösen

  • GEEKS4GEEK

  • [ ]

Action Items for Others


  • YT VIDEOS

  • [ ]

  • [ ]

Questions


  • Wie löse ich ein Signal aus ?

Prozesse — Signale


Was ist ein Signal ?

Ein Signal ist eine Reporting Methode für spezielle Events & wird durch mehrere Faktoren ausgelöst:

explizite Anforderung (von einem Prozess)

Es ist asynchron → Es wird nicht geplant

Beispiel : „Hey, stopp kurz, etwas Wichtiges!“

Wann entstehen Signale ?

  • Fehler – z. B. Division durch 0 → OS sendet SIGFPE (Floating Point Exception).

  • Externe Ereignisse – z. B. du drückst Ctrl+C → OS sendet SIGINT.

  • Explizite Anforderung – ein Prozess ruft kill(pid, signal) auf, um einem anderen Prozess ein Signal zu schicken.

Wie kommt ein Signal an?

  • Solange blockiert ⇒ pending (wartet).

  • Zustellung passiert an „sicheren Punkten“ (z. B. bei Systemaufrufen).

  • Danach führt der Prozess eine Aktion aus.

Was kann der Prozess?

  1. Standardaktion nehmen (z. B. beenden, stoppen, ignorieren).

  2. Ignorieren (für einige Signale erlaubt).

  3. Eigenen Handler ausführen (kleine C-Funktion).

Mini-Beispiel:

  • SIGINT (Strg+C) ⇒ Standard: beenden.

  • SIGTERM ⇒ „freundlich beenden“ (Standard von kill).

  • SIGKILLsofort beenden (kannst du nicht abfangen/ignorieren).

  • SIGCHLD ⇒ Ein Kindprozess hat seinen Status geändert (z. B. beendet).

Wann wird ein Signal Zugestellt ?

Ein Signal kann einem Prozess zugestellt werden, falls P unterbrechbar ist :

  • Verlassen eines Systemaufrufs

  • bei einem Page Fault

  • Clock Interrupt

Important

Beispiele für Signale wären :

  • Timer läuft ab

  • KindProzess läuft zu Ende oder terminiert

  • I/O Errors

  • Terminierung des Prozesses - CTRL + C

  • Teilen durch 0

Signale für den/die Shell Programmer/in 👩🏻‍💻

nohup

nohup ./long_running_process &
  • verhindert dass der Prozess nach dem Beenden des Terminals zuende ist.

trap

trap "rm $TEMP_FILE; exit" SIGHUP SIGINT SIGTERM
  • Fängt bestimmte Signale ab → Befehl wird ausgelöst

  • Hier : Falls eines der Signale auftritt, Datei löschen und saueber beenden.

kill

kill -HUP 9518
kill -1 9518  # -1 = SIGHUP
→ Schickt Signal an Prozess mit PID 9518.
int kill(pid_t pid, int sig);

Beispiel-Liste an Prozessen :

Nr.NameStandardaktionBeschreibung
1SIGHUPProzess beendenHangup (Terminal geschlossen), oft für „Reload Config“ genutzt
2SIGINTProzess beendenUnterbrechen (Ctrl+C)
3SIGQUITCore-Dump + BeendenSauber beenden, Debug-Info
4SIGILLCore-Dump + BeendenIllegale CPU-Instruktion
5SIGTRAPCore-Dump + BeendenBreakpoint erreicht (Debugging)
6SIGABRTCore-Dump + Beendenabort() aufgerufen
8SIGFPECore-Dump + BeendenDivision durch 0, Überlauf
9SIGKILLSofort beendenNicht fangbar oder ignorierbar
10SIGBUSCore-Dump + BeendenUngültiger Speicherzugriff (Bus Error)

Rest of SIGNAL LIST - SKIP

Was ist ein Signal Handler ?

Um auf ein Signal reagieren zu können, brauchen wir einen Signal handler.

void handler(int sig);
  • Parameter sig beinhaltet die Nummer des Signals

Wie sieht die Arbeitsweise eines Signal Handlers aus?

  1. ==Signal kommt an==, “normale” Codeabarbeitung wird gestoppt.
    Falls für dieses Signal schon ein Handler aktiv ist → weitere blockiert.

  2. ==Beearbeitung== : handler() aufgerufen, Variablen gesetzt.

  3. Das Signal wird unblocked- Der Prozess fägt da an, wo er aufgehört hat (als das Signal kam).

  4. ==Besonderheit==: Systemaufrufe

    • Manche System Calls (z. B. read, write, open) werden automatisch ==neu gestartet==, falls sie unterbrochen wurden.

    • Falls schon ein Teil der Daten übertragen wurde, liefern sie Partial Success zurück.

  5. ==Verhalten ändern==

    • Mit siginterrupt() kannst du festlegen, dass ein System Call nicht automatisch neu gestartet wird, sondern stattdessen mit einem Fehler (EINTR) abbricht.

Important

Beispiel:

  • Dein Programm wartet mit read() auf Eingabe.

  • Ctrl+C sendet SIGINT.

  • Dein Handler läuft → read() wird automatisch neu gestartet, außer du hast es mit siginterrupt() verboten.

Was passiert mit Signalen beim Kindprozess ? 🧑‍🧒

  • Nach dem fork() Kommando erbt der Kindprozess alle vom ElternP. installierten Signal Handler.

  • Nach [[15-05-2025]] werden alle Handler auf die default Aktion gesetzt.

  • Falls der ELternprozess ein Signal ignoriert, dann ignoriert das Kind diesen ebenfalls.

  • **SIGCHLD** bei Kind-Ende

    • Wenn ein Kindprozess beendet wird, bekommt der Elternprozess SIGCHLD.

    • Standardmäßig muss der Elternprozess dann wait() aufrufen, um den Zombie zu beseitigen.

    • Sonderfall: Wenn der Elternprozess SIGCHLD ignoriert, werden keine Zombies erstellt.

Jetzt sigaction() anstatt von signal() - Warum ?

  • Speichern der ursprünglichen Signalbehandlung → Saven wie es davor behandelt wurde, und anschließend zurücksetzen.

  • In der Lage, andere Signale zu blockieren, während der Signal Handler läuft. → Verhindern, dass Code inmnerhalb einer kritischen Operation unterbrochen wird.

Definition von sigaction()


Funktionsprototyp

int sigaction(int sig,
              const struct sigaction *act,
              struct sigaction *oact);
  • sig: Welche Signalnummer (z. B. SIGINT, SIGTERM).

  • act: Neue Behandlung für dieses Signal (zeigt auf eine befüllte struct sigaction).

  • oact: (optional) OLD ACT - Hierhin schreibt der Kernel die alte Behandlung zurück. NULL, wenn du sie nicht brauchst.

  • Rückgabe: 0 bei Erfolg, -1 bei Fehler (Details in errno).


DatenStruktur

struct sigaction {
    union {
        void (*sa_handler)(int);  // einfacher Handler
        void (*sa_sigaction)(int, siginfo_t *, void *); // erweiterte Infos
    } __sigaction_u;
    sigset_t sa_mask;   // blockierte Signale während Handler läuft
    int sa_flags;       // Optionen (z. B. SA_RESTART)
};
  • sa_handler: Zeiger auf deinen einfachen Handler void handler(int sig).

  • sa_sigaction: Alternative erweiterte Handler-Signatur mit Zusatzinfos (siginfo_t), wenn du SA_SIGINFO nutzt.

  • sa_mask: Eine Signalmaske. Alles, was du hier einträgst, wird zusätzlich blockiert, während der Handler läuft.

  • sa_flags : Zusätzlich setzbare Flags

GrundIdee der Nutzung

struct sigaction action;
sigset_t signal_mask;
 
/* 1) Maske vorbereiten: Was soll während des Handlers blockiert sein? */
sigfillset(&signal_mask);
// Praxis: oft gezielt mit sigemptyset(&signal_mask); sigaddset(&signal_mask, SIGINT);
 
/* 2) Struktur befüllen */
action.sa_handler = handler;   // deine Handler-Funktion
action.sa_mask = signal_mask;  // blockierte Signale während Handler
action.sa_flags = 0;           // keine Spezialoptionen
 
/* Handler installieren */
sigaction(SIGTERM, &action, NULL);

Code Example eines Signal Handlers

\#include <stdio.h>
\#include <stdlib.h>
\#include <signal.h>
\#include <unistd.h>
 
/* Global flag to tell the main loop to exit */
volatile sig_atomic_t stop = 0;
 
/* Signal handler function */
void handle_sigint(int sig) {
    (void)sig;  // unused parameter
    write(STDOUT_FILENO, "\nCaught SIGINT, cleaning up...\n", 31);
    stop = 1;   // set flag to stop main loop
}
 
int main() {
    struct sigaction action;
 
    /* Configure handler */
    action.sa_handler = handle_sigint;
    sigemptyset(&action.sa_mask);   // don't block any other signals
    action.sa_flags = SA_RESTART;   // restart interrupted syscalls
 
    /* Install handler for SIGINT */
    if (sigaction(SIGINT, &action, NULL) == -1) {
        perror("sigaction");
        exit(EXIT_FAILURE);
    }
 
    printf("Running... press Ctrl+C to stop.\n");
 
    /* Main loop */
    while (!stop) {
        printf("Working...\n");
        sleep(1);  // simulate work
    }
 
    printf("Program exiting cleanly.\n");
    return 0;
}
void psignal(unsigned sig, const char *s);
print message according to signal number sig
 
char * strsignal(int sig);
return pointer to message according to signal number sig

Beispiele für Signal Handler

SIGCHILD - Zombie Prozesse vermeiden

void reapchild(int signo) {
    while (waitpid(-1, NULL, WNOHANG) > 0);
}

SIGURG - Urgent TCP Data

static volatile sig_atomic_t recvurg;
 
static void sigurg(int signo) {
    recvurg = 1;
}
  • Der Handler setzt nur eine globale Variable

SIGQUIT - handle Quit from keyboard

static void sigquit(int signo) {
    syslog(LOG_ERR, "got signal %d", signo);
    dologout(1);
}

Signal Handler - Summary

  • short : do only one thing

  • indicate use with global variable volatile int

  • not time-consuming

  • NO functional features

  • NOT continue on program bugs (SIGBUS, SIGSEGV, SIGFPE)

The Password Encryption/Hash

Hash Methoden :

  • DES cipher

  • MD5 hash

  • SHA-256 hash

  • SHA-512 hash

Attacks

  • Inversion of Hashing / Encryption

    • Crypto Research Topic

  • dictionary attack - variations of dictionary words

  • brute corce - exhaustive search

Dictionary Attack

  • 2¹⁷ words in German Duden

Brute Force Attack

  • 2¹²⁸ Bit Strings of length 128

Defenses against inverting Crypto Hashes with brute force

  • salt

  • long passwds / special chars

  • CPU / RAM intensive operations

Important

good openSSL password : openssl rand -base64 9
nCJewLUeXrUU
9 bytes = 72 bits = 12 base64–characters



Summaries


Important