Entwickler-Ecke
Windows API - Schnelle IPC
Flamefire - Di 31.08.10 11:37
Titel: Schnelle IPC
Ich habe einen Slaveprocess und einen Masterprocess.
Der Slaveprocess hat eine Tabelle mit Einstellungen, auf die er ständig zugreift (>10 mal je Sekunde)
Aus dem Masterprocess will ich jetzt diese Tabelle ändern können.
Synchronisierung ist nicht nötig (nicht schlimm, wenn die Tabelle nicht vollständig geschrieben wurde, bevor sie gelesen wird)
Wichtig ist nur, dass des Lesen absolut schnell geht (ohne Zusatzaufwand)
Wie mache ich das?
jaenicke - Di 31.08.10 12:24
Kennst du schon, mit MMFs. Mehr dazu heute Abend nach der Arbeit. ;-)
delfiphan - Di 31.08.10 16:51
Ist diese Tabelle eine Klasse? Oder ein Array of Records, und was für Daten hast du drin? z.B. Strings?
Im Prinzip kannst du mir MMF Shared Memory haben (ein Memoryblock, der in mehreren Prozessen identisch ist) du musst einfach mit Pointern aufpassen.
Boldar - Di 31.08.10 19:10
ist das Pollen wirklich nötig, oder kannst du nicht auch dem Slave ne message schicken, wenns was neues gibt?
Flamefire - Di 31.08.10 19:58
Der Slave ist ne DLL in nem andren Prozess. Die kümmert sich darum, dass verschiedene Tasten vertauscht werden.
Diese "vertauschung" steht in einem statischen Array. Also kein Pointer-Probleme.
Message kann ich nicht senden, da ich kein Fenster habe.
Delete - Di 31.08.10 20:18
Du kannst auch mit PostThreadMessage eine Nachricht an einen Thread eines Prozesses ohne Fenster senden.
delfiphan - Di 31.08.10 20:45
Wenn es eine Konsolenapplikation ohne GUI ist, kannst du dir auch einen Thread mit Messageloop machen:
http://www.delphi-library.de/topic_Ereignisorientierte+ThreadsMessage+Handling_90333,0.html
Dann schickst du die Konfiguration per WM_COPYDATA
Oder ändert sich die Konfiguration ständig?
Und sonst ist MMF sicher auch eine Lösung.
EDIT: Die Library oben hat einen bösen Bug. Und zwar verwende ich dort Classes.AllocateHWnd/DeallocateHWnd in einem Thread. Die Funktionen sind nicht thread-safe (MakeObjectInstance ist nicht thread-safe, weil es die globalen Variablen InstFreeList und InstBlockList verwendet).
EDIT: Nevermind! Hatte meinen Kommentar übersehen
FHandle := Classes.AllocateHWnd(nil);
Es ist also alles gut :)
Delete - Di 31.08.10 21:49
WM_COPYDATA wird nicht funktionieren, da die Nachricht ein Fensterhandle benötigt.
delfiphan - Di 31.08.10 22:00
Luckie hat folgendes geschrieben : |
| WM_COPYDATA wird nicht funktionieren, da die Nachricht ein Fensterhandle benötigt. |
Kriegste mit obiger Library auch. Daher die ganze Geschichte in den Edits mit dem AllocateHWnd. Die Funktion kreiert ja ein Fensterhandle.
Delete - Di 31.08.10 22:28
OK, aber ich würde das mal ausprobieren.
Astat - Di 31.08.10 22:35
Flamefire hat folgendes geschrieben : |
Der Slave ist ne DLL in nem andren Prozess. Die kümmert sich darum, dass verschiedene Tasten vertauscht werden.
Diese "vertauschung" steht in einem statischen Array. Also kein Pointer-Probleme.
Message kann ich nicht senden, da ich kein Fenster habe. |
Hallo Flamefire, hier der Klassiker.
1. Thread in der DLL wartet auf Sperrobjekt (Mutex oder Semaphore)
2. Master schreibt neue Daten in MMF und signalisiert Sperrobjekt
3. DLL Thread liest Daten, und vertauscht Tasten, und wartet wieder auf Sperrobjekt.
usw......
Somit ist permanentes Polling nicht notwendig.
lg. Astat
delfiphan - Mi 01.09.10 07:15
Wenn es einfach nur ein Array of Integer ist und ihm egal ist, ob das Array als ganzes bereits geschrieben wurde oder nicht, muss er nicht locken.
Ich glaube 32-bit aligned sollten die Integers aber sein und sie müssen auch als Integers geschrieben werden (nicht einzelne Bytes schreiben). Das müsste man nochmals genauer nachschauen.
Flamefire - Mi 01.09.10 10:54
Die DLL braucht dauerhaften Zugriff auf die Daten. Geändert werden die nur 1 mal bis sehr selten. Wenn für nen winzigen Moment die Daten nicht konsistent sind, ist das egal.
Ich muss nur wissen, wie ich direkt aus dem Addressbereich der DLL lesen und schreiben kann. Von mir aus auch per Writeprocessmemory. Ich muss nur irgendwie herauskriegen, wo die Struktur liegt.
Aber wie?
Edit: Ok...delphiphan hat ne Klasse veröffentlicht. Einfach gehts nicht. Thx
Flamefire - Mi 01.09.10 17:39
Kann ich auch einen SharedMemory auf einen bestehenden Speicher setzen? Also dass ich in meinem Fall den Pointer auf meine Struktur übergebe, und der den bestehenden Bereich dann "shared" setzt?
delfiphan - Mi 01.09.10 20:46
Nein. Das sind spezielle Memorybereiche. Damit kann der Delphi Memory Manager auch nicht umgehen und wenn, dann hättest du Zwingend andere Sachen auch, weil der Pointer i.A. nicht korrekt aligned ist.
Boldar - Mi 01.09.10 20:59
Was spricht denn gegen die gennanten Möglichkeiten mittels messages?
jaenicke - Do 02.09.10 04:57
Flamefire hat folgendes geschrieben : |
| Kann ich auch einen SharedMemory auf einen bestehenden Speicher setzen? |
Du brauchst doch nur umgekehrt deinen Pointer ändern. Einen großen Unterschied macht das für dich doch gar nicht.
Boldar hat folgendes geschrieben : |
| Was spricht denn gegen die gennanten Möglichkeiten mittels messages? |
Wenn das nur so selten geändert werden soll, geht es so auch, denn dann kann der Empfänger die neuen Daten selbst schreiben. Einfacher ist aber ein solcher gemeinsamer Speicher, dann kann man es direkt ändern.
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!