> Übung Betriebssysteme



Ähnliche Dokumente
Binäre Bäume. 1. Allgemeines. 2. Funktionsweise. 2.1 Eintragen

Fakultät Angewandte Informatik Lehrprofessur für Informatik

Vorkurs C++ Programmierung

1 Vom Problem zum Programm

Zählen von Objekten einer bestimmten Klasse

Folge 19 - Bäume Binärbäume - Allgemeines. Grundlagen: Ulrich Helmich: Informatik 2 mit BlueJ - Ein Kurs für die Stufe 12

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Grundlagen von Python

Tutorium Rechnerorganisation

4. Jeder Knoten hat höchstens zwei Kinder, ein linkes und ein rechtes.

Einführung in die Programmierung Laborübung bei Korcan Y. Kirkici. 12.Übung bis

MetaQuotes Empfehlungen zum Gebrauch von

Tutorium Informatik 1. Aufgabe 2: Formatierte Ein- und Ausgabe

4D Server v12 64-bit Version BETA VERSION

desk.modul : WaWi- Export

Liesmich zum Kurs: Programmieren in der Bioinformatik mit Perl Konfigurierung der Programmierumgebung

Suchbäume. Annabelle Klarl. Einführung in die Informatik Programmierung und Softwareentwicklung

C++ Grundlagen. ++ bedeutet Erweiterung zum Ansi C Standard. Hier wird eine Funktion eingeleitet

Workshop: Eigenes Image ohne VMware-Programme erstellen

Programmierkurs Java

Karlsruher Institut für Technologie

Informatik Grundlagen, WS04, Seminar 13

Die Programmiersprache C99: Zusammenfassung

Automatisierung ( Fernsteuerung ) von Excel unter Microsoft Windows Tilman Küpper (tilman.kuepper@hm.edu)

1. Übung zu "Numerik partieller Differentialgleichungen"

Übungen zu Einführung in die Informatik: Programmierung und Software-Entwicklung: Lösungsvorschlag

Virtueller Seminarordner Anleitung für die Dozentinnen und Dozenten

Professionelle Seminare im Bereich MS-Office

Matrix42. Use Case - Sicherung und Rücksicherung persönlicher Einstellungen über Personal Backup. Version September

Thermoguard. Thermoguard CIM Custom Integration Module Version 2.70

Modellierung und Programmierung 1

SCHNELLEINSTIEG ZUM TOOL NODEBUILDER

Übung: Verwendung von Java-Threads

Es sollte die MS-DOS Eingabeaufforderung starten. Geben Sie nun den Befehl javac ein.

Übungspaket 31 Entwicklung eines einfachen Kellerspeiches (Stacks)

Zugriff auf die Modul-EEPROMs

Übung 9 - Lösungsvorschlag

Leitfaden zur ersten Nutzung der R FOM Portable-Version für Windows (Version 1.0)

Version 0.3. Installation von MinGW und Eclipse CDT

Computeria Solothurn

Windows Server 2012 R2 Essentials & Hyper-V

Objektorientierte Programmierung für Anfänger am Beispiel PHP

Einrichtung des Cisco VPN Clients (IPSEC) in Windows7

Was ist PDF? Portable Document Format, von Adobe Systems entwickelt Multiplattformfähigkeit,

Prozeß P1 Prozeß P2. Zur Synchronisation stehen den beiden Prozessen binäre Semaphore und die beiden Funktionen

Informatik 1 Tutorial

Einführung in die C-Programmierung

Einführung in die Informatik für Naturwissenschaftler und Ingenieure (alias Einführung in die Programmierung)

Künstliches binäres Neuron

Java Kurs für Anfänger Einheit 5 Methoden

Algorithmen & Datenstrukturen 1. Klausur

Leitfaden zur Installation von Bitbyters.WinShutdown

Einführung in Java. PING e.v. Weiterbildung Andreas Rossbacher 24. März 2005

2. Darstellung von Information im Computer

2. Konfiguration der Adobe Software für die Überprüfung von digitalen Unterschriften

Qt-Projekte mit Visual Studio 2005

mit dem TeXnicCenter von Andreas Both

Java Einführung Collections

Einführung in die Programmierung

Algorithmen und Datenstrukturen Suchbaum

