Ist es möglich, GREIFT zu ändern, die für die synchrone E / A geöffnet wurde für asynchrones I / O während seiner Lebensdauer geöffnet werden?

StackOverflow https://stackoverflow.com/questions/2475713

Frage

Die meisten meiner täglichen Programmierarbeit in Windows sind heute um I / O-Operationen aller Art (Rohre, Konsolen, Dateien, Steckdosen, ...). Ich bin mir sehr wohl bewusst, verschiedener Methoden des Lesens und von / zu verschiedenen Arten von Griffen zu schreiben (synchron, asynchron Warten auf Abschluss auf Ereignisse, Warten auf Datei-Handles, I / O-Abschluss-Ports und Warnbare I / O). Wir verwenden viele von denen.

Für einige unsere Anwendungen wäre es sehr nützlich sein, nur eine Möglichkeit zu haben, alle Griffe zu behandeln. Ich meine, kann nicht das Programm wissen, welche Art von Griff er empfangen hat, und wir verwenden möchte, sagen wir mal, E / A-Abschlussports für alle.

Also zuerst möchte ich fragen:

Nehmen wir an, ich habe einen Griff:

HANDLE h;

, die von meinem Prozess von irgendwo für I / O empfangen wurden. Gibt es eine einfache und zuverlässige Art und Weise, um herauszufinden, welche Fahnen mit erstellt wurde? Die Haupt-Flagge in Frage FILE_FLAG_OVERLAPPED.

Der einzige Weg, mir bisher bekannt, ist zu versuchen, solchen Griff in I / O-Completion-Port (mit CreateIoCompletionPort()) zu registrieren. Wenn das der Griff gelingt es wurde mit FILE_FLAG_OVERLAPPED erstellt. Aber nur dann, I / O-Completion-Port verwendet werden muss, da der Griff nicht von ihm ohne Schließen des HANDLE h selbst nicht registriert werden kann.

Providing gibt es eine einfache Art und Weise einer Präsenz von FILE_FLAG_OVERLAPPED, um zu bestimmen, es wäre meine zweite Frage kommen:

Gibt es eine Möglichkeit, wie diese Flagge zu bereits bestehenden Griff hinzufügen? Das würde einen Griff machen, die ursprünglich geöffnet war für synchrone Operationen für asynchrone offen zu sein. Gäbe es eine Möglichkeit geben, wie entgegengesetzt zu schaffen (entfernen Sie die FILE_FLAG_OVERLAPPED von asynchronen Synchron Griff erstellen)?

Ich habe keinen direkten Weg nach der Lektüre über MSDN und googeln viel gefunden. Gäbe es zumindest einigen Trick sein, die das gleiche tun könnten? Wie neu zu erstellen, den Griff in gleicher Weise mit CreateFile() Funktion oder etwas ähnliches? Etwas auch nur teilweise dokumentiert oder nicht dokumentiert überhaupt?

Der Haupt Ort, wo ich diese benötigen würde, ist es, die die Art und Weise (oder die Art und Weise) Verfahren zur Bestimmung sollten durch Anwendungen von Drittanbietern lesen / schreiben, um es von Griffen gesendet. Wir können nicht kontrollieren, wie Produkte von Drittanbietern erstellen ihre Griffe.

Lieber Windows-Gurus: Hilfe bitte

Im Hinblick

Martin

War es hilfreich?

Lösung 2

3 Jahre vergangen und Windows 8 wird veröffentlicht. Dank der Regression bei der Umsetzung der Konsole in Windows 8 ich eingeführt hat etwas über das Problem zu tun, die diese Frage ausgelöst. Also habe ich schließlich versucht ReOpenFile () Funktionsaufruf zu verwenden.

In einem Satz:. Für meine Zwecke ist es nutzlos

Die ReOpenFile () API wird für „unter eine vorhandene Datei-Handle und bekommen einen anderen Griff, der einen anderen Satz von Zugriffsrechten hat“ verwendet. Mindestens das angegeben ist in der Originalartikel .

Ich habe versucht, die ReOpenFile () auf Console Eingabegriff zu verwenden:

  stdin_in = GetStdHandle(STD_INPUT_HANDLE);
  stdin_in_operlapped = ReOpenFile(stdin_in, GENERIC_READ | GENERIC_WRITE,
                                   FILE_SHARE_READ, FILE_FLAG_OVERLAPPED);
  if (stdin_in_operlapped ==  INVALID_HANDLE_VALUE)
    {
      my_debug("failed to ReOpen stdin handle with OVERLAPPED flag: %d", GetLastError());
      exit(1);
    }

