Prozesse - Koblenz
Transcrição
Prozesse - Koblenz
Übung zu Grundlagen der Betriebssysteme 6. Übung 20.11.2012 Prozess & Programm Erläutern Sie den Begriff Prozess und unterscheiden Sie die Begriffe Prozess und Programm voneinander. • Verwaltet ein in Ausführung befindliches Programm und die dazugehörigen Betriebsmittel → die Abstraktion eines Programms während der Ausführung • Prozesse befinden sich immer in genau einem der folgenden Zustände: Prozess & Programm Prozess & Programm Prozesse sind • aktive Komponenten • befinden sich in Ausführung • können voneinander abhängen • zwischen Prozessen kann es Konflikt-Situation geben • benutzen Ressource (Betriebsmittel) • Prozessinterkommunikation ermöglicht Synchronisation zwischen Prozessen • haben einen Zustand • Strategien legen fest, wie mit Prozessen verfahren wird Vorlesung: Prof. Frey: 04-processes, S.5 Aufgabe 1 a) Erläutern sie mit wenigen Worten die 5 Zustände eines Prozesses aus dem Prozesszustands-Diagramm. b) Gehen sie auf den Zustand „waiting“ näher ein und erläutern und begründen sie mit wenigen Worten, ob auf diesen Zustand auch verzichtet werden könnte! Aufgabe 1 new + terminated: • Prozesse, die den Rechner gerade betreten bzw., ihn nach vollständiger Bearbeitung verlassen. • Sie entstehen, wenn ein neuer Benutzer sich "einloggt", ein bestehender Prozess einen Subprozess bildet oder ein Dienst angeboten wird. • Ein initiierter Prozess gleicht dem Zustand ready, allerdings mit dem Unterschied, das in der Prozesstabelle noch kein Eintrag für einen Prozesskontrollblock existiert. • Terminierte Prozesse werden in der Regel mit allen Datenstrukturen gelöscht. • In UNIX wird der Prozesskontrollblock allerdings solange gespeichert, wie der unmittelbare Elternprozess läuft. Dieser hat die Möglichkeit mit einem Systemaufruf den Terminierungsstatus zu erfragen Aufgabe 1 ready: • Prozesse, die ihren Ablauf fortsetzen können, befinden sich im Zustand ready. Sie warten lediglich auf die Prozessorzuteilung • Der Prozess besitzt alle Ressourcen und wartet auf die Zuteilung eines Prozessors Aufgabe 1 running: • Im Zustand running wird der Prozess auf dem Prozessor ausgeführt Aufgabe 1 waiting: • Prozesse im Zustand waiting warten auf bestimmte Ereignisse, die für den weiteren Prozessablauf notwendig sind, z.B. Zuteilung von Speicherplatz, und sind daher blockiert. • Wird auch als bedingtes Umschalten bezeichnet, weil der Prozesswechsel davon abhängt, ob eine Bedingung erfüllt ist. Ein Problem existiert jedoch darin, dass zwischen Auswertung der Bedingung und der darauffolgenden Aktion ein Prozesswechsel stattfinden kann. Hier müssen dann Mechanismen der Prozesskoordination greifen. • Blockierte Prozesse konkurrieren mit anderen Prozessen um die Zuteilung des Prozessors. Aufgabe 1 Ist waiting notwendig? Process Control Block Informationen über einen Prozess werden im Process Control Block (PCB) gehalten: Der PCB enthält unter anderem: • Prozesszustand • Registerinhalte der CPU, z.B. Befehlszähler und Stack-Zeiger • Zugeordnete Hauptspeicherbereiche, z.B. für den Programm-Code und den Datenbereich, z.B. für globale Variablen • Zugeordnete Ressource, z.B. Peripheriegeräte und geöffnete Dateien • Prozesserzeugniszeitpunkt • Priorität • Verbrauchte Rechenzeit • User-ID → die Nummer des Benutzers dem der Prozess gehört • Prozess-ID des Vaterprozesses • Umgebung des Prozesses, u.a. das Arbeitsverzeichnis Prozess-Tabelle (Linux -> top) top - 13:53:20 up 21 days, 41 min, 2 users, load average: 0.00, 0.01, 0.05 Tasks: 67 total, 1 running, 66 sleeping, 0 stopped, 0 zombie Cpu(s): 0.0%us, 0.3%sy, 0.0%ni, 99.7%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1025336k total, 382160k used, 643176k free, 90452k buffers Swap: 511996k total, 7612k used, 504384k free, 240620k cached PID 592 31164 1 2 3 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 USER syslog root root root root root root root root root root root root root root root root root root root root PR 20 20 20 20 20 20 RT RT 0 0 20 0 20 20 0 0 0 20 0 20 20 NI VIRT RES SHR S %CPU %MEM 0 30432 980 980 S 0.3 0.1 0 2724 1088 864 R 0.3 0.1 0 3508 1544 1120 S 0.0 0.2 0 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 -20 0 0 0 S 0.0 0.0 -20 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 -20 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 -20 0 0 0 S 0.0 0.0 -20 0 0 0 S 0.0 0.0 -20 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 -20 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 0 0 0 0 S 0.0 0.0 TIME+ 0:37.74 0:00.01 0:00.71 0:00.00 0:08.40 0:00.30 0:00.00 0:07.00 0:00.00 0:00.00 0:00.00 0:00.00 0:03.08 0:00.09 0:00.00 0:00.00 0:00.00 0:00.00 0:00.00 0:13.45 0:00.31 COMMAND rsyslogd top init kthreadd ksoftirqd/0 kworker/u:0 migration/0 watchdog/0 cpuset khelper kdevtmpfs netns sync_supers bdi-default kintegrityd kblockd ata_sff khubd md kworker/0:1 kworker/u:1 Prozess-Tabelle (Linux -> htop) Prozess-Tabelle (Windows -> Task-Manager) • Leerlaufprozess Leerlaufprozess • Der Leerlaufprozess (engl. idle task) ist ein „Pseudo“-Prozess, der in vielen Betriebssystemen immer dann Prozessorzeit bekommt, wenn kein anderer Prozess ausgeführt wird. • In dem Betriebssystem Windows wird der Leerlaufprozess im Taskmanager im Reiter „Prozesse“ immer angezeigt und zeigt ungenutzte Rechenzeit, also die Kapazität, die nicht von Anwendungen beansprucht wird. • Die Summe der Anteile aller laufenden Prozesse an der Prozessorauslastung (einschließlich des Leerlaufprozesses) beträgt daher immer 100 %. • Auf unixähnlichen Betriebssystemen ist in der Regel das KommandozeilenProgramm top installiert, das in der dritten Zeile einen mit id (für idle task, s. o.) markierten Wert für den prozentualen Anteil des Leerlaufprozesses an der Gesamtauslastung aller Prozessoren des Systems ausgibt. Aufgabe 2 a) Kompilieren und Starten sie das folgende Programm „father_son.c“ unter Linux und erläutern Sie die Ausgabe im Bezug auf die Variable „i“. Beziehen Sie sich dabei auch auf die Zeile if (fork() ) und was hier passiert. #include <stdio.h> #include <stdlib.h> int i; int rnd; void main(){ if (fork()) for (i=0; i<500; i++){ printf("\n Father: %i", i); sleep(1); } else for (i=0; i<500;i++){ printf("\n Son: %i", i); rnd=rand(); sleep(rnd%3); } } Aufgabe 2 bs@bsuebung:~$ ./father_son Father: Son: 0 Father: Son: 1 Son: 2 Father: Son: 3 Father: Son: 4 Father: Son: 5 Father: Son: 6 Son: 7 Son: 8 Father: Son: 9 Father: Father: Son: 10 Father: Son: 11 Father: Father: Son: 12 Father: Son: 13 0 1 2 3 4 5 6 7 8 9 10 11 12 Aufgabe 2 bs@bsuebung:~$ ./father_son Father: Son: 0 Father: Son: 1 Son: 2 Father: Son: 3 Father: Son: 4 Father: Son: 5 Father: Son: 6 Son: 7 Son: 8 Father: Son: 9 Father: Father: Son: 10 Father: Son: 11 Father: Father: Son: 12 Father: Son: 13 0 1 2 3 4 5 6 7 8 9 10 11 12 Aufgabe 2 b) Der Befehl ps -elf --forest gibt ihnen eine Tabelle mit verschiedenen Spalten aus. Recherchieren sie die Angabe in den folgenden Spalten und erläutern sie sie mit wenigen Worten. (1) F (2) S (3) UID (4) PID (5) PPID (6) PRI (7) SZ (8) WCHAN (9) TIME (10) CMD Aufgabe 2 root@bsuebung:~# ps F S UID PID PPID ... 0 S bs 2129 1934 1 S bs 2130 2129 4 R root 2164 1431 -elf C PRI NI ADDR SZ WCHAN 0 0 0 80 80 80 0 0 0 - STIME TTY TIME CMD 454 hrtime 10:51 pts/1 00:00:00 ./father_son 454 hrtime 10:51 pts/1 00:00:00 ./father_son 1252 10:52 pts/0 00:00:00 ps -elf -e → select all processes, Identical to -A -l → long format -f → full-format listing ps -elf -e listet alle Prozesse des Systems auf -lf beeinflussen lediglich die Formatierung der Ausgabe Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Aufgabe 2 Erweitern Sie das Programm „father_son.c“ so, das die Variable „i“ in einem gemeinsamen Speicher abgelegt wird und alle erzeugten Prozesse auf eine Variable zugreifen und diese hoch zählen. (Benutzen Sie für die Lösung POSIX Shared Memory). Aufgabe 2 #include #include #include #include #include #include <stdio.h> <sys/types.h> <sys/ipc.h> <sys/shm.h> <sys/wait.h> <stdlib.h> #define MAXCOUNT 1000000 #define SHMSEGSIZE sizeof(int) int main(){ int i, shmID, *shared_mem, count=0, total=0,rnd; shmID = shmget(IPC_PRIVATE, SHMSEGSIZE, IPC_CREAT | 0644); shared_mem = (int*)shmat(shmID,0,0); *shared_mem = 0; if (fork()) for (i=0; i<500; i++){ *shared_mem+=1; printf("\n Father: %i", *shared_mem); sleep(1); } else for (i=0; i<500;i++){ *shared_mem+=1; printf("\n Son: %i", *shared_mem); rnd=rand(); sleep(rnd%3); } shmdt(shared_mem); shmctl(shmID, IPC_RMID, 0); return 0; } Aufgabe 2 Erläutern Sie mit wenigen Worten welches neue Problem mit der Lösung von Aufgabe 2d) bzgl. der Variable i und der darauf zugreifenden Prozesse entstanden ist! Aufgabe 2 :~# ./fatherSonShared Father: Son: 2 Father: Son: 4 Son: 6 Father: Son: 7 Father: Son: 9 Father: Son: 11 Father: Son: 13 Son: 15 Son: 16 Father: Son: 17 Father: Father: Son: 19 Father: Son: 22 Father: Father: Son: 24 Father: Son: 27 Father: Father: Son: 29 Father: Son: 32 Son: 34 Son: 35 Father: 1 3 5 8 10 12 14 18 20 21 23 25 26 28 30 31 33 Interprozesskommunikation (IPC) Systembefehle für Shared Memory • #include <sys/shm.h> shmget (allocates shared memory) → legt ein neues Segment an bzw. greift auf ein bestehendes Segment zu. • shmat (shared memory attach) → hängt ein Shared Memory-Segment an den Adressraum eines Prozesses an. • shmdt (shared memory detach) → entfernt ein Shared Memory-Segment aus dem Adressraum des aufrufenden Prozesses. • shmctl (shared memory control) → führt Steuerungsfunktionen auf einem Shared Memory-Segment durch. Interprozesskommunikation (IPC) Shared Memory Aufgabe 3 Über die Manpage des Befehls ps (man ps) können sie die verschiedenen Prozess-State-Codes ablesen, die ein Prozess einnehmen kann. Kompilieren und Starten sie das folgende Programm ynlahd.c # gcc -o ynlahd ynlahd.c -> ./ynlahd #include #include #include #include <stdlib.h> <unistd.h> <stdio.h> <wait.h> int main () { if (fork()) { //Father process printf("Father waits\n"); sleep(60); printf("Father stops waiting\n"); } else { //Son process printf("Son starts\n"); int i=0; for(i=0;i<=10;i++) printf("Son counts %d\n",i); printf("Son exits\n"); exit (1); } return 0; } Aufgabe 3 • • • • Welcher besondere Zustand wird hier vom "Son"-Prozess eingenommen? Betrachten Sie während der Laufzeit des obigen Programms die Prozess-Status Tabelle mit ps –elf. Geben Sie den relevanten Teil der Ausgabe hier an. Was ist besonders an dem Zustand des "Son"-Prozesses. F S UID PID PPID C PRI NI ADDR SZ WCHAN 0 S root 15344 14679 0 80 0 - 1 Z root 15345 15344 0 80 0 - 4 R root 15350 15289 0 80 0 - STIME TTY TIME CMD 454 hrtime 16:24 pts/0 00:00:00 ./ynlahd 0 exit 1253 - 16:24 pts/0 00:00:00 [ynlahd]<defunct> 16:25 pts/1 00:00:00 ps -elf Aufgabe 3 Zombie-Prozess: Als Zombie wird ein Prozess bezeichnet, der beendet wurde, aber trotzdem noch in der Prozesstabelle des Betriebssystems auftaucht und auch geringfügig Systemressourcen belegt. Zombie-Prozesse richten selbst keinen Schaden an, können aber auf Fehlfunktionen hinweisen. F S UID PID PPID C PRI NI ADDR SZ WCHAN 0 S root 15344 14679 0 80 1 Z root 15345 15344 0 80 4 R root 15350 15289 0 80 0 0 0 - STIME TTY TIME 454 hrtime 16:24 pts/0 00:00:00 ./ynlahd 0 exit 16:24 pts/0 00:00:00 [ynlahd]<defunct> 1253 16:25 pts/1 00:00:00 ps -elf PROCESS STATE CODES: Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the state of a process: D R S T W X Z CMD uninterruptible sleep (usually IO) running or runnable (on run queue) interruptible sleep (waiting for an event to complete) stopped, either by a job control signal or because it is being traced. paging (not valid since the 2.6.xx kernel) dead (should never be seen) defunct ("zombie") process, terminated but not reaped by its parent. Aufgabe 3 Aufgabe 3 Zombie-Prozess Was müsste im "Father"-Prozess wie verändert werden damit das Programm korrekt abläuft? #include #include #include #include <stdlib.h> <unistd.h> <stdio.h> <wait.h> int main () { if (fork()) { //Father process printf("Father waits\n"); wait(0) //-> sleep(60) → wait(0) oder waitpid(pid_t) printf("Father stops waiting\n"); } else { //Son process printf("Son starts\n"); int i=0; for(i=0;i<=10;i++) printf("Son counts %d\n",i); printf("Son exits\n"); exit (1); } return 0; }