41
A Adaptive C Communication E Environment Teil 1

Adaptive - Institut für Informatik | TU Bergakademie Freiberg · Echtzeit Betriebsysteme (VxWorks, ... 6} 7} Bsp. Singleton ... Huston, Johnson, Syyid: The ACE Programmers Guide

Embed Size (px)

Citation preview

AAdaptive CCommunication EEnvironment

Teil 1

Gliederung

Motivation Überblick ACE

Entwurfsmuster, Framework Wrapper Facade Architektur ACE Bsp. Interprozesskommunikation mit ACE

Motivation Gängige Anforderungen an Software

ErweiterbarFlexibelPortierbar

Schwer realisierbar, fallsKernkonzepte & Softwarekomponenten

ständig neu “erfunden”Monolithischer Softwareaufbau

ZuverlässigWiederverwendbarFinanzierbar

Motivation

Entwicklung von Multi Plattform-Anwendungen problematisch:Komponentenbibliotheken mit verschiedenen

API‘s und Semantik auf unterschiedlichen Plattformen

Verschiedene Standards: z.B. POSIX, UNIX98, Win32

Beispiel Sockets API

Fehleranfällig: Häufig Return-Werte ignoriert Netzwerk Byte-Ordering

vergessen Nicht portabel:

Headerfiles Unterschiedliche Standards

In C geschrieben

→ C++ Wrapper wünschenswert

#include <sys/types.h>#include <sys/socket.h>int echo_server () {…int n_handle;int s_handle = socket (PFJJNIX, SOCK_DGRAM, 0);…addr.sin_family = AF_INET;addr.sin_port = PORT_NUM;…if (bind (s_handle, (struct sockaddr *) &addr,

sizeof addr) == -1) return -1;if (n_handle = accept (s_handle, (struct sockaddr *) &addr,

&addr_len) != -1) { int n; while ((n = read (s_handle, buf, sizeof buf}) > 0) write (n_handle, buf, n);

close (n_handle); } return 0;}

Überblick ACE Open Source Software Toolkit OO-Framework zur Entwicklung von

Kommunikationssystemen auf verschiedenen Plattformen

Abgedeckte Aspekte:Verbindungsaufbau und DiensteinitialisierungEvent demultiplexing & Event handler dispatchingStatische und dynamische DienstekonfigurationNebenläufigkeit und SynchronisierungVerteilte Kommunikationsdienste (Namen, Zeit,

Loggen, ...)

Überblick ACE

Entwickelt u.a. von Douglas Schmidt 1992 als open source Projekt veröffentlicht Ab 1994 Einsatz in kommerziellen Produkten

Boeing Siemens Ericson Nokia http://www.cs.wustl.edu/~schmidt/ACE-users.html

Firma: Riverace (www.riverace.com)

Überblick ACE

Unterstützte PlattformenAlle Windows VersionenUnix, Linux (SunOS 4.x, HP UX, Linux Redhat,

Suse etc.)Echtzeit Betriebsysteme (VxWorks, Chorus ,...)Diverse Großrechner ArchitekturenAuf vielen c++ Compilern getestet

ACE - Musterübersicht

ACE implementiert komplexe Entwurfsmuster und Frameworks

Exemplarisch Double Checked

Pattern im Kontext “Singleton Pattern”

Bsp. Singleton Zweck

Existenz max. einer Instanz einer Klasse Globaler Zugriffspunkt auf Instanz

Struktur

Singleton

static instance() ○

static instance_

getData()

data_

return instance_

Bsp. Singleton Eigene Implementierung, Versuch 1

Probleme: impliziter Konstruktor, Instanz wird manchmal unnötig erzeugt

1 public class Singleton{2 private static instance_3 = new Singleton();

4 public static instance(){5 return instance_;6 }7 }

Bsp. Singleton Eigene Implementierung, Versuch 2

1 public class Singleton{2 private static instance_;

3 private Singleton(){};

4 public static instance(){5 if (instance_ == 0)6 instance_ = new Singleton();

7 return instance_;8 }9 }