Und was ich erhalte, ist: Fehler 1168: „Element nicht gefunden“. „Danke Microsoft“. Ich werde nicht einmal versuchen, es für anonyme Rohre zu verwenden, da die Dokumentation heißt es:

„Asynchronous (überlappt) Lese- und Schreibvorgänge werden nicht von anonymen Leitungen unterstützt. Dies bedeutet, dass Sie nicht die ReadFileEx und WriteFileEx Funktionen mit anonymen Pipes verwenden. Darüber hinaus wird die LpOverlapped Parameter von Readfile und Writefile ignoriert, wenn diese Funktionen mit anonymen Rohren verwendet werden.“

Danke, Leute, die alle für Ihre Anregungen. Wenn asynchron vom Griff zu lesen, muss man bereit für die Tatsache auch sein, dass der Betrieb synchron vervollständigen kann. Dass ich weiß. Der Hauptgrund dafür war ich diese Frage lautet:

wenn eine synchrone Lese hat dich auf einig Objekten ausgegeben (zumindest anonyme Rohre und Konsoleneingabe in Windows 8), dann ruft Closehandle () von einem anderen Thread auf dem gleichen Griff entweder ausfallen oder hängen, bis die Readfile () abgeschlossen ist; dass Mittel wird es auf unbestimmte Zeit in vielen Fällen hängen. Das ist der Grund, warum ich den Synchron Griff mit asynchronem ersetzen wollte.

Jetzt ist es mir klar, dass es in Windows-Betriebssystemen einfach nicht möglich ist, einige Lesevorgänge in einfacher Weise zu stornieren. Wenn von Synchron Griffe Lesen, man muss nur Ausfahrt aus der Anwendung selbst wenn ReadFile- () noch in einem Thread von einem Griff zu lesen, weil es einfach unmöglich ist, zuverlässig eine solche Leseoperation aufzuwachen. In Know ... In neueren OS ist es möglich, dass die Operation abzubrechen. Allerdings gibt es keine Möglichkeit, Wetter der Faden in der ReadFile- () -Aufruf ist zu wissen, schon oder noch nicht. Wenn ReadFile- () ist noch nicht dann genannt gibt es keine Operation abzubrechen und nachfolgende Lese hängen wird. Der einzige Weg wäre, um den Griff zu schließen, aber die Operation hängt, oder nicht auf einig Objekten und auf einigen Betriebssystemen. Die einzig richtige Lösung ist, asynchrones I / O. Aber, wie ich schon eingangs erwähnt, unsere APP wird gestartet, indem Anwendungen von Drittanbietern und wir können sie nicht dazu zwingen, alle für immer Named Pipes mit der stdio überlappten-Flag erstellen.

Ich gebe auf und gehen böse hässlichen Hacks zu implementieren ... wir werden ohne ÜBERLAPPVERBINDUNG Struktur aus Griffe Lesen haben zu halten, die mit ÜBERLAPPVERBINDUNG Flagge erstellt wurden, und Griffe und Gewinde undicht ....

Andere Tipps

Ich sehe, ich war ein schlechter Leser von MSDN: / ich total verpasst Funktion ReOpenFile() die wahrscheinlich schon im Juni 2003 in Windows Server 2003 (gemäß dieser Artikel ). Zu verteidigen ich zumindest ein wenig: Ich würde erwarten, dass die CreateFile() Beschreibung Querverweis auf ReOpenFile() Beschreibung. Es gibt eine Referenz auf ReOpenFile() Seite CreateFile() Seite, aber nicht umgekehrt.

Diese Funktion scheint genau zu aktivieren, was ich brauche: Hinzufügen oder aus bereits bestehenden Griffen von FILE_FLAG_OVELRAPPED auf / zu entfernen, indem sie mit dem gewünschten Eigenschaften neuen Griff zu schaffen! obwohl :-D ich habe es noch nicht getestet. Es ist leider nur unter Windows 2003 Server, Windows Vista und ab. Frage über die früheren OS-Versionen beantwortet wurde hier . Die Funktion existiert nicht in der öffentlichen API in OS vor Windows 2003 Server. Es wird durch die zugrunde liegende Implementierung verwendet, aber es ist für Entwickler auf diesen Systemen nicht verfügbar (nicht unterstützt).

