1 / 30

Echtzeitbetriebssysteme Übungen

Echtzeitbetriebssysteme Übungen. M.Sc. Alexander Nitsch, M.Sc. Michael Rethfeldt (mit freundlicher Unterstützung von Dr.-Ing. Guido Moritz). Übungsfahrplan. Übung 1 – Hello World. Übung 1 – fork(). #include <stdio.h> #include <stdlib.h> int main(void) { int status; int fork_pid;

Télécharger la présentation

Echtzeitbetriebssysteme Übungen

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. EchtzeitbetriebssystemeÜbungen M.Sc. Alexander Nitsch, M.Sc. Michael Rethfeldt (mit freundlicher Unterstützung von Dr.-Ing. Guido Moritz)

  2. Übungsfahrplan

  3. Übung 1 – Hello World

  4. Übung 1 – fork() #include <stdio.h> #include <stdlib.h> int main(void) { int status; int fork_pid; fork_pid=fork() ; if ( fork_pid == 0 ) { printf("* Ich bin der Sohn. *\n"); exit(3); } else if (fork_pid == -1) { printf("Aufruf von fork() gescheitert!\n"); exit(2); } wait(&status); // warten auf Ende des Sohnes printf("wait-Status: 0x%x | 0x%x | 0x%x |\n", status, (status>>8) & 0xff, status & 0xff); return 0; } fork() fork_pid = fork_pid = fork_pid!=0 fork_pid==0 printf() exit() fork_pid!=-1 wait() printf()

  5. Übung 1 – Speicherbelegung Speicher Speicher Code beider Prozesse Code Code Daten Daten Vater Daten des Vaters Daten Daten des Sohnes

  6. Übung 1 – Wieviele Söhne werden erzeugt?

  7. Übung 1 – Wieviele Söhne werden erzeugt? Vater Vater Sohn1 Sohn1 1. fork() printf() 1. fork() Sohn2 Sohn3 Sohn2 2. fork() 2. fork() printf() 2. fork() printf() ENDE

  8. Sohn 3 PID: 3 Sohn 1 PID: 2 Sohn 4 PID: 4 Vater PID=1 Sohn 5 PID: 4 Sohn 2 PID: 3 Sohn 6 PID: 5 Übung 2 Frage: Kann es sein, dass PID=3 und PID=4 zweimal vergeben werden?

  9. Typischer Prozessbaum 3774 ? Ss 0:00 /usr/sbin/privoxy --user privoxy privoxy --pidfile 3779 ? Ss 0:00 /usr/sbin/sshd -o PidFile=/var/run/sshd.init.pid 10341 ? Ss 0:00 \_ sshd: bj [priv] 10343 ? S 0:00 | \_ sshd: bj@pts/3 10344 pts/3 Ss+ 0:00 | \_ -bash 27959 ? Ss 0:00 \_ sshd: bj [priv] 27961 ? S 0:00 \_ sshd: bj@pts/4 27962 pts/4 Ss 0:00 \_ -bash 28213 pts/4 R+ 0:00 \_ ps -fax 3834 ? S 0:00 /bin/sh /usr/bin/mysqld_safe --user=mysql 4016 ? S 0:00 \_ /usr/sbin/mysqld --basedir=/usr -- 4682 ? S 0:00 /usr/lib/AntiVir/antivir --updater-daemon 4770 ? Ss 0:00 /usr/sbin/cupsd 4815 ? Ss 0:01 /usr/sbin/nscd 4835 ? Ss 0:00 /usr/sbin/smbd -D -s /etc/samba/smb.conf 4842 ? S 0:00 \_ /usr/sbin/smbd -D -s /etc/samba/smb.conf 7378 ? S 0:04 \_ /usr/sbin/smbd -D -s /etc/samba/smb.conf 27995 ? S 0:00 \_ /usr/sbin/smbd -D -s /etc/samba/smb.conf

  10. Übung 2 #include <stdio.h> int main(void) { int var; printf(“PID(Father)=%d, var=%d\n", getpid(), var); if ( fork() == -1 ) { fprintf( stderr, "Aufruf fork() gescheitert!\n" ); } else { var++; printf(“PID=%d, var=%d\n", getpid(), var); if ( fork() == -1 ) { fprintf( stderr, "Fehler beim 2. fork()!\n"); } else { var++; printf(“PID=%d, var=%d\n", getpid(), var); } } return 0; }

  11. Übung 2 Typische Ausgaben nach stdout PID(Father): 5179, var=0 PID=5180, var=1 PID=5181, var=2 PID=5180, var=2 PID=5179, var=1 PID=5182, var=2 PID=5179, var=2

  12. Übung 2: Execl() Vater fork() Vater Sohn fork() ExternesProgramm Vater

  13. Übung 2: Execl • Fork() dient der Prozessverzweigung • Execl() dient dem Starten des externen Programmes • Nebeneffekt: • Alle Daten des Vaters werden gelöscht • Alle Filedescriptoren des Vaters werden freigegeben • Anwendung: • Starten von Programmen, z.B. init

  14. Execl()-Parametermapping int execl(const char *path, const char *arg, ...); Ausführbare Datei int execl(“/bin/ls”, “ls”, “-lias”, NULL);

  15. Übung 3 • Fork() erzeugt Kopie aller Daten des Prozesses A • Direkter Datenaustausch zwischen Prozessen nicht möglich • Ausweg: Pipe des Betriebssystems Prozess A Prozess B Betriebssystem

  16. Übung 3 • Array aus zwei File-Descriptoren: int fd[2] • Erzeugen der Pipe mit pipe() • Vererbung von fd[2] durch fork() an Sohn • Lesen: fd[0] Schreiben: fd[1] • Schließen der korrespondierenden File-Descriptoren • Writer schließt fd[0] • Reader schließt fd[1] Prozess A Prozess B Betriebssystem read(fd[0]); write(fd[1]);

  17. Übung 3 Prozess A Prozess B Initialisieren einer Pipe fd[2], File-Zähler=2 pipe(fd) Erzeugen des Sohn-Prozesses, File-Zähler=4 fork() Schließen des Lesedescriptors (fd[0]) und des Schreibdescriptors (fd[1]), File-Zähler=2 close(fd[0]) close(fd[1]) write(fd[1]) read(fd[0]) Datenaustausch über Pipe

  18. Übung 3 • Signale können jederzeit auftreten • Nebenläufige Fehlerbehandlung erfolgt in Signal-Handlern • Behandlung des Signals, sodass Hauptprogramm fehlerfrei weiterläuft ! Idealer Programmverlauf Unterbrochener Programmverlauf Signal Signal-behandlung

  19. Übung 4 • Systemweiten eindeutigen Key erzeugen • Öffnen der Nachrichtenwarteschlange (Messagequeue) • Projektidentifier proj_id kennzeichnet Nummer der Pipe Prozess A Prozess B Betriebssystem ftok(…,1) msgget() msgrcv(); ftok(…,1) ftok(…,2) msgget() msgget() msgsnd() Proj_id=1 Proj_id=2 Prozess C ftok(…,2) msgget() msgrcv();

  20. Übung 4 Was ist an welcher Schreibweise günstiger?

  21. Übung 5 – Casting von Funktionszeigern Linke Variante ist inkorrekt, da Rückgabetyp von thread_start falsch ist!

  22. Übung 5 – Typen von Funktionszeigern

  23. Übung 6 – Condition Variablen

  24. Übung 7 – Deadlock • Zwei Prozesse betreten in unterschiedlicher Reihenfolge zwei kritische Abschnitte • Kritischer Punkt: Threadumschaltung, wenn einer der Threads in einem kritischen Abschnitt ist DEADLOCK

  25. Übung 7 – Prioritäteninversion • Ein höher priorisierter Thread wird durch einen niedriger priorisierten Thread unterbrochen. • Bezeichnung: Direct Blocking

  26. Übung 7 – Pass Through Blocking

  27. Übung 7 – Priority Inheritance Protocol • PL wird auf Priorität von PH angehoben, wenn PH das Mutex anfordert • PM kommt nicht zum Zuge • Zeit im kritischen Abschnitt wird verringert • Keine Kenntnis der nutzenden Threads nötig

  28. Übung 7 – Priority Ceiling Protocol (PCP) Der Grundgedanke bei PCP ist, sicherzustellen, dass ein Prozess, der andere Prozesse in kritischen Abschnitten unterbricht und einen eigenen betritt, eine höhere Priorität in diesem Abschnitt garantieren muss als die Prioritäten aller unterbrochenen kritischen Abschnitte. Kann diese Bedingung nicht erfüllt werden, wird der Prozess blockiert. • Vermeidung von Deadlocks und Mehrfachvererbungen (Chained Blocking) [Raj91] • Einführung einer Ceiling-Konstanten c(Sj) pro Semaphor Sj • c(Sj) = Priorität des höchst-prioren Prozesses, der das Semaphor nutzen wird • Prozess P kann ein Semaphor S nur setzen, wenn seine Priorität größer als die der Ceiling-Konstanten aller nicht von P zur Zeit belegten Semaphoren ist (außer er besitzt bereits das höchst-priore Semaphor) • Kann ein Prozess ein Semaphor nicht setzen, wird die Priorität des unterbrochenen Prozessesauf die des unterbrechenden Prozesses erhöht • Einführung einer System-Ceiling-Konstanten S* zur einfacheren Berechnung Maximum aller Semaphor-Ceiling-Konstanten, die gerade genutzt werden

  29. Übung 7 – Beispiel PCP P0 P1 P2 3 Prozesse (P0, P1 & P2) konkurrieren über 3 Semaphoren (S0, S1 & S2)  Statische Prio S*=0 S*=2 S*=0 S*=0 Prio 3 2 1 S*=3 Prio-Vererbung P1P2 S*=2 Da alle Semaphore anfangs noch komplett frei sind, ist die Ceiling des Systems S* noch 0  P2 bekommt in jedem Fall S2  danach ist S* = S2 = 2 (S2 ‚begründet‘ S*)

  30. Übung 7 – Deadlockvermeidung Prio(P1) = Prio(P2) = 1 C(S1) = C(S2) = 1

More Related