CS计算机代考程序代写 Betriebssysteme

Betriebssysteme
Besprechung: 1. Prozesse
https://ess.cs.tu-dortmund.de/DE/Teaching/SS2020/BS/
Horst Schirmeier
horst.schirmeier@tu-dortmund.de
https://ess.cs.tu-dortmund.de/~hsc
AG Eingebettete Systemsoftware mit Material von Olaf Spinczyk, Informatik 12, TU Dortmund Universität Osnabrück

Theoriefrage 1
Wie unterscheiden sich die folgenden Kommandos?
a) cat a.txt > b.txt
Der Inhalt von a.txt wird nach b.txt geschrieben
b) cat a.txt >> b.txt
Wie a), allerdings wird der Inhalt in b.txt angehangen
2

Theoriefrage 2
2. Erklärt in eigenen Worten die Ausgabe des folgenden Kommandos:
ls | grep -c .pdf
– ls listet alle (nicht versteckten) Dateien und Ordner im aktuellen Verzeichnis – grep -c zählt die Zeilen, welche „(beliebiges Zeichen) pdf“ enthalten
(d.h. insbesondere diejenigen, die auf „.pdf “ enden)
– | verbindet die Ausgabe von ls mit der Eingabe von grep
– ls | grep -c .pdf gibt die Anzahl der (nicht versteckten) PDF Dateien im aktuellen Verzeichnis aus
3

Theoriefrage 3
3. Was versteht man unter einem „verwaisten“ Prozess? Wie verändert sich beim „Verwaisen“ die Prozesshierarchie?
– Ein Prozess, dessen Elternprozess terminiert ist
– Verwaiste Prozesse werden vom init-Prozess (PID 1) adoptiert
4

Theoriefrage 4
for (;;) fork();
Was ist das Problem bei der Ausführung von diesem Code?
Jedes fork startet einen neuen Prozess
Dem Betriebssystem gehen irgendwann die PIDs aus
→ Es können keine weiteren Prozesse gestartet werden
Hohe CPU-Last, Speicherverbrauch etc. Umgangssprachlich: „fork-Bombe” Beschränkung durch limits.conf(5) möglich
● ●
● ● ●
5

Theoriefrage 3
for (;;) fork();
Verhalten in der 1. 2. 3. n. Generation?
Generation
1
2
3
n
Prozesse
6

Theoriefrage 3
for (;;) fork();
Verhalten in der 1. 2. 3. n. Generation?
Generation
1
2
3
n
Prozesse
1
2
4
2n-1
→ Exponentielles Wachstum
7

Programmierung in C – Teil a)
Einlesen von Standardeingabe, Anzeigen der Auswahl

#define NAPPS 3
#define NAPPS 3
// Ausgabe der Programme
// Ausgabe der Programme
void printApps(char const *apps[]) {
void printApps(char const *apps[]) {
printf(“Programme:\n”);
printf(“Programme:\n”);
for (int i = 0; i < NAPPS; i++) { for (int i = 0; i < NAPPS; i++) { printf(" %d. %s\n", i, apps[i]); printf(" %d. %s\n", i, apps[i]); } } } } int main() { int main() { // die Anwendungen definieren // die Anwendungen definieren char const *apps[NAPPS]; char const *apps[NAPPS]; apps[0] = "ps"; apps[0] = "ps"; apps[1] = "date"; apps[1] = "date"; apps[2] = "ls"; apps[2] = "ls"; printApps(apps); printApps(apps); ... ... 8 Programmierung in C – Teil a) Einlesen von Standardeingabe, Anzeigen der Auswahl ● ... ... // Nutzereingabe gültig? // Nutzereingabe gültig? if (input < 0 || input >= NAPPS) {
if (input < 0 || input >= NAPPS) {
printf(“Ungültige Eingabe: %d\n”, input);
printf(“Ungültige Eingabe: %d\n”, input);
return EXIT_FAILURE;
return EXIT_FAILURE;
}
}
// Auswahl ausgeben
// Auswahl ausgeben
char const *cmd = apps[input];
char const *cmd = apps[input];
printf(“Es wurde %s gewählt\n”, cmd);
printf(“Es wurde %s gewählt\n”, cmd);
9

Programmierung in C – Teil b)
Starten von Programmen (ergänzt Code aus Teil a)