Das bedeutet praktisch, dass es keine Hoffnung für mich ist, zumindest für die nächsten paar Jahre, bis wir Drop-Unterstützung für ältere Windows-Plattformen. Es bedeutet auch, dass die Situation der I / O in Bezug auf OS älter als Windows Vista wirklich schlecht gewesen. Anderer schmerzhafter Teil, insgesamt wurde die Möglichkeit wurde fehlende synchrones und asynchrones I / O auf diesen älteren Systemen zu löschen.

Außerdem vermisst ich immer noch einen Teil der Antwort: kann das Vorhandensein von Fahnen mit irgendwelchen Mitteln getestet werden? Ich habe nicht Funktion dafür, dass gefunden. Das bedeutet, dass, wenn wir zu garantieren Anwesenheit von etwas Flagge in Dateiobjekt wollen, dann immer die Datei wieder geöffnet sein muss.

Wenn ich verstehe, was Sie nach, würde Ich mag empfehlen, wenn es egal, mit der sich überlappenden Flagge oder nicht geöffnet. Ich glaube, dass Sie sicher in einer OVERLAPPED Struktur sowohl in den synchronen und asynchronen Fällen passieren können. Ihr Code muss Griff ReadFile() Rückkehr false und GetLastError() Rückkehr ERROR_IO_PENDING können. Sie werden auch entsprechende Anrufe GetOverlappedResult(), WaitForSingleObject() etc.

hinzufügen müssen

Der MSDN-Artikel auf ReadFile() hat einige gute Informationen hierzu finden Sie unter „Überlegungen zum mit synchroner Datei-Handles arbeiten“ und „Überlegungen für mit asynchroner Datei-Handles arbeiten“ in dem „Synchronisation und Datei-Position“ Abschnitt.

Testing Griff Flaggen sollten wahrscheinlich die gleiche Art und Weise durchgeführt werden wie die Berechtigungen Testen der Griff mit erstellt wurde. Versuch es. Wenn die API fehlschlägt, versucht, den Rückfall. Wenn das fehlschlägt, einen Fehler zurück.

Ich denke, die wirklich zu sagen, was die Art und Weise ist die Dokumentation für ReadFile- sagt: „Wenn hFile mit FILE_FLAG_OVERLAPPED geöffnet, ... Funktion falsch, dass der Lesevorgang abgeschlossen ist mitteilen.“

Meine Interpretation des Fehlers ist, (und die Frage, die Sie sich stellen müssen, ist): Wenn es möglich war, den überlappten Status einer Datei-Handle zu überprüfen, warum sollte ReadFile- nicht, dass der Check machen und dann die überlappten Struktur validieren entsprechend , explizit in einer nicht überlappenden Art und Weise mit einem überlappenden Griff, wenn genannt scheitern?

Ich weiß nicht, einen Weg, um die Flagge eines Griffs zu bestimmen und die Nebenwirkungen von api ReOpen verwenden, aber da Ihr Ziel war

  

wäre es sehr nützlich sein, nur eine Möglichkeit zu haben, alle Griffe zu behandeln

Wenn Sie synchrones Verhalten wünschen (ich meine mit synchronen api für nicht überlappende Griffe und Asynchron-api gefüttert mit ÜBERLAPPVERBINDUNG Struktur mit anschließender Wartezeit auf der Veranstaltung überlappend) Sie können immer die Asynchron api verwenden auch wenn der Griff in nicht überlappten Modus wie bereits erwähnt von @Brett
eröffnet Ich kann bestätigen, dass dies funktioniert (zumindest für Named Pipes) es:

void connectSynchronous(HANDLE hPipeThatWeDontKnowItsFlag){
    ...
    BOOL bRet = ::ConnectNamedPipe(hPipeThatWeDontKnowItsFlag, pOverlapped);

    if(bRet == FALSE){
        DWORD dwLastErr = ::GetLastError();

        if(dwLastErr == ERROR_IO_PENDING){
            //The handle was opened for asynchronous IO so we have to wait for the operation
            ...waitFor on the overlapped hEvent;

        }else if(dwLastErr == ERROR_PIPE_CONNECTED){
            //The handle was opened for synchronous IO and the client was already connected before this call: that's OK!
            return;
        }else{
            throw Error(dwLastErr);
        }
    }/*else{
        //The handle was opened for synchronous IO and the client has connected: all OK
    }*/
}

Eine Alternative zum CreateIoCompletionPort Hack ist ein Null-Byte-Readfile mit einem NULL LpOverlapped zu tun. Wenn es mit ERROR_INVALID_PARAMETER nicht annehmen, dass es mit FILE_FLAG_OVERLAPPED geöffnet wurde.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top