Asynchroner Zugriff auf eine Pipe
-
hiho allerseits.
mal eine Frage zum asynchronen Zugriff auf files/pipes.
ich habe zwei Prozesse am laufen, die über ein Pipe kommunizieren sollen.
Leider kann es vorkommen, dass der Client beim Auslesen der Pipe aus dem ReadFile nicht returnt.
Vermutlich greifen in diesem Moment Server und Client gleichzeitig auf die Pipe zu.
Ich wollte dem Abhilfe schaffen und hab die Pipe mit dem Flag FILE_FLAG_OVERLAPPED erzeugt sowie eine Overlapped Struktur und ein Event erzeugt auf welches, so denke ich, gewartet wird, bis der Schreib/Leseprozess abgeschlossen ist.OVERLAPPED o; memset(&o, 0 , sizeof(o)); o.hEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); bool bOK = ReadFile(m_hPipe, m_achPipeInBuffer, PIPE_BUF_SIZE, &dwReadCnt,&o) != 0; if (!bOK && GetLastError() == ERROR_IO_PENDING ) { WaitForSingleObject(o.hEvent, INFINITE); CloseHandle(o.hEvent); bOK = true; }
Der ganze Spass funktioniert aber leider so nicht. ReadFile return nicht. (gar nicht)
Kann mir vielleicht jemand sagen, wo der Fehler liegt und mir nen Tipp geben wie ich den Zugriff auf die Pipe asynchron zum Laufen bringe?
Bzw. würde es mit ja schon reichen, vor dem Zugriff auf die Pipe einfach nur sicherzustellen, dass momentan kein anderer Prozess auf diese Zugriff hat.
WaitForSingleObject(hPipe) funzt da leider net.thx
Watto
-
Aus der MSDN:
If hFile was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is not NULL, the read operation starts at the offset specified in the OVERLAPPED structure and ReadFile may return before the read operation has been completed. In this case, ReadFile returns FALSE and the GetLastError function returns ERROR_IO_PENDING. This allows the calling process to continue while the read operation finishes. The event specified in the OVERLAPPED structure is set to the signaled state upon completion of the read operation.
-> ReadFile kehrt zurück, aber Dein WaitForSingleObject wartet ewig. Da ReadFile nicht wieder aufgerufen wird, kann auch der Status des Events nicht gesetzt werden.
-
nunja... eigentlich returnt er ja aus dem ReadFile ja gar nicht, das ist ja das wunderliche.
aber vielleicht hängt das ja irgendwie alles mit dem wait zusammenwas tun? ...
sprache zeuswoher weiß ich nun wann der readfile zugriff beendet wurde?
-
Du hast nicht zufällig ein Windows NT-Derivat auf dem das Teil nicht läuft oder? Ich hatte nämlich ein ähnliches Problem mit Overlapped-Com-Port-Zugriff unter NT(5.0). Zum Schluss stellte sich heraus, dass die Member der Overlapped-Struktur welche laut MSDN mit folgender Zeile beschrieben sind: "This member is ignored when reading from or writing to named pipes and communication devices" (Konkret: Offset und OffsetHigh) eben doch nicht ganz so ignoriert werden wie man sich das gerne wünscht. Sie müssen nämlich explizit null gesetzt werden.
BTW: Hast du die Pipe auch im Overlapped-Modus geöffnet?
-junix
-
HI !
.. hab nicht alles 100%ig gelesen, aber mach doch aus der einen Pipe
einfach 2 Pipes. Eine zum Lesen und eine zum Schreiben. Beide Prozesse
sollten dann natürlich diese entgegengesetzt nutzen und mindestens 2 Threads
zum handling dieser haben..mfg
-
Hab nochmal etwas nachgeforscht: Anonyme Pipes (CreatePipe) können kein Overlapped IO. Das geht nur mit Named Pipes (CreateNamedPipe) (funktioniert aber nur auf NT soviel ich weiss).
Was du aber tun könntest um ein "Quasi Overlaped" Verhalten zu erzeugen ist, nur soviel zu lesen, wie auch tatsächlich in der Pipe pendent ist. Mit PeekNamedPipe(pipe_HANDLE, NULL, 0, NULL, &BytesToRead_DWORD, NULL) kannst du die Anzahl Bytes die zum Zeitpunkt des Aufrufs in der Pipe liegen ermitteln.
(Ja, PeekNamedPipe funktioniert auf allen Win32 Systemen)-junix
-
ja die pipe läuft mit dem overlapped flag und die overlapped struktur hab ich auch noch mal explizit "genullt".
reneg hat recht. es liegt an dem waitforsingleobject auf serverseite, welches nicht return und somit returnt auch readfile auf der client seite nicht (vermute ich mal), da er wohl wartet bis der schreibprozess auf serverseite abgeschlossen ist.
man muss dazu sagen, dass meine pipe auch im WAIT modus läuft. das heißt, dass read/write erst returnen, wenn der prozess abgeschlossen ist. spezifizier ich das flag nicht,gehen, so hab ich das gefühl, einige daten in der pipe verloren.naja bin grad nochn bissl am rumtüffeln.
-
Wieso gehen Daten verloren? Meine erfahrung mit Pipes zeigte, dass der schreibende Prozess bei einer vollen Pipe wartet, bis es wieder Platz gibt. (Handelte sich um das Auslesen einer Konsolenausgabe)
die Zeile memset hatte ich vermutlich überlesen, sorry.
-junix
-
ok, das mit dem NOWAIT flag war doch keine so dumme idee. so block er wenigstens
nicht das ausführen der read/write operation.das mit der "doppelpipe" hab ich auch schon mal ausprobiert @hardcoreProgramierer. das klappte. thx
wollte aber trotzdem gern mal die DUPLEX funktion einer pipe ausprobieren und gerne wissen wie man den gleichzeitigen (asynchronen) zugriff auf ein und die selbe pipe instanz handelt.
nur um noch mal konkret zu werden. wie kann man feststellen ob ein prozess gerade auf eine read/write operation zugreift (und wie warte ich bis die operation für den aufrufen prozess wieder verfügbar ist)? und was genau bewirken nun diese eventhandles?
thx