M. Graefenhan Übungen zu C. Blatt 3. Musterlösung

Step by Step Webserver unter Windows Server von Christian Bartl

Zugriff auf Daten der Wago über eine Webseite

Internet Explorer Version 6

Einführung in die Java- Programmierung

Objektorientierte Programmierung

Kommunikations-Parameter

Klausur in Programmieren

Java Virtual Machine (JVM) Bytecode

Alte Software auf neuer Hardware, Neue Software auf alter Hardware

2 DAS BETRIEBSSYSTEM. 2.1 Wozu dient das Betriebssystem. 2.2 Die Bildschirmoberfläche (Desktop) Themen in diesem Kapitel: Das Betriebssystem

Artikel Schnittstelle über CSV

Vorkurs Informatik WiSe 15/16

The ToolChain.com. Grafisches Debugging mit der QtCreator Entwicklungsumgebung

QUICK INSTALLATION GUIDE

PROGRAMMIEREN MIT C. }, wird kompiliert mit dem Befehl. (-o steht für output) und ausgeführt mit dem Befehl

Werkzeuge der Informatik UNIX

Installation der SAS Foundation Software auf Windows

Programmierung für Mathematik (HS13)

Datentypen: Enum, Array, Struct, Union

Übung 9. Quellcode Strukturieren Rekursive Datenstrukturen Uebung 9

Applet Firewall und Freigabe der Objekte

1 Einleitung. Lernziele. Symbolleiste für den Schnellzugriff anpassen. Notizenseiten drucken. eine Präsentation abwärtskompatibel speichern

Wie halte ich Ordnung auf meiner Festplatte?

Programmierung in C. Grundlagen. Stefan Kallerhoff

KVIrc installieren (win) i. KVIrc installieren (win)

Herzlich Willkommen bei der nfon GmbH

ABB i-bus KNX. Software-Information. Melde- und Bedientableau. Typ: MT 701.2

Java Script für die Nutzung unseres Online-Bestellsystems

Der neue persönliche Bereich/die CommSy-Leiste

Informatik I Tutorial

ICS-Addin. Benutzerhandbuch. Version: 1.0

Programmieren für Ingenieure Sommer Ein Rechner. Rechner sind überall. Gerät, das mittels programmierbarer Rechenvorschriften Daten verarbeitet.

OPERATIONEN AUF EINER DATENBANK

Überprüfung der digital signierten E-Rechnung

Einführung in die Programmierung

Wie können Sie eine Client Lizenz wieder freigeben?

Datei Erweiterungen Anzeigen!

Sortierte Folgen 250

Transkript:

> Übung Betriebssysteme Übung 3 Michel Steuwer Wintersemester 2012/13 Gruppe Parallele und Verteilte Systeme (PVS) Institut für Informatik Westfälische Wilhelms-Universität Münster

Organisatorisches 2 Die Vorlesung am Donnerstag, den 8. November 2012, findet wegen des Hochschultags nicht statt.

1. Übungsblatt 3 Aufgabe 1 Dynamische Speicherverwaltung in C a) Verwendung von malloc und free b) Fehlersuche Aufgabe 2 Binärer Baum in C

Aufgabe 1 a): Verwendung von malloc und free 4 Vervollständigung eines Programms zur dynamischen Speicherverwaltung Anlegen und Freigeben von Speicherbereichen soll überwacht werden monitoring alloc.c: Anlegen und Freigeben von Speicherblöcken. Ablage der reservierten Blöcke in einem Array (alloc blocks) Maximale Anzahl von reservierten Blöcken: MAX ALLOCATIONS

Aufgabe 1 a): Verwendung von malloc und free 4 Vervollständigung eines Programms zur dynamischen Speicherverwaltung Anlegen und Freigeben von Speicherbereichen soll überwacht werden monitoring alloc.c: Anlegen und Freigeben von Speicherblöcken. Ablage der reservierten Blöcke in einem Array (alloc blocks) Maximale Anzahl von reservierten Blöcken: MAX ALLOCATIONS 1 void *monitoring alloc malloc(size t size): Speicher reservieren mittels Systemaufruf (malloc) Speichern von Informationen zu abgelegten Blöcken in alloc blocks

Aufgabe 1 a): Verwendung von malloc und free 5 2 void monitoring alloc free(void * block): Freigabe des übergebenen Speicherbereiches (free) Einträge im Array wieder freigeben

Aufgabe 1 a): Verwendung von malloc und free 5 2 void monitoring alloc free(void * block): Freigabe des übergebenen Speicherbereiches (free) Einträge im Array wieder freigeben 3 void init monitoring alloc(): Initialisierung der Datenstrukturen

Aufgabe 1 a): Verwendung von malloc und free 5 2 void monitoring alloc free(void * block): Freigabe des übergebenen Speicherbereiches (free) Einträge im Array wieder freigeben 3 void init monitoring alloc(): Initialisierung der Datenstrukturen 4 int shutdown monitoring alloc(): Überprüfen des Arrays auf nicht freigegebene Blöcke Rückgabe der Anzahl der nicht freigegebenen Blöcke 15 Punkte

init monitoring alloc 6 Globale Variablen: int allocations: Anzahl der Speicherallokationen init_monitoring_alloc: void init_monitoring_alloc() { allocations = 0; // no allocation done so far // iterate through the array... AllocatedMemoryBlock block; for (int i = 0; i < MAX_ALLOCATIONS; i++) { block = &allocated_blocks[i]; //... initializing all block block >frame block >size = 0; block >ordinal = 0; = NULL; // or use memset to set the whole memory to 0 at once / memset(allocated_blocks, 0, sizeof(allocatedmemoryblock) MAX_ALLOCATIONS); /

monitoring alloc malloc 7 monitoring_alloc_malloc: void monitoring_alloc_malloc(size_t size) { void allocated = NULL; if (allocations < MAX_ALLOCATIONS) { allocated = malloc(size); if(!allocated) { printf("error: Block of size %lu could not be allocated!\n", (unsigned long)size); else { // allocation was successful // number of allocations is used as index of the global array AllocatedMemoryBlock block = &allocated_blocks[allocations]; // store information about allocation in a block block >frame = allocated; block >size = size; block >ordinal = allocations; allocations++; // increment allocations done return allocated; Neuen Speicherblock anlegen und am Ende von alloc_blocks ablegen. allocations wird als Index des globalen Arrays verwendet

monitoring alloc free 8 monitoring_alloc_free: void monitoring_alloc_free(void ptr) { int found = 0; for( AllocatedMemoryBlock block = allocated_blocks; block!= &allocated_blocks[max_allocations 1]; block++ ) { if (block >frame == ptr && ptr!= NULL) { found = 1; // found block to be freed free(block >frame); // free allocated memory // clear information about the block block >frame = NULL; block >size = 0; block >ordinal = 0; if(!found) { printf("error: Block %p not allocated!\n", ptr); Durchsuche Array nach dem freizugebenden Block Das Array wird mit dem Zeiger block durchgegangen, bis die Speicheradresse des letzten Elements des Arrays erreicht wurde

shutdown monitoring alloc 9 shutdown_monitoring_alloc: int shutdown_monitoring_alloc() { int leakingbytes = 0; // iterate through the array to search for leaks for( AllocatedMemoryBlock block = allocated_blocks; block!= &allocated_blocks[max_allocations 1]; block++ ) { if (block >frame!= NULL) { // found leak printf("error: block with ordinal %lu was not freed!\n", (unsigned long)block >ordinal); leakingbytes += block >size; // count bytes leaked free(block >frame); // free allocated memory block >frame = NULL;block >size = 0; block >ordinal = 0; printf("error: Leaking %lu bytes in total!\n", (unsigned long)leakingbytes); return leakingbytes; Die Anzahl der nicht freigegebenen Bytes wird gezählt und ausgegeben

Aufgabenteil b): Fehlersuche 10 Finden Sie die Speicherlöcher im Beispielprogramm Textuelle Beschreibung ausreichend 3 Punkte

leaking function 11 char leaking_function(char first, char last) { char allocated = NULL; char ptr = first; if(ptr) { while(ptr!= last) { if( ptr) { allocated = (char ) monitoring_alloc_malloc( ( ptr) sizeof(char) ); ++ptr; return allocated; In leaking_function werden u. U. mehrere Speicherblöcke reserviert. Es wird aber nur ein Zeiger auf den zuletzt reservierten Block zurückgegeben. Die anderen Blöcke sind somit nicht mehr erreichbar und werden nicht freigegeben!

leaking program 12 foo = (char ) monitoring_alloc_malloc(23); bar = (char ) monitoring_alloc_malloc(5); bar[0] = 11; bar[1] = 22; bar[2] = 33; bar[3] = 44; bar[4] = 55; allocated = leaking_function(foo, foo+23); if(allocated) { monitoring_alloc_free(allocated); allocated = NULL; In main wird an verschiedenen Stellen Speicher reserviert explizit durch Aufruf von monitoring_alloc_malloc implizit im Aufruf von leaking_function Jeder dieser Speicherblöcke muss wieder freigegeben werden, sobald er nicht mehr verwendet werden wird. Jedoch wird der an foo zugewiesen Speicherblock nie freigeben.

Binärer Baum in C 13 Implementierung eines binären Suchbaums in C Beispiel eines binären Suchbaums: 8 3 10 1 6 14 4 7 13 Dazu sollten vier Funktionen implementiert werden: createtree Erzeugt einen neuen Baum insert Fügt dem Baum einen Knoten hinzu binarysearch Durchsucht den Baum cleanuptree Gibt den allozierten Speicher des Baums frei

node t Struktur 14 Eine Struktur node_t repräsentiert einen Knoten im Baum typedef struct _node_t { int value; struct _node_t parent; struct _node_t left; struct _node_t right; node_t; Jeder Knoten hält einen Wert (value), sowie Zeiger auf den Elternknoten und die beiden Kinderknoten Der Typ der Zeiger ist jedoch nicht node_t, sondern struct _node_t Dies ist nötig, da der Typname node_t erst nach der Definition eingeführt wird und in der Definition noch nicht zur Verfügung steht Daher wird der Struktur der Typname struct _node_t gegeben, bevor der Typ in node_t umbenannt wird Auf diesen temporären Typnamen kann in der Definition verwiesen werden

createtree 15 createtree: node_t createtree(int rootvalue) { // allocate memory for one node node_t root = (node_t )malloc(sizeof(node_t)); // initialize newly created node root >value = rootvalue; root >parent = NULL; root >left = NULL; root >right = NULL; return root; Der Wurzelknoten muss mit malloc angelegt werden, da auch noch nach Beenden der Funktion mit ihm gearbeitet werden soll

insert Teil 1 16 Es muss die richtige Position zum Einfügen gefunden werden Dazu wird der Baum traversiert und insert rekursiv aufgerufen insert: void insert(node_t tree, int value) { if (tree >value >= value) { // value to be inserted is smaller or equal if (tree >left) { // tree >left is not NULL => insert anywhere in left subtree insert(tree >left, value); else { // tree >left is NULL => insert new node node_t left = (node_t )malloc(sizeof(node_t)); left >value = value; left >parent = tree; left >left = NULL; left >right = NULL; tree >left else { = left;

insert Teil 2 17 Die Überprüfung ob in Zeiger NULL ist wir genutzt um zu entscheiden, ob der Baum weiter durchsucht werden muss, oder die Position zum Einfügen gefunden wurde insert: else { // value to be inserted is greater if (tree >right) { // tree >right is not NULL => insert anywhere in right subtree insert(tree >right, value); else { // tree >right is NULL => insert new node node_t right = (node_t )malloc(sizeof(node_t)); right >value = value; right >parent = tree; right >left = NULL; right >right = NULL; tree >right = right;

binarysearch 18 Der Baum wird per Rekursion traversiert Wird der Wert gefunden, wird 1 zurückgegeben Sind wir bei einem ungültigen Knoten (Zeiger ist NULL) kann der Wert nicht mehr gefunden werden und wir geben 0 zurück binarysearch: int binarysearch(node_t tree, int value) { // if tree is invalid return false if (tree == NULL) { return 0; // if value of current node is equal to value return true if (tree >value == value) { return 1; // value of current node is greater => go left if (tree >value > value) { return binarysearch(tree >left, value); // value of current node is smaller => go right if (tree >value < value) { return binarysearch(tree >right, value); return 0; // to prevent compiler warning; shouldn t go here

cleanuptree 19 Nachdem beide Teilbäume aufgeräumt wurden, wird der Knoten mit free freigegeben Es wird nur traversiert, wenn der Knoten nicht NULL ist cleanuptree: void cleanuptree(node_t tree) { if (tree) { // tree is not NULL => traverse tree if (tree >left) { // tree >left is not NULL => clean up left subtree cleanuptree(tree >left); if (tree >right) { // tree >right is not NULL => clean up right subtree cleanuptree(tree >right); // free current node itself free(tree); // free can be called with a NULL pointer

Schnittstellen: Übersicht 20 API ABI ISA Tools Libraries System aufrufe Betriebssystem System ISA Hardware Anwendungen User ISA Aus Sicht des Anwenders gibt es mehrere Ebenen von Schnittstellen: Tools, Systemprogramme: Schnittstelle für den Benutzer (z.b. dir, ls) API: Schnittstelle für Programmierer (Compilezeit, z.b. libc,win32,...) ABI: Schnittstelle für Programme (Laufzeit, z.b. ELF,PE32+,...) ISA (Instruction Set Architecture): Maschinenbefehlssatz (i386,sparc,...)

Wahl der Waffen: Individualität vs. Kompatibilität 21 Ausprägung der Schnittstelle auf allen Ebenen hängt ab von BS und Maschine D.h. Benutzer, Programmierer und Programme müssen sich auf ein bestimmtes System einstellen Es gibt eine enorme Vielzahl verschiedener Systeme Gut: Unterschiedliche Systeme bieten unterschiedliche Stärken (und natürlich auch Schwächen) Schlecht: Will man mehrere Systeme unterstützen muss man die Eigenheiten der Systeme beachten Standards grenzen das Chaos der Schnittstellen auf einzelnen Ebenen oder sogar ebenenübergreifend ein Leider gibt es auch wieder eine Vielzahl von Standards Heute: große Klassen von BS mit grundlegender Kompatibilität innerhalb der Klasse und kleineren individuellen Unterschieden

(Defacto)-Standards für System-Schnittstellen 22 Verschiedene Standards spezifizieren Tools, APIs und ABIs. Standard Tools API ABI Beispiele (konforme Systeme) POSIX Y Y Solaris, Mac OS X, AIX, Linux, Cygwin System V Y Y Y Solaris, AIX, Linux BSD Y Y (Y) FreeBSD, OpenBSD, NetBSD, Linux WIN32 Y Y Y Windows NT und folgende, Wine (teilw.) POSIX: Portable Operating System Interface (for UniX) Standard aus der Unix-Welt, aktuell in der Version POSIX:2008 Umfasst API sowie Standardtools Nicht nur auf Unix beschränkt, auch für Windows gibt es Adaptierungen (Cygwin, Interix,...)

(Defacto)-Standards für System-Schnittstellen 23 System V: BSD: Unix Betriebssystem von AT&T, seit 1992 in der Version 4.2 Bezeichnet aber auch Standard für Schnittstellen für eine ganze Klasse von Unix (ähnlichen) Systemen Umfasst API und Tools aber vor allem ABI System V ABI wird in nahezu allen Unix ähnlichen Systemen genutzt Von der Berkley Software Distribution (erstmals 1977) abgeleiteter Standard Umfasst API sowie Tools BSD und System V sind Unix Derivate die maßgeblichen Einfluss auf andere Unix-basierte und -ähnliche BS genommen haben Linux, Mac OS, Solaris, uvm.

APIs: Beispiele und weitere Informationen 24 Linux und Unix Die wichtigsten System APIs sind: POSIX, System V sowie BSD (in verschiedenen Versionen) Informationen findet man online sowie zum jeweiligen System mittels man 2 intro bzw. man syscalls Windows Die Win32 API ist seit Windows NT die gängige API für alle Windows Programme Die Erweiterung für 64-Bit wird meist ebenfalls mit Win32 (for 64-bit Windows) bezeichnet Eine Online-Dokumentation ist im MSDN (Microsoft Developer Network, msdn.microsoft.com) zu finden

Beispiel für eine API: Lesen aus einer Datei 25 Eine Anwendung möchte aus einer Datei lesen Dazu wird eine konkrete API benötigt Eine Mögliche Lösung: Die Funktion read der POSIX API Diese Funktion dient zum Lesen aus einer Datei und besitzt drei Parameter: Dateideskriptor, Datenpuffer, Zeichenanzahl Beispiel-Aufruf in C (u.a. POSIX-konform): count = read(fd, buffer, nbytes); Es wird durch count die Anzahl tatsächlich gelesener Zeichen zurückgeliefert, sie kann evtl. kleiner als nbytes sein Wurde der Systemaufruf nicht erfolgreich ausgeführt, dann wird count auf -1 gesetzt, die Fehlernummer wird hierbei in die globale Variable errno gelegt

Verwendung und Implementierung der API 26 Eine API muss von einer konkreten Bibliothek implementiert werden Die Implementierung ist System-spezifisch (also bezgl. ABI und ISA) Die durch die API beschrieben Funktionalität wird dabei auf konkrete Aufrufe des Systems abgebildet Die Funktion read ist z.b. unter Unix in der C Standard Library implementiert (z.b. glibc) Dabei gilt insbesondere: Ein Programmtext kann auf allen Systemen übersetzt werden, welche die verwendete API anbieten Ein Programm (binär) kann auf allen Systemen ausgeführt werden, welche die verwendete ABI und ISA anbieten

ABI vs. API 27 API Application Programming Interface: Syntaktische und Semantische Beschreibung von Funktionsaufrufen Für eine konkrete Programmiersprache ABI Application Binary Interface: Beschreibung der Konvention zur Ausführung und Interaktion von Programmen in einem BS Format von binären Programm-, Object- und Bibliotheksdateien: z.b. ELF (Unix), PE32+ (Windows) Repräsentation von Datentypen: Größe, byte-order, alignment Speicherverwaltung und -layout: Virtuelle Adressräume, Abbild des Programms und der Daten im Speicher Realisierung von Funktionsaufrufen (calling conventions): Umgang mit Stack und Registern, Übergabe von Parametern, Rückgabe von Werten Symbole der Systemaufrufe: Beschreibung der Systemaufrufe auf binärer Ebene (Umsetzung einer API in Programmadressen)

ABI Ausprägungen 28 ABIs existieren für verschiedene Plattformen: i386, AMD-64, SPARC, MIPS,... verschiedene Systeme: System V, Windows, Mac OS, OS/2,... Binärformate: ELF (System V), PE32+ (Windows), a.out,... Datenrepräsentation: z.b. 32 oder 64 Bit, Big- oder Little-Endian Calling Convention: cdecl (x86 standard), stdcall (Win 32 standard), fastcall (Win 32, gcc)

ABI: Beispiel Binärformat ELF 29 Eine ELF konforme Datei enthält: Program Header Table, Section Header Table, sowie Daten (Programmcode usw.) Header beschreibt Einstiegspunkte der Datei sowie genaues Datenformat und Plattform Kurzinformationen, für welche Plattform eine ELF-Datei bestimmt ist, können mittels file ausgelesen werden Beispiel: Binary (myapp) für x86 64 GNU/Linux myapp: ELF 64 bit LSB executable, x86 64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15,... Beispiel: Binary (myapp) für SPARC myapp: ELF 32 bit MSB executable, SPARC, version 1 (SYSV), dynamically linked (uses shared libs), not stripped Mittels readelf können alle ELF-Informationen ausgelesen werden

ABI: Beispiel Calling Conventions cdecl,fastcall 30 cdecl: Parameter werden von rechts nach links auf dem Stack abgelegt Rückgabe wird in Registern abgelegt, falls passend (int in eax, float in st0) Die Register eax,ecx,edx können von der Funktion frei verwendet werden fastcall: Nicht standardisiert, Microsoft und GCC arbeiten dabei wie folgt: Die ersten beiden Parameter (von links nach rechts) werden in Registern ( fast) abgelegt, falls passend Die restlichen Parameter werden von rechts nach links auf dem Stack abgelegt

Zusammenfassung ABI 31 Mit dem ABI Aspekt der Speicherverwaltung aus Sicht der Prozesse werden wir uns später noch ausführlich befassen! Kompatibilität: Programme können auf anderen Systemen ausgeführt werden, wenn diese die gleiche ABI (Version!) unterstützen (Calling Conventions, Systemaufrufe), und insbesondere den gleichen Maschinenbefehlssatz und die gleiche Datenrepräsentation verwenden. außerdem kompatible Versionen aller verwendeten Bibliotheken installiert sind.