Hallo zusammen,
ich brauche ein kleinbisschen Starthilfe.
Bei Linux habe ich mich schon etwas mit dem Thema
Interprozesskommunikation beschäftigt, also mit Sockets, MessageQueues,
Semaphoren etc.
Nun möchte ich aber unter Windows CE 2 Programme miteinander
Kommunizieren lassen. Das eine Programm arbeitet mit der Seriellen
Schnittstelle und das andere verarbeitet diese Daten.
Kann mir jemand ein klein bisschen Starthilfe geben wie ich das am
besten angehe?
Ich hatte erst an Messagequeues gedacht. Dabei habe ich aber gesehen,
dass OpenMsgQueue den Prozesshandle und den Handle der erstellten
MsgQueue haben möchte. Diese kann ich doch garnicht liefern, oder etwar
doch? Meine Kenntnisse von Windows CE sind noch sehr beschränkt,
deswegen fehlt mir ein bisschen der Überblick.
Ich hoffe ihr könnt mir ein bisschen bei den Startschwierigkeiten helfen
und mir eine Kommunikationsart Empfehlen.
Gruß
Josef
P.S.: Bei der Geschichte mit Sockets über den Localhost, gibt das
Probleme mit Firewalls?
ich hab das Windows CE Gerät momentan nicht da aber du hast recht, die
Firewall geschichte könnte ich auch in der Debug Simulation starten.
Habe ich denn recht das es mit Messagequeues nicht geht sondern bei so
einer Prozesskommunikation nur noch die Sockets bleiben? Oder gibt es
eine alternative und welche Vor-/Nachteile hat dies?
Bei der Überlegung des Problems kamen mir auch noch ein paar Fragen.
Wo werden Globale Variablen gespeichert? Auch wenn sie Global heißen
sind sie doch nur für die Prozesse verfügbar und ein anderes .exe
Programm kann nicht auf die Globalenvariablen eines anderen Zugreifen,
oder?
warum müssen es denn 2 Prozesse sein? Durch das IPC ist das ganze doch
viel komplexer.
Unter windows könnte man das ganze aber über die normale Messageque
machen. Sonst gibt es auch noch Shared Memory und eventuell kommt auch
eine Pipe in frage.
Die Pipe würde sich vermutlich am einfachsten machen, weiss aber nicht
ob sie in WindowsCE vorhanden ist.
Es müssen 2 Programme werden weil sich ein Programm mit der
Datenbeschaffung und das andere mit der Verarbeitung befasst. Das
Programm der Datenbeschaffung kann sich später auch ändern bzw. wird
durch ein anderes ersetzt.
Du sagst das in Windows dies über normale Messageques machbar ist.
Meinst du damit die Taskkommunikation oder wirklich die Kommunikation
zwischen 2 Prozessen/Programmen. Wenn ja, wie geht dies?
Josef schrieb:> Es müssen 2 Programme werden weil sich ein Programm mit der> Datenbeschaffung und das andere mit der Verarbeitung befasst. Das> Programm der Datenbeschaffung kann sich später auch ändern bzw. wird> durch ein anderes ersetzt.
was ist denn das für ein Grund?
1. ein programm kann auch mehrere Dinge gleichzeitig machen
(z.b. mit Threads)
2. Ist doch egal ob du nun das eine Programm austauschst oder nicht,
warum
sollte dann der Teil mit der Varbeitung nicht mit ausgetauscht
werden?
dafür hättest du ein Programm was wesentlich besser zur Testen ist.
Sonst passiert es dir früher oder später das beide Programm nicht
zusammenpassen weil du etwas am Datenaustausch geändert hast.
Im Windows gibt es noch ein globale Message, darüber erfolgt z.b. die
Benachrichtung wenn z.b. Windows in den Schlafmodus wechseln will, in
diesen kann man auch Daten austauschen. Ob das sinnvoll ist hängt aber
von der Menge und häufigkeit der Daten ab.
Ich möchte dies aber in 2 Programmen machen, da sich 1. später jemand
anderes mit dem einen Teil beschäftigen soll und 2. ich später wirklich
nur ein Programm anpassen/austauschen möchte ohne das andere anzupassen.
Klar das die Schnittstelle für den Datenaustausch fest geregelt sein
muss damit es zu keinen Problemen führt.
Die Geschichte mit den globalen Messages klingt nicht Sinnvoll. Es
werden sicher im sekunden Takt um die 256 Bytes abgefragt. Anscheinend
könnte es am besten per Socketverbindung passieren. Oder einer
"virtuellen Datei" aber da weiß ich noch nicht wie ich eine Dateianlege
die nicht aufs Flashlaufwerk geschrieben werden soll sondern nur im RAM
zur Verfügung steht.
In welcher Weise könnte man denn das ganze als DLL nutzen? Bei der DLL
müsste ich dann eine Funktion für den Datenaustausch implementieren und
das eine Programm ruft diese Funktion dann auf? Eventuell wäre das noch
eine alternative. Dabei müsste ich aber noch eine Initfunktion
erstellen, die in dem zweiten Programm immer aufgerufen wird.
Zwie Blum schrieb:> @Peter: "Teile und herrsche". Weil das unter Windows sooo schwierig ist,> sind die Programme ja auch solche Wasserköpfe.
ja aber wenn der code für eine Seriellen Schnittstelle kleiner ist, also
der code für IPC dann fragt man sich schon nach dem sinn.
Dazu kommen dann noch solche Probleme wie, wer startet denn das
2.Programm? wer beendet es wieder. Was passiert wenn das
auswerteprogramm zwei mal gestartet wird?
sinvollerweise müsste man den seriellen Teil in einen Dienst auslagern
der vom System gestartet wird. (keine ahnung ob das bei CE auch geht).
@Josef
Aber eine DLL ist hat erstmal wenig mit IPC zu tun. Wenn du es mit einer
DLL machen willst dann geht es auch ohne IPC. eine C (nicht C++) dll
kannst du ohne PRobleme von .net ansprechen.
vielen dank für eure diskussionsbeiträge.
Das die ganzen Fehler abgefangen werden müssen ist mir schon klar und
ist auch ein großer Aufwand, trotzdem soll der Teil ausgelagert werden.
Meine Frage bezüglich der DLL Geschichte ist noch: Kann ich die DLL auf
dem Gerät tauschen und mit einer neuen DLL die z.B. dann über TCP/IP
arbeitet ersetzen und das Programm läuft weiter? Also wird die DLL zur
Laufzeit eingebunden oder beim Kompilieren?
Beide Programme werden im Autostart gestartet, das sollte Windows CE
doch noch schaffen....hoffentlich.
Das Programm, welches im moment die Serielle Schnittstelle bedient muss
später auch Realtimefähig sein. Das andere Programm wird in .net
Programmiert und ist somit schon nicht mehr Echtzeitfähig. Das ist auch
ein Grund, weswegen es 2 Programme sein müssen.
Einfacher für das spätere Handling wird somit eine IPC anstatt die DLL
Variante.
Josef schrieb:> Meine Frage bezüglich der DLL Geschichte ist noch: Kann ich die DLL auf> dem Gerät tauschen und mit einer neuen DLL die z.B. dann über TCP/IP> arbeitet ersetzen und das Programm läuft weiter? Also wird die DLL zur> Laufzeit eingebunden oder beim Kompilieren?
das kannst du machen wie du willst. Aber wenn du sie zur laufzeit
tauschen willst dann musst du im program die möglichkeit vorsehen die
dll zu entladen. Ob es aus .net geht weiss ich nicht. Windows bietet es
aber grundsätzlich an.
> Das Programm, welches im moment die Serielle Schnittstelle bedient muss> später auch Realtimefähig sein.
nur mal aus neugier - warum?
Geht es dir nur darum um keine Daten zu verlieren oder müssen die daten
in einer gewissen zeit angenommen und bestätigt werden?
ok. die dll geschichte klingt doch nicht so simpel wie gedacht. ich
hätte erwartet das ich sie 1:1 an die Stelle kopiere und alles gut ist.
Das Programm welches die Serielle Schnittstelle bedient wird später
durch ein Programm ersetzt welches Echtzeitfähig arbeiten muss. Es
werden dort Programme mit genauem Zeitverhalten abgearbeitet. Bei der
Seriellenschnittstelle lassen sich auch Timeouts definieren, diese
müssen auch exakt arbeiten. Ich weiß nicht 100% ob sie das bei .net
tuen. Ich weiß zwar auch nicht ob sie das in C/C++ machen aber dort gehe
ich einfach davon aus.
Josef schrieb:> ok. die dll geschichte klingt doch nicht so simpel wie gedacht. ich> hätte erwartet das ich sie 1:1 an die Stelle kopiere und alles gut ist.
Das kann so ablaufen. Ja.
> Das Programm welches die Serielle Schnittstelle bedient wird später> durch ein Programm ersetzt welches Echtzeitfähig arbeiten muss.
definiere was 'echtzeitfähig' für dich bedeutet.
Dir ist hoffentlich auch klar, dass die Fähigkeit 'echtzeitfähig'
abzulaufen hauptsächlich vom zugrundeliegenden Betriebssystem abhängt?
Wenn Windows seinen Plattencache aufräumt, dann räumt es den auf. Andere
Prozesse haben dann Pause, wenn Windows es will.
Josef schrieb:> Es> werden dort Programme mit genauem Zeitverhalten abgearbeitet. Bei der> Seriellenschnittstelle lassen sich auch Timeouts definieren, diese> müssen auch exakt arbeiten.
wenn du sich bei der Schnittelle einrichtest dann ist es egal ob du es
von .net oder c++ machst, es wird jeweil dem Betriebssystem übergeben.
Um welche genaue zeitverhalten geht es denn? Millisekunden, Sekunden?
.net ist erstmal nicht wirklich langsamer als mit c geschrieben
programme. Und wenn es wirklich nur um ein paar byte gehen die von der
Schnittstelle kommen wird es kein unterschied machen.
Meist sind sogar schlecht geschriebene C++ Programme langsamer als
welche in C#, weil viele gar nicht bewusst ist das Objekte kopiert
werden.
Es geht dabei um Millisekunden. Betriebssystem ist Windows CE 6.0 R2.
Windows garantiert ein 1ms Taskzyklus mit einem Glitch von max. ca.
100µs. Bei .net Programmen räumt Windows zwischendurch den Cache auf und
zerstört damit die Echtzeit, bei C/C++ Programmen ist dies aber nicht
der Fall und bleibt weiterhin im 1ms Takt.
Die größe der Datenmenge wird sich im Bereich von 256Bytes abspielen,
also nicht wenig aber auch keine riesen Mengen.
Das Echzeitfähigeprogramm muss später mit genauen Taskzeiten arbeiten
und da darf es keine Toleranz von mehren ms geben. Einzelne Tasks werden
mit 10ms oder 100ms arbeiten.
"Meist sind sogar schlecht geschriebene C++ Programme langsamer als
welche in C#..." gibt es da auch mehr Informationen drüber? Was zeichnet
denn ein schlecht geschriebenes C++ Programm aus? Gibt es
Funktionen/Algorithmen/Methoden/Arbeitsweisen die man defintiv vermeiden
sollte?
Josef schrieb:> gibt es da auch mehr Informationen drüber? Was zeichnet> denn ein schlecht geschriebenes C++ Programm aus? Gibt es> Funktionen/Algorithmen/Methoden/Arbeitsweisen die man defintiv vermeiden> sollte?
class data
{
char p[100];
};
langsam
void test1( const data d ) { /* mach was mit d /* };
schneller
void test2( const data& d ) { /* mach was /* };
das sind halt die Feinheiten.
Ich war auch immer der Meinung das Java/#c langsam ist, aber nach ein
paar Tests hat sich gezeigt das kaum Anwendungen gibt wo man es
wirklicht merkt. Meist kommt die langsamkeit nicht von der Sprache
sondern sondern von einer falschen/ungünstigen Umsetzung der Aufgabe.
Also der Aufruf per Namensreferenz ist schneller als ein direkter
zugriff auf eine variable/klasse?
gibts dafür eine sinnvolle erklärung? kann der compilier referenzen
sinnvoll zwischenspeichern und bei wenigen somit schneller arbeiten und
bei mehreren macht es kein unterschied mehr?
Josef schrieb:> Also der Aufruf per Namensreferenz ist schneller als ein direkter> zugriff auf eine variable/klasse?>> gibts dafür eine sinnvolle erklärung?
Es muss beim Aufruf keine Kopie des Arguments gemacht werden.
Reicht das?
Entscheidungsbaum für Argumenttypen
1
Ja Nein
2
+----- Will die Funktion eine Variable --------+
3
| beim Aufrufer ändern können? |
4
| |
5
v |
6
Ja Gibt es den Fall, dass der Nein |
7
+-- Aufrufer keine Variable hat? -----+ |
8
| | |
9
| | |
10
v v |
11
Verwende einen Pointer Verwende eine Referenz |
12
|
13
|
14
+--------------------------+
15
|
16
Ja v
17
+------------- Handelt es sich um einen -----------+
18
| eingebauten skalaren Datentyp? |
19
| (char, int, long, double, etc) |
20
| |
21
v v
22
Verwende pass per value Verwende eine const Referenz
Also:
Ich denke die Dll mit einem eigenen Task dürfte für Dich das richtige
sein.
1. Dll (DYNAMIC Link Library) werden immer zur Laufzeit geladen (nur
wenn Du Sie bei laufendem Programm austauschen willst wirds etwas
komplizierter)
2. Wenn Du kurze reaktionszeiten haben willst, dann gib dem task in der
dll einen höhere priorität als einem normalen Task
http://msdn.microsoft.com/en-us/library/bb202728.aspx
Dann kommen Dir höchsten noch Treiber und das OS in die Quere aber nicht
Dein .net Thread.
Gruß
Tom
ahja klar. die namensreferenz ist ja wie ein pointer auf die variable
und somit erstellt er die variable nicht neu sondern kann direkt
reinschreiben.
ich bin kein großer freund von diesen referenzen weil mir genau die
information fehlt, dass ich direkt immer in der gleichen variable
arbeite.
somit ist das oben aufgeführte beispiel doch auch eine komplett andere
sache. in dem einen programm arbeite ich mit der beim aufruf erstellten
kopie der variable und in der anderen arbeite ich in der aktuellen
variable die sich auch zur laufzeit (bei mehreren tasks) ändern könnte.
also bei der referenz geschichte muss man auch gut aufpassen was man
macht.
Verhindert das const beim Funktionsparameter das die Funktion die
Variable beschreiben kann? Aber es verhindert nicht, dass die Variable
in einer anderen Task manipuliert wird, oder?
3. Wenns unbedingt zwei Processe sein müssen, dann nimm Sockets mit dem
localhost (nein kein Problem mit Firewall, die gibts bei CE
standardmäßig eh nicht) oder
4. Wenn Du eine message queue nehmen willst, nimm CreateMsgQueue da
brauchst Du keine Handles:
http://msdn.microsoft.com/en-us/library/bb202792.aspx
Gruß
Tom
Josef schrieb:> also bei der referenz geschichte muss man auch gut aufpassen was man> macht.
nicht wirklich.
Du musst nur const korrekt arbeiten. Das ist dann schon fast alles.
Dafür kriegst du dann aber auch etwas: Du versetzt den Compiler in die
Lage, dich in noch stärkerem Umfang vor dir selber zu schützen.
Und, oh ja.
Multitasking ist dann sowieso wieder eine eigene Sache. Das hat aber
wieder weniger mit Referenzen zu tun, als viel mehr der Anwendung von
Synchronisierungsmechanismen wie Semaphoren etc.
Hört sich so an, als ob Du bisher noch nicht viel mit C/C++ gemacht
hast, sonst wären Pointer/Referenzen was völlig normales.
Wenn Du Dih mit const nichts auskennst, dann würde ich es erst mal
weglassen. Wenn man es nämlich nicht ganz konsequent im ganzen Programm
macht kommt man schnell in teufels küche und fängt an das const
wegzucasten.
Zur windows Processen/Taks etc kann ich Dir das hier noch empfehlen:
http://www.amazon.de/Programming-Applications-Microsoft-Windows/dp/1572319968/ref=sr_1_20?ie=UTF8&s=books-intl-de&qid=1276070066&sr=1-20
Ist zwar nicht speziell für CE aber funktioniert dor meist ebenso.
Vielen Dank für eure ganzen Tips.
Ich hab mir dieses Buch bestellte:
http://www.amazon.de/Programming-Windows%C2%AE-Developer-Reference-PRO-Developer/dp/0735624178/ref=sr_1_1?ie=UTF8&s=books-intl-de&qid=1276070917&sr=8-1
Dauert aber noch bis es ankommt.
Ich habe vorher nut mit Pointer gearbeitet und nicht mit Referenzen.
CreateMsgQueue gibt mir jeweils den gleichen Handler zurück wenn ich den
gleichen Namen in 2 Programmen aufrufe? Das wäre ja klasse.
So wie es aussieht wirds nun die Socketverbindung. Im moment mit einer
Localenverbidnung und später könnte diese Leicht durch eine externe
socket verbindung ersetzt werden. Diese Variante klang auch sehr
interessant. Wobei mich bei der Socketverbindung der Overhead etwas
stört.
Sachen wie Semaphoren/Mutex und andere Spermechanismen sind mir schon
ein Begriff und habe ich in kleineren Programmen auf einem Unixsystem
genutzt, doch die Windowswelt ist neu für mich.
Josef schrieb:> CreateMsgQueue gibt mir jeweils den gleichen Handler zurück wenn ich den> gleichen Namen in 2 Programmen aufrufe? Das wäre ja klasse.
Exakt, wie sonst soll das andere Programm wissen wie es auf die Queue
zugreifen kann?
Aber noch mal, ich sehe auch keinen Grund wieso Du nicht ne DLL nimmst.
Mach dort nen eigenen Task mit höherer Priorität auf und gut is.
Ich selbst verwende Referenzen eigentlich kaum sondern meist Pointer, da
damit auch beim Aufruf immer klar ist, ob per reference oder value
übergeben wird.
Tom
P.S.: Handle, nicht Handler
Josef schrieb:> Ich habe vorher nut mit Pointer gearbeitet und nicht mit Referenzen.
Das ist das C Erbe.
In C++ wird wesentlich mehr mit Referenzen gemacht als mit Pointern.
Pointer übergibt man nur dann
* wenn es nicht anders geht, weil zb eine Funktion aus einer Lib
aufgerufen werden soll und die nun mal einen Pointer haben will
* wenn die Funktion ausdrücken will
Eigentlich erwarte ich vom Aufrufer eine Speicherfläche an der
ich meine Ergüsse ablegen kann. Ich gebe aber dem Aufrufer die
Möglichkeit, das auszuschlagen indem er mir einen NULL Pointer
übergeben darf. In dem Fall tu ich dann nichts.
Ansonsten nimmt man Referenzen.
Und nein. Eine Referenz ist nicht per se ein 'versteckter Pointer'. Eine
Referenz ist erst mal nur 'ein anderer Name für eine ansonsten
existierende Variable'. Das hat so zunächst mal nichts mit Pointern zu
tun, auch wenn der Compiler in manchen Fällen Referenzen mittels
Pointern implementiert.
> interessant. Wobei mich bei der Socketverbindung der Overhead etwas> stört.
Von nichts kommt nichts.
Entweder du willst die Flexibilität, die Verbindung auch über Kontinente
hinweg herstellen zu können, oder du willst sie nicht.
Aber ist ja kein Problem, ist ja schliesslich C++
Da gibt es dann eine Basisklasse, die für den Rest des Programms ein
Interface beschreibt, welches völlig losgelöst von irgendwelcher
Technologie den Kommunikationsendpunkt beschreibt.
Und davon abgeleitet gibt es dann zb eine Klasse, die die eigentliche
Kommunikation über TCP/IP implementiert oder eine andere Klasse, die
dasselbe mittels Queues macht oder eine 3te, die das über Shared Memory
erledigt, etc ....