Sammlung von möglichen Klausuraufgaben. --> Musterklausur WS2012/2013 Flashcards

1
Q

1) Abstraktion / Hierarchie

Was ist unter Abstraktion sowie unter Hierarchie zu verstehen?

Bitte erläutern Sie die Begriffe im Allgemeinen und im Speziellen (auf den Entwurf von Software bezogen)!

Stellen Sie die Vorteile, bzw. die Nachteile der beiden Ansätze gegenüber!

A

Abstraktion: Die Trennung des Wesentlichen vom Unwesentlichen und der anschließenden Beschränkung auf das Wesentliche.

Hierarchie: Modulbildung, Bildung von verschiedenen Schichten, wobei Module mehrfach verwendet werden (können)

**Abstraktion **+ **i.Allgemeine schnellere Lösung, automatisierte Implementierung möglich (Hochsprachen C++, Java, Matlab) ** **

- Geringere Performance

Hierarchie + Universell einsetzbar, effiziente Teilimplementierungen können unverändert übernommen werden.** **

**- **Größerer Aufwand bei der Erstellung wieder verwendbarer Module

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Welche Methoden, bzw. Ansätze werden verfolgt, um Abstraktion im Softwareentwurf zu erreichen? Nennen und erläutern Sie zwei Beispiele!

A

Höhere Programmiersprachen:

Die Nutzung der Basisbefehle einer Hardware wird abstrahiert, indem umfangreichere Befehle und Konzepte dem Nutzer zur Verfügung gestellt werden, welche anschließend von einem Compiler in einen Äquivalent, aber aus den Basisbefehlen bestehenden, Ablauf übersetzt wird. Hierbei werden die Befehle der Hochsprache nicht durch eine feste Kombination von Basisbefehlen ersetzt, sondern komplexer (quasi intelligent) ersetzt. So übernimmt der Compiler beispielsweise die Verwaltung der Speicheradressen oder optimiert den Code.

Verwendung von Modulen, z.B. HAL:

Der Zugriff auf die Hardware wird durch die HAL abstrahiert. Dem Anwender/ Entwickler werden Befehle zur Verfügung gestellt, welche unabhängig von der eingesetzten Hardware ist. Die eigentliche Umsetzung dieser Funktionen bei der Hardware wird durch die HAL realisiert. So werden beispielsweise entsprechend der eingesetzten Hardware unterschiedliche Adressbereiche bei einem und demselbem Befehl genutzt.

Verwendung von Modulen, z.B. Implementierung von Kommunikationsprotokollen gemäß hierarchischen ISO-OSI-Referenzmodell:

Trennung von Anwendungs und Transportschicht

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Erläutern Sie die Bedeutung von Header-Files bei der Programmierung in C!

Welche Vorteile können hierdurch erreicht werden?

A

Die wichtigste Aufgabe der Nutzung von Header-Files bei der Programmierung in C ist die Umsetzung des Geheimhaltungsprinzips. Dabei findet die Implementierung von Funktionen innerhalb der c-Datei statt und die Deklaration im Header-File. Einem Kunden kann später die C-Datei im kompilierten Zustand übergeben werden, um so die Implementierung der Funktionalität geheim zu halten. Die Funktionsweise und die benötigten Übergabeparameter werden dem Kunden dann im h-File bekannt gegeben.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Was ist unter einem Hardware Abstraction Layer (HAL) zu verstehen?

Welche Bestandteile kann eine HAL enthalten?

Folgt eine HAL dem Abstraktions- oder dem Hierarchie-Paradigma des Software Engineering?

A

Die HAL isoliert die Hardware von den Anwendungsprogrammen. Jeder Zugriff auf die Hardware muss über die Vermittlung der HAL geschehen. Bei der Verwendung eines Betriebssystems ist sie die unterste Schicht des Betriebssystems.

Der Zugriff auf die Hardware wird durch die HAL abstrahiert. Dem Anwender/ Entwickler werden Befehle zur Verfügung gestellt, welche unabhängig von der eingesetzten Hardware ist. Die eigentliche Umsetzung dieser Funktionen bei der Hardware wird durch die HAL realisiert.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Welche Funktionen sollten Sie in den Treibern für eine CAN-Schnittstelle zur Verfügung stellen?

A

Grundlegende Funktionen eines Interfaces:

init(), exit(), read(),write()

Erweiterte Funktionen insbesondere bei verbindungsorientierter Kommunikation:

wait(), close(), open(),

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Es gibt in C die beiden folgenden Möglichkeiten, Konstanten zu definieren.

                   #define MWSTFAKTOR 0.19 

bzw. const float MwStFaktor = 0.19;

Worin besteht der Unterschied bei diesen beiden Möglichkeiten?

Wodurch unterscheidet sich insbesondere der kompilierte Code?

Stellen Sie die Vorteile, bzw. die Nachteile der beiden Ansätze gegenüber!

A

_Definition/Unterschied: _

#define: im Code wird bei jeder Verwendung der Konstanten diese durch den Präprozessor mit dem Wert, der bei der Definition hinter dem Namen steht, ersetzt. Das heißt, es wird innerhalb des Datensegments bei jedem Aufruf der Wert fest hinterlegt.

const: Es wird eine Variable erzeugt, welche beim Aufruf wie eine normale Variable genutzt wird. Das heißt bei jeder Verwendung der Konstanten wird im Code die Adresse der Variablen hinterlegt. Einziger Unterschied zu einer normalen Variablen ist, dass eine direkte Zuweisung eines neuen Wertes zu einer Fehlermeldung des Compilers führt.

Vor- und Nachteile:

#define-Methode:

verbraucht weniger Speicher, erlaubt aber schnelleren Zugriff, da direkt aus dem Programmspeicher gelesen wird.

const-Variante:

wird meist so umgesetzt, dass noch einmal auf eine andere Speicherstelle im Flash referenziert wird. Compileranweisungen sind typsicher. Präprozessoranweisungen sind dies nicht (Verantwortung des Programmierers)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Beschreiben Sie die Typendefinitionen unter Verwendung von einem Include-Guard für eine 32 Bit lange Gleitkommazahl FLOAT32!

Im Handbuch des Compilers ist für den gewählten Mikrocontroller folgende Tabelle angegeben:

double 64 Bit

float 32 Bit

unsigned int 16 Bit, big endian

unsigned long int 32 Bit, big endian

char 8 Bit unsigned

char 8 Bit

A

ifndef FLOAT32

typedef float FLOAT32

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Erläutern Sie die Funktionsweise eines Include-Guards!

A

Der Include-Guard schützt vor Mehrfachdefinitionen. Dabei wird immer die erste Definition verwendet, alle nachfolgenden werden übersprungen

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Gegeben sei der folgende Codeausschnitt

char variable;

char* pointer;

pointer = &variable;

variable = 5;

*pointer = 6;

Beschreiben Sie Vorgehensweise beim Kompilieren des Programms!

Wie sieht die Aufteilung des Speichers aus?

Gehen Sie davon aus, dass char 1 Byte lang ist. Der Datenspeicher hat eine Größe von 64 kByte.

A

Mit der Zeile char variable; wird eine 1 Byte lange Variable im Speicher reserviert.

Mit der Zeile char* pointer; wird ein Pointer im Speicher reserviert. Die Information, dass der Speicher eine Größe von 64 kByte hat, soll auf einen 16 Bit / 2 Byte langen Pointer hinweisen.

Also sieht die Speichermap anschließend folgendermaßen aus (Adressen beispielhaft)

0x0000 variable

0x0001 pointer (1 Byte)

0x0002 pointer (2. Byte) (Reihenfolge egal, da keine Informationen über big oder little endian vorliegen.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Beschreiben Sie Vorgehensweise bei der Ausführung des Programms!

Geben Sie die einzelnen Arbeitsschritte in „Pseudo-Assembler-Code“ an! Oder beschreiben Sie möglichst eindeutig mit Worten!

A

Schreibe Adresse von variable an die Adresse von pointer (0x0001-0x0002)

Schreibe 5 an die Adresse von variable (0x0000)

Schreibe 6 an die von pointer angegebene Speicheradresse (0x0000)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Wieso sind in C auch die Datenpointer typengebunden?

Geben Sie ein Beispiel, wo diese Typenbindung benötigt wird!

A

Die Pointer sind typengebunden,weil beim Dereferenzieren bekannt sein muss, wie der Inhalt zu interpretieren ist. Zum Beispiel sind float und int bei algebraischen Befehlen unterschiedlich zu behandeln.

Ebenso ist beim De- und Inkrementieren des Pointers die Größe des Datentyps entscheidend (Pointerarithmetik).

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Was ist unter einem void-Pointer zu verstehen?

A

Ein void-Pointer ist ein Pointer ohne Datentyp-Bindung. Er verweist auf eine Speicheradresse, aber die Größe und der Typ der Daten sind unbekannt. Vor der Verwendung des Inhalts der Adresse sollte der void-Pointer zu dem passenden Typ gecastet werden. Anwendung findet der void-Pointer bei der Verwendung von Callback-Funktionen, wenn die Anzahl und Art der übergebenen Parameter zur Kompilationszeit unbekannt sind.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Was ist unter einem Funktionspointer zu verstehen? Wodurch unterscheidet er sich von einem Datenpointer?

A

Ein Funktionspointer verweist nicht auf eine Variable oder Struktur im Datenspeicher, sondern auf die erste Adresse einer Funktion. Ein Funktionspointer lässt sich wie ein normaler Funktionsaufruf nutzen. Verwendung findet ein Funktionspointer immer dann, wenn vor der Kompilierung nicht bekannt ist, welche Funktionen existieren. Besonders relevant ist dies bei den so genannten Callback-Funktionen. Ebenso finden Funktionspointer Anwendung, wenn die Auswahl einer Funktion mittels einer if- oder switch-Abfrage in Bezug auf die benötigte Rechenzeit optimiert werden soll.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Was ist unter einem Betriebssystem zu verstehen?

Welche Aufgaben erfüllt ein Embedded Betriebssystem mindestens?

A

Ein Betriebssystem verwaltet die Ressourcen des Systems. Hierzu gehört die Verwaltung des Speichers aber auch der CPU. Ebenso kann es Sicherheitsfunktionen beinhalten.

Ein Embedded Betriebssystem beinhaltet mindestens die HAL und einen Scheduler.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Diskutieren Sie die Vor- und die Nachteile des Einsatzes eines Betriebssystems auf einem Embedded System!

Wann erscheint ein Einsatz sinnvoll? Wann nicht?

A

Vorteile:

flexibler im Zusammenhang mit zusätzlichen Prozessen und Hardwarekomponenten

Übernahme der Prozess- und Speicherverwaltung

sicherer Funktionalität (besseres Safety)

**Nachteile: **

benötigt Ressourcen

anfälliger für Angriffe(geringere Security)

**Einsatz sinnvoll wenn: **

mehrere Prozesse (Art und Anzahl unbekannt) sind.

Bauteile und Schnittstellen flexibel sein sollen

Prozesse nicht kooperativ sein sollen

**Einsatz nicht sinnvoll wenn: **nur ein Prozess

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Was ist unter einem Scheduler zu verstehen?

A

Task mit hoher Priorität der CPU-Zeiten an niederpriore Tasks vergibt.

17
Q

Erläutern Sie die vier Zustände im nachfolgend gezeigten Zustandsdiagramm!

Erläutern Sie auch einige wichtige Zustandsübergänge!

A

Vier dargestellte Zustände, welcher ein Prozess bei der Verwendung eines Schedulers annehmen kann:

Dead: Prozess existiert nicht für den Scheduler. Die ihm zugrunde liegende Funktion existiert lediglich im Daten- Segment.

Ready: Prozess ist bereit, durch die CPU bearbeitet zu werden.

Running: Prozess wird durch die CPU bearbeitet.

Waiting: Prozess existiert, kann aber nicht weiter verarbeitet werden, beispielsweise fehlt ihm eine Information wie eine Benutzereingabe.

Wichtige Übergänge:

Create: Sobald die Funktion aufgerufen wird, werden die Variablen der Funktion angelegt und dem Scheduler als existenten Prozess bekannt gegeben.

Kill: Prozess wird beendet, indem dessen Variablen gelöscht werden.

Assign: Prozess, welcher bereit ist, wird nun bearbeitet.

Relinquish: Prozess soll später weiter verarbeitet werden.

Block: Prozess kann nicht weiter verarbeitet werden, weil ihm etwas fehlt.

Freigeben: Prozess kann wieder bearbeitet werden, weil nun die fehlenden Informationen bekannt sind.

18
Q

Beschreiben Sie die Ereignisse bei einem Round-Robin-Scheduling-Verfahren unter Verwendung von drei Tasks gleicher Priorität! Verwenden Sie die Darstellung aus Teilaufgabe (17)!

Welche Rolle spielt hier der Scheduler?

A

Das Round Robin Scheduling arbeitet nach dem „first come first serve“ Verfahren. Jeder Prozess, welcher sich im „ready“ Zustand befindet, wird einer Warteschlange hinzugefügt und es wird immer der Prozess dem „running“ Zustand zugeordnet, welcher am längsten „ready“ ist. Sollte der aktive Prozess länger als eine festgelegte Zeit zur Abarbeitung benötigen, wird er „aufgegeben“ und wieder an das Ende der Warteschlange der Prozesse gesetzt, welche „ready“ sind.

Die Priorität der Prozesse spielt bei diesem Verfahren keine Rolle.

Der Scheduler übernimmt die Rolle, den am längsten wartenden Prozess dem aktiven Zustand zuzuordnen und – falls dieser zu lange dauert – auch wieder wegzunehmen.

Der Scheduler wird periodisch aufgerufen und führt diese Zustandsänderungen durch. Er gibt dann (kooperativ !) die CPU an den nächsten Task in der Reihe ab.

19
Q

Beschreiben Sie die Abläufe bei einem Shortest Job First Scheduling!

A

Bei dieser Ablaufplanung wird als nächstes immer der Prozess bearbeitet, welcher die kürzeste angegebene Bearbeitungszeit benötigt.

20
Q

Gegeben sei der folgende Code für einen Task :

static void task1(void *pvParameters)

{

while(1)

{ // Aufgabe der Dauer von 100 Ticks ausführen (diese ist nicht

// Bestandteil der Aufgabe

// hier müssen Sie noch Code einfügen. }

}

task2 und task3 sind ähnlich aufgebaut, führen aber andere Aufgaben aus, die jeweils 150 und 100 Ticks benötigen.

Es soll nun die nachstehend beschriebene Zeitcharakteristik erreicht werden!

Welche Möglichkeiten der Umsetzung gibt es? Nennen Sie mindestens zwei Möglichkeiten!

Schreiben Sie für eine der Möglichkeiten die hierzu benötigte main()-Funktion!

A

1. Möglichkeit (statische Taskplanung ohne Betriebssystem):

int main(void)

{

while(1)

{ Task1(); Task2(); Task3(); Idle(); }

}

2. Möglichkeit (Betriebssystem mit Prioritäten und Schlafzyklen mit vTaskDelay):

static void task1(void *pvParameters)

{

while(1)

{ // Aufgabe der Dauer von 100 Ticks ausführen (diese ist nicht

// Bestandteil der Aufgabe

// hier müssen Sie noch Code einfügen.

// hinzugefügter Code

// entsprechend für task2 und task3

vTaskDelay( 400 / portTICK_RATE_MS ); }

}

int main( void ) {

xTaskCreate( task1, “Task 1”, 1000, NULL, 1, NULL );

xTaskCreate( task2, “Task 2”, 1000, NULL, 2, NULL );

xTaskCreate( task2, “Task 2”, 1000, NULL, 2, NULL

vTaskStartScheduler();

for( ;; ); }

3. Möglichkeit (Betriebssystem mit Prioritäten und Schlafzyklen mit vTaskDelayUntil):

static void task1(void *pvParameters)

{

while(1)

{ // nun wird der Code hier eingefügt

portTickType xLastWakeTime;

// Initialise the xLastWakeTime variable with the current time.

xLastWakeTime = xTaskGetTickCount();

const portTickType xFrequency = 500;

while(1)

{ // Aufgabe der Dauer von 100 Ticks ausführen (diese ist nicht

// Bestandteil der Aufgabe

// hier müssen Sie noch Code einfügen.

// hinzugefügter Code

// entsprechend für task2 und task3

vTaskDelayUntil( &xLastWakeTime, xFrequency); }

}

int main( void ) {

xTaskCreate( task1, “Task 1”, 1000, NULL, 1, NULL );

xTaskCreate( task2, “Task 2”, 1000, NULL, 2, NULL );

xTaskCreate( task3, “Task 3”, 1000, NULL, 3, NULL );

vTaskStartScheduler();

for( ;; ); }

21
Q

Beschreiben Sie die Funktionsweise einer Queue zur Kommunikation zwischen zwei Tasks!

Welchen Vorteil hat die Verwendung einer solchen Queue gegenüber dem Datenaustausch über einen gemeinsamen Bereich im Datenspeicher?

A

Bei einer Queue handelt es sich generell um einen „first in first out“ Stapel fester Größe, wobei ggfs. ein Element auch an den Anfang des Stapels hinzugefügt werden kann. Die Elemente werden als Kopie des Originals hinzugefügt.

Vorteile:

Hinzufügen auf beiden Seiten des Stapels möglich

Anwender muss sich nicht darum kümmern, wie auf den nächsten Wert zugegriffen wird und ob die Queue voll ist

22
Q

Beschreiben Sie die Funktionsweise des Befehls

**xStatus = xQueueSendToBack( xQueue, &lValueToSend, 0 ); **

A

Diese Funktion schreibt den letzten Parameter am Ende des Stapels, bzw. unter den Stapel, sofern der Stapel noch nicht voll ist,

**1.Parameter: **welcher Stapel soll genutzt werden.

2.Parameter: von welcher Variablen soll der Inhalt kopiert werden.

**3.Parameter: **wie lange soll versucht werden, Daten zu kopieren, falls der Stapel aktuell voll ist.

Die Funktion gibt einen Fehlercode zurück, falls der Wert wegen eines vollen Stapels nicht kopiert werden konnte.

23
Q

Prozessmodelle (8 Punkte)

Nennen Sie einige Vor- und Nachteile des Wasserfallmodells!

A

**Vorteile: **

für kleinere Projekte sinnvoll

Phasen sind klar abgegrenzt

einfach zu planen und zu kontrollieren

**Nachteile: **

dauert lange, bis erster, lauffähiger Prototyp erstellt ist

Fehler werden erst spät entdeckt

unflexibel gegenüber Änderungen

zu viel Wert auf der Dokumentation

24
Q

Welche Vorteile sind mit den agilen Prozessmodellen verbunden?

A

**Vorteile: **

hohe Flexibilität

für kleinere Projekte sinnvoll

frühzeitige Erkennung von Fehlern/Risiken

kürzere Entwicklungszyklen

25
Q

Beschreiben Sie die hauptsächlichen Charakteristika von iterativ-inkrementellen Prozessmodellen!

A

Bei iterativ inkrementellen Prozessmodellen werden dieselben Kombinationen von aufeinander folgenden Teilschritten mehrfach durchlaufen, um sich inkrementell der finale Lösung zu nähern.

Ein Beispiel ist das Spiralmodell.

Dabei finden mehrfach die vier Schritte statt:

  1. Planung des nächsten Zyklus.
  2. Ermittlung der Anforderungen.
  3. Beurteilung der Lösungsansätze.
  4. Umsetzung.
26
Q

Werkzeuge (13 Punkte)

Was ist unter Semantic Versioning zu verstehen?

Beschreiben Sie die wichtigsten Regeln!

A

Semantic Versioning ist eine Vorgabe, wie die Versionsnummer eines Programms anzugeben ist. Es handelt sich um eine Kombination von 3 Zahlen, welche jeweils mit einem Punkt getrennt sind. erste 1.Zahl: Hauptversion, 2.:Unterversion, 3.Patchversion.

Regeln:

  • Wenn eine höhere Versionsart inkrementiert wird, dann alle niederen Versionsarten auf 0 zurücksetzen.
  • Patchversion wird erhöht, wenn ausschließlich bestehende Funktionen verändert wurden. Programm in diesem Fall rückwärts kompatibel.
  • Unterversion wird erhöht, wenn zusätzlich neue Funktionen hinzugefügt wurden.Programm immer noch rückwärts kompatibel
  • Hauptversion wird erhöht, wenn Programm nicht mehr rückwärts kompatibel ist, wenn zum Beispiel Funktionen entfernt wurden.
27
Q

Sie verwalten eine Datei test1.txt mit einem Source Code Management (SCM) System wie GIT. Im Ausgangszustand lautet der Inhalt der Datei:

abc

def

Eine zweite Datei test2.txt enthält die Zeilen:

abc

def

ghi

Welche Ausgabe erhalten Sie beim Aufruf des Befehls **diff test1.txt test2.txt **?

28
Q

Sie committen nun die Datei test1.txt. Sie fügen nun eine weitere Zeile mit dem Inhalt xyz ans Ende der Datei an und committen diese ebenfalls. Wie sieht dann der Versionsbaum aus?

A

abc

def

|

abc

def

xyz

29
Q

Welche Befehle / Operationen müssen Sie vornehmen, dass Ihr GIT-Baum wie folgt aussieht?

Siehe Bild(10)

A

Initalversion einpflegen, Datei erweitern und committen,

Initalversion nochmals aufrufen und anderweitig ergänzen und committen

die beiden weiterentwickelten Dateien der Initalversion zu einer neuen Masterdatei mergen

30
Q

Wie lautet der Inhalt der Datei test1.txt diesen Schritten?

A

000

abc

def

xyz