Problem: fehlende Synchronisierung in Zeilen 5-6

Bsp. Singleton Eigene Implementierung, Versuch 3

Problem: falsche Synchronisierung

1 public class Singleton{... // Korrekt

2 public static instance(){3 if (instance_ == 0)4 synchronized {5 instance_ = new Singleton();6 }

7 return instance_;8 }9 }

Bsp. Singleton

Korrekte Lösung dokumentiert im “Double Check Pattern”

1 if (instance_ == 0){2 synchronized {3 if (instance_ == 0)4 instance_ = new Singleton();5 }6 }

Muster

Jedes Muster beschreibt ein in unserer Umwelt beständig wiederkehrendes Problem und erläutert den Kern der Lösung für dieses Problem, so dass Sie diese Lösung beliebig oft anwenden können, ohne sie jemals ein zweites Mal gleich auszuführen(Christopher Alexander)

Formuliert für architektonische Probleme Idee übertragbar auf Entwurf von Software-

systemen

Muster

Unterschiedliche Ebenen von Mustern:Architekturmuster beschreibt Organisationsstruktur

(Subsysteme, Komponenten)

Entwurfsmuster beschreibt Struktur und Beziehungen innerhalb eines Subsystems

Idiom beschreibt Lösung eines Implementierungsproblems in einer bestimmten Programmiersprache

Entwurfsmuster

Beschreiben abstrakt & strukturiert oft vorkommende Probleme & ihre Lösungen

Erfassen Entwurfsentscheidungen, die erfahrungsgemäß gut funktionieren

Müssen an konkrete Probleme angepasst werden

Weitgehend unabhängig von spezifischen Programmiersprachen

Formen Sprache, um Entwürfe zu diskutieren

Entwurfsmuster - Bestandteile

Name und Klassifikation Zweck Auch bekannt als Motivation Anwendbarkeit Struktur Teilnehmer

Entwurfsmuster - Bestandteile

Zusammenarbeit Konsequenzen Implementierung Beispielcode Bekannte Anwendungen Verwandte Muster

Entwurfsmuster - Vorteile

Zuverlässig Wiederverwendbar Erweiterbar Vereinfachen Kommunikation

(Standardisierung von Namen…)

Framework Implementation von Entwurfsmustern Repräsentiert durch Menge von abstrakten Klassen und

Art und Weise wie Instanzen zusammenarbeiten Wiederverwendbares Design für Anwendung Definiert grundlegende Struktur und Architektur der

Anwendung

Unterschied zu Klassenbibliothek: Hauptprogramm für globale Steuerung Inversion of Control

Portabler Code Möglichkeiten:

#ifdefs

→komplex, schwer wartbar/erweiterbar

Musterbasiert: Wrapper Facade → Verschleiern von plattformspezifischem Code

#if defined (_WIN32) SOCKET h;#else int h;#endif

Wrapper Facade Besteht aus einer oder mehreren Klassen, die Funktionen und

Datenstrukturen (die z.B. von nichtobjektorientierten API‘s bereitgestellt werden) innerhalb portabler, objektorientierter Interfaces kapseln

Wrapper Facade – Implementation

Semantisch zusammengehörende Funktionen identifizieren und in Wrapper Facade Klassen gruppieren

Mehrere Funktionen in einer Methode vereinigen

Socket API:…int n_handle;s_handle=socket(…);…bind(…);listen(…);n_handle=accept(s_handle,…);

ACE_SOCK_Acceptor:

ACE_SOCK_Acceptor acceptor;…acceptor.open (…);acceptor.accept(…);

Wrapper Facade – Implementation

Funktionen unter Wrapper Facade vereinigen um damit Portabilität zu gewährleisten Bsp. Thread Management

Win32: CreateThread()POSIX: pthread_create()UI: thr_create()

Unterschiedliche Rückgabewerte

ACE_Thread_Manager::spawn()

Benötigte Informationen über Argumente übergeben1 Rückgabekonvention: 0 erfolgreich, -1 Fehler (Fehlergrund in errno gespeichert)

Wrapper Facade - ACE_Thread_Manager::spawn()1. ACE_Thread_Manager::spawn (run_svc, thread_args, THR DETACHED 1 THR

SCOPE SYSTEM);

3. //zugrundeliegende Plattform, hier: UI Threads thr_create (0, 0, run_svc, thread_args, THRJ3ETACHED | THR_SCOPE_SYSTBM, &thread_id);

5. run_svc (thread_args) {/*...*/}

1. Betriebssystem erzeugt Thread Ausführungskontext2. Betriebssystem allokiert Speicher für Thread Stack3. Register Set des neuen Thread wird vorbereitet, ruft bei

Ausführung run_svc() auf4. Thread als ausführbar markiert, Betriebssystem kann ihn

ausführen

ACE Architektur

ACE Architektur

Adaption Layer: Ca. 10 % von ACE Zwischen eigentlichen Betriebssystem API‘s und Rest

von ACE Kapselt grundlegende OS Mechanismen mittels

Wrapper Facade → einheitliches Interface für betriebsystemnahe Aufrufe

Implementiert in ACE_OS Klasse (ca. 500 statische C Methoden)

ACE Architektur - Adaption Layer

Kapselt u.a. folgende OS Mechanismen:

Multi-threading und Synchronization InterprozesskommunikationEvent demultiplexingDynamisches LinkingMemory Mapping und shared memory

ACE Architektur

OO-Wrapper Layer Ca. 50 % Verwendet Wrapper Facade Pattern Bietet praktisch selbe Funktionalität wie Adaption

Layer, verwendet allerdings objektorientierte, typsichere C++ Klassen, die ACE_OS Methoden aufrufen

Applikationen verwenden Wrapper Klassen durch Vererbung oder Instantiierung

ACE Architektur - OO-Wrapper Layer

Nebenläufigkeit und Synchronisation ACE_Mutex, ACE_Token, …

Prozess-/Threadmanagement ACE_Process, ACE_Thread_Manager, …

Interprozesskommunikation IPC SAP

Memory Management ACE_Allocator, ACE_Malloc, …

Timer Klassen ACE_Timer_Queue, …

Signal Handling ACE_Sig_Handler, …

ACE Architektur Framework Layer

Highest level Building Blocks in ACE Integriert und vergrößert Wrapper KlassenFramework Komponenten basieren auf

Entwurfsmustern spezifisch für Kommunikationssoftware

ACE Architektur – Framework Layer Event handling framework

Reactor/Proactor überwachen mehrere Event-Quellen

Verbindungs- und Serviceinitialisierung Acceptor/Connector

passiver/aktiver Verbindungsaufbau, Svc_Handler verarbeitet eigentliche Ereignisse

Stream Framework Service Configuration Framework

Service Configurator unterstützt dynamische Initialisierung, Unterbrechung, Wiederaufnahme, Rekonfiguration und Beendigung von Diensten

ACE Architektur

Service and Components LayerFertige Anwendungen, die auf ACE basieren,

u.a.: Distributed logging service Webserver JAWS Corba-Implementierung TAO

Beispiel: IPC_SAP

ACE_IPC_SAP

ACE_SOCK ACE_TLI ACE_SPIPE ACE_FIFO

… … … …

ACE_SOCK - Wrapper für BSD Sockets

ACE_SOCK_Acceptor passiver Verbindungsaufbau, basierend auf accept() und listen()

ACE_SOCK_Connector aktiver Verbindungsaufbau, basierend auf connect()

ACE_SOCK_Dgram kapselt UDP Protokoll-Funktionalität

ACE_SOCK_IO kapselt u.a. send(), receive(), write()

ACE_SOCK_Stream kapselt TCP Protokoll-Funktionalität, nach Verbindungsaufbau verwendet