// Auswahl in neuem Prozess ausführen
// Auswahl in neuem Prozess ausführen
pid_t pid;
pid_t pid;
pid = fork();
pid = fork();
if (pid == -1) {
if (pid == -1) {
// — Fehlerbehandlung weggelassen
// — Fehlerbehandlung weggelassen
} else if (pid > 0) { // Elternprozess
} else if (pid > 0) { // Elternprozess
// Status lesen und beenden
// Status lesen und beenden
int status;
int status;
waitpid(pid, &status, 0); // — Fehlerbehandlung wegg. waitpid(pid, &status, 0); // — Fehlerbehandlung wegg.
printf(“PID von %s: %d\n\n”, cmd, pid);
printf(“PID von %s: %d\n\n”, cmd, pid);
return status;
return status;
} else { // Kindprozess
} else { // Kindprozess
execlp(cmd, cmd, NULL);
execlp(cmd, cmd, NULL);
perror(“Fehler beim Ausführen des Programms”);
perror(“Fehler beim Ausführen des Programms”);
return EXIT_FAILURE;
return EXIT_FAILURE;
}
}
10

Programmierung in C – Teil c)




Eine weitere „App“ namens „exit“ in das App-Array aufnehmen, bei deren Auswahl Programm beenden:
Schleife:
alles in while (1) { … } einbetten
Nach scanf(…): im Eingabepuffer verbleibende Zeichen „entsorgen“
// stdin leeren
// stdin leeren
int c; int c;
while ((c = getchar()) != ‘\n’ && c != EOF);
while ((c = getchar()) != ‘\n’ && c != EOF);
// Programmende bei exit
// Programmende bei exit
if (input == 3) {
if (input == 3) {
return EXIT_SUCCESS;
return EXIT_SUCCESS;
}
}
11

Programmierung in C – Teil d)
Abfragen des Makros WIFEXITED und entsprechende Ausgabe

if (WIFEXITED(status)) {
if (WIFEXITED(status)) {
printf(“Prozess wurde ordnungsgemäß beendet,” printf(“Prozess wurde ordnungsgemäß beendet,”
“Exit Status = %d\n”, WEXITSTATUS(status));
“Exit Status = %d\n”, WEXITSTATUS(status));
} else {
} else {
printf(“Prozess wurde nicht ordnungsgemäß beendet.” printf(“Prozess wurde nicht ordnungsgemäß beendet.”
“Exit Status Code: %d\n”, WEXITSTATUS(status)); “Exit Status Code: %d\n”, WEXITSTATUS(status));
}
}
12

Programmierung in C – Zusatzaufgabe
Zusätzlich nach App-Auswahl die Argumente einlesen
„maximal 100 Zeichen“ plus Null-Terminator, also 100+1


13
// Argumente einlesen
// Argumente einlesen
printf(“Argumente: “);
printf(“Argumente: “);
char in[100+1];
char in[100+1];
fgets(in, sizeof(in), stdin); // — Fehlerbehandlung fgets(in, sizeof(in), stdin); // — Fehlerbehandlung
// evtl. Newline am Ende entfernen
// evtl. Newline am Ende entfernen
in[strcspn(in, “\n”)] = 0;
in[strcspn(in, “\n”)] = 0;
// Array für Argumente: 10 + Programmname (1) + NULL-Terminator
// Array für Argumente: 10 + Programmname (1) + NULL-Terminator
char const *args[10 +1 +1];
char const *args[10 +1 +1];
// 1. Argument ist der Programmname
// 1. Argument ist der Programmname
int n = 0;
int n = 0;
args[n++] = cmd;
args[n++] = cmd;
args[n++] = strtok(in, ” “);
args[n++] = strtok(in, ” “);
char *p;
char *p;
while ((p = strtok(NULL, ” “)) != NULL && n <= 10) { while ((p = strtok(NULL, " ")) != NULL && n <= 10) { args[n++] = p; args[n++] = p; } } args[n] = NULL; // Terminator args[n] = NULL; // Terminator // ... zusätzlich Änderung des exec*-Aufrufs: // ... zusätzlich Änderung des exec*-Aufrufs: execvp(cmd, (char **) args); execvp(cmd, (char **) args);