UNIX Commands
ps Command um Prozesse zu sehen
-
Prozesszustand
R - läuft auf einem Prozessor (running)
S – vorübergehend schlafend (< 20 s), z. B. durch Aufrufe wie
sleep()I – inaktiv, schlafend (≥ 20 s)
D – ununterbrechbar schlafend, meist wegen I/O
T – angehalten oder getraced (stopped or traced)
W – ausgelagert (swapped)
Z – Zombie (zombie)
Was ist der Unterschied zwischen fork( ) und execve( )?
fork() erstellt einen Kindprozess, das heißt wir haben anschließend zwei Prozesse, diese beiden können weiter laufen, welcher P. wann arbeitet kann mittels Semaphoren gesteuert werden. execve() hingegen erzeugt einen neuen Prozess, der den jetztigen überschreibt, der ‘’alte” Code läuft nicht mehr.
int execve(const char *filename, char *const argv [], char *const envp[]);-
filename contains the path to the new program
-
argv are the command line arguments for the new process
-
envp is a string array of environment strings
-
The argv and envp arrays are terminated by the NULL pointer.
Process Creation 🎨
Welche Eigenschaften hat ein Child Process ?
After using fork( ) a child process is created. It inherits many things from the parent process.
-
Unique PID
-
CPU time set to 0
-
PPID : parent Process ID
-
Inherits file descriptors, priority, etc.
-
does not inherit file locks
Return Codes von fork()
| Rückgabewert | Bedeutung | Typische Aktion |
|---|---|---|
| 0 | Im Kindprozess | child_code(); |
| PID des Kindes | Im Elternprozess | parent_code(); |
| -1 | Fehler | error_handling(); |
switch (fork()) {
case 0: child_code(); break; // Kindprozess
case -1: error_handling(); break; // Fehler
default: parent_code(); break; // Elternprozess
}Waiting for Completion ⏰
Important
Mittels wait() oder waitpid() kann ein Elternprozess warten, biss ein Kinprozess aufgehört hat zu arbeiten.
pid t wait(int *status);
pid t waitpid(pid t wpid, int *status, int options);Was sind Zombie - Prozesse ?
Zombie Prozesse sind bekannt als :
Ein Eltern-Prozess wartet normalerweise auf die Completion von dem Kindprozess (status code). Wenn allerdings ein LKindprozess läuft, und kein Elternprozess auf diesen wartet → Zombieprozess
Auf welche Ereignisse kann man warten ?
-
DEFAULT : prozess terminiert
-
WUNTRACED → Rückkehr auch, wenn der Kindprozess gestoppt wird (Signale):
SIGTTIN,SIGTTOU,SIGTSTP,SIGSTOP -
WCONTINUED → Rückkehr auch, wenn ein gestoppter Kindprozess _fortgesetzt_wird (
SIGCONT). -
WNOHANG → Sofort zurückkehren, auch wenn noch kein Kindprozess beendet wurde (nützlich für nicht-blockierendes Warten).
Aus was stellt sich ein Status zusammen ?
-
EXIT CODE des Kindes (falls normal beendet)
-
SIGNAL, falls der Prozess durch ein Signal beendet wurde
Wie kann man einen Exit Status / Signal herauslesen ?
Mittels WEXITSTATUS() or WTERMSIG().
Die 5 Variationen von execve()
| Funktion | Search Path (PATH)? | Argumentformat | Environment-Übergabe möglich? |
|---|---|---|---|
| execl | ❌ (Pfad muss voll angegeben werden) | Liste von Strings (...) | ❌ |
| execlp | ✅ (Sucht in PATH) | Liste von Strings (...) | ❌ |
| execle | ❌ | Liste von Strings (...) + letztes Argument ist envp[] | ✅ |
| execv | ❌ | Array argv[] | ❌ |
| execvp | ✅ | Array argv[] | ❌ |
Was sind die grundsätzlichen Unterschiede zwischen den Varianten ?
-
PATH -
PATHsetzen oder nicht -
Format von argv – ob die Argumente als variadische Parameter (
...) oder als Array (argv[]) übergeben werden. -
Environment – ob du ein eigenes Environment setzen kannst.
Important
Ein Environment beinhaltet eine semi-permanente Konfiguration für Programme
Beispiel Konfigurationen des Environments :
-
PATH – the program search path
-
TERM – the kind of terminal
-
PRINTER – the user’s default printer
-
==Environment== = Satz an Key-Value-Paaren, die ein Prozess von seiner Shell/Elternprozess erbt.
-
Beispiele:
-
PATH→ Suchpfad für Programme -
TERM→ Terminal-Typ -
PRINTER→ Standarddrucker
-
Beispiele von Umgebungsvariablen 🌳
$ TESTVAR=abc
$ echo $TESTVAR
abc # Variable ist in der aktuellen Shell gesetzt
$ ./getenv TESTVAR
TESTVAR is not set # Kindprozess (Programm) sieht die Variable nicht,
# da sie nicht exportiert wurde
$ export TESTVAR
$ ./getenv TESTVAR
TESTVAR=abc # Jetzt im Environment verfügbar
$ TESTVAR=
$ ./getenv TESTVAR
TESTVAR= # Variable ist leer, aber vorhanden
$ unset TESTVAR
$ ./getenv TESTVAR
TESTVAR is not set # Variable komplett gelöschtPROCESS RESOURCE USAGE — SKIP
Solution : Semaphores 🛠️
Semaphoren sind IPC Mechanisamen - Inter Process Communication
When are Semaphores needed ?
Wir brauchen Semaphoren wenn mehrere Prozesse eine gemeinsame Ressource benutzen. Sie koordinieren den Zugriff auf kritische Abschnitte.
Was ist das Shared Memory Problem ?
Angenommen zwei Prozesse greifen auf diesselbe Speicheradresse 0x10000000 zu. Bei 0x10000000 steht der Wert 0.
P1 schreibt an dieser Stelle den Wert 42 rein. Jetzt ließt P2 den Wert bei 0x10000000 . Wird dieser 0 oder 19 sein ?
Important
Ohne eine bestimmte Reihenfolge der Abarbeitung / Plan könnte passieren :
P1 wird gestoppt
P2 wird gestoppt
Vielleicht läuft einer auf einer kleineren Priorität ?
Vielleicht gab es ein IO Problem ?
Was ist P() bei einem Semaphor ?
P steht für passeren und bedeutet ==“Ich möchte diese Ressource nutzen”==
Cases :
-
Falls der Wert des
Semaphors == 0ist → Warten -
Falls der Wert des
Semaphors >= 1→ Fortfahren, Wert um 1 ==dekrementieren==.
Was ist V() bei einem Semaphor ?
V steht für vrijgeven und bedeutet ==“Ich bin fertig und gebe die Ressource frei !”==
Cases :
-
Prozess gibt Ressourcen frei
-
Semaphor Wert wird um 1 erhöht
Important
Mittels
semget()kann man ein Semaphoren Paar anfordern.Die Operationen auf einem S-Paar werden mit
semop()durchgeführt.Ein Semaphoren Paar lässt sich mit
semctl()entfernen.
C Code Semaphor Beispiel
Create new Semaphore Set
/* create new semaphore set with n semaphores, return semid */
int new_sem(int n)
{
return semget(IPC_PRIVATE, n, SEM_A | SEM_R );
}Operation on Semaphore Sets
int operation_p(int semid) /* enter critical region */
{
struct sembuf sb;
sb.sem_num = 0;
sb.sem_flg = 0;
sb.sem_op = -1;
if (semop(semid, &sb, 1) < 0) /* 1 operation */
{
perror("semop() in operation_p()");
return 0; /* false, error */
}
return 1; /* true, success */
}Delete Semaphore Set
/* delete semaphore set semid */
int delete_sem(int semid)
{
if (semctl(semid, 0, IPC_RMID) < 0)
{
perror("semctl(sem, 0, IPC_RMID, 0)");
return 0; /* error removing semaphore */
}
return 1; /* success */
}UNIX : Shared Memory Segment
| Schritt | Funktion | Zweck |
|---|---|---|
| 1 | shmget() | Shared-Memory-Segment anlegen (gibt Segment-ID zurück) |
| 2 | shmat() | Segment in den Adressraum einbinden (Pointer erhalten) |
| 3 | Pointer nutzen | Lese-/Schreiboperationen im Shared Memory |
| 4 | shmctl() | Segment löschen oder Attribute ändern |