#include "ace/SOCK_Acceptor.h"#include "ace/SOCK_Stream.h"…class Server{public:Server (int port):server_addr_(port),peer_acceptor_(server_addr_) { data_buf_= new char[SIZE_BUF]; }

int accept_connections (){ if (peer_acceptor_.get_local_addr (server_addr_) == -1)

ACE_ERROR_RETURN ((LM_ERROR,"%p\n","Error in get_local_addr"),1); ACE_DEBUG ((LM_DEBUG,"Starting server at port %d\n",

server_addr_.get_port_number ())); while(1){ ACE_Time_Value timeout (ACE_DEFAULT_TIMEOUT); if (peer_acceptor_.accept (new_stream_, &client_addr_, &timeout)== -1)

{ ACE_ERROR ((LM_ERROR, "%p\n", "accept"));continue; }

else {ACE_DEBUG((LM_DEBUG,"Connection established with remote %s:%d\n",client_addr_.get_host_name(),client_addr_.get_port_number()))

handle_connection(); }}}

Beispiel: passiver Server

int handle_connection(){ for(int i=0;i<NO_ITERATIONS;i++) { int byte_count=0; if( (byte_count=new_stream_.recv_n (data_buf_, SIZE_DATA, 0))==-1)

ACE_ERROR ((LM_ERROR, "%p\n", "Error in recv")); else{

data_buf_[byte_count]=0;ACE_DEBUG((LM_DEBUG,"Server received %s \n",data_buf_));

} }if (new_stream_.close () == -1)

ACE_ERROR ((LM_ERROR, "%p\n", "close"));return 0; }

private: char *data_buf_; ACE_INET_Addr server_addr_; ACE_INET_Addr client_addr_; ACE_SOCK_Acceptor peer_acceptor_; ACE_SOCK_Stream new_stream_; };

int main (int argc, char *argv[]){ if(argc<2){

ACE_ERROR((LM_ERROR,"Usage %s <port_num>", argv[0]));ACE_OS::exit(1); }

Server server(ACE_OS::atoi(argv[1])); server.accept_connections(); }

Beispiel: Connector in Verbindung mit Acceptor

#include "ace/SOCK_Connector.h"#include "ace/INET_Addr.h"…

class Client{public: Client(char *hostname, int port):remote_addr_(port,hostname){

data_buf_="Hello from Client";}int connect_to_server(){ ACE_DEBUG ((LM_DEBUG, "(%P|%t) Starting connect to %s:%d\n", remote_addr_.get_host_name(),remote_addr_.get_port_number())); if (connector_.connect (client_stream_, remote_addr_) == -1)

ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","connection failed"),-1); else

ACE_DEBUG ((LM_DEBUG,"(%P|%t) connected to %s\n", remote_addr_.get_host_name ())); return 0;}

int send_to_server(){ for(int i=0;i<NO_ITERATIONS; i++){ if (client_stream_.send_n (data_buf_, ACE_OS::strlen(data_buf_)+1, 0) == -1){

ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","send_n"),0);break;

}}close();}int close(){ if (client_stream_.close () == -1)

ACE_ERROR_RETURN ((LM_ERROR,"(%P|%t) %p\n","close"),-1); else

return 0;}private: ACE_SOCK_Stream client_stream_; ACE_INET_Addr remote_addr_; ACE_SOCK_Connector connector_; char *data_buf_;};int main (int argc, char *argv[]){ ... Client client(argv[1],ACE_OS::atoi(argv[2])); client.connect_to_server(); client.send_to_server(); }

Fazit+ plattformunabhängig+ vielseitig anwendbar+ gut dokumentiert

Huston, Johnson, Syyid: The ACE Programmers Guide Schmidt, Huston: C++ Network Programming. Volume 1+2 http://www.cs.wustl.edu/adaptive.html

- Keine Exceptions, nur Fehlercodes 1992 beinhaltete C++ Standard Exceptions noch nicht hinreichend Exceptions unter Performance Gesichtspunkten eher nachteilig