Upload
phamkiet
View
226
Download
0
Embed Size (px)
Citation preview
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
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
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