Frage

Ich habe ein Projekt, das ich dachte, würde relativ einfach sein, aber erweist sich mehr Schmerz sein, die ich gehofft hatte. Erstens sind die meisten der Code, den ich mit interagieren bin ist Legacy-Code, dass ich nicht die Kontrolle über, so kann ich große Paradigmenwechsel nicht.

Hier ist eine vereinfachte Erklärung dessen, was ich tun muss: Sagen, dass ich eine große Anzahl von einfachen Programmen, die von der Standardeingabe und schreiben zu stdout lesen. (Diese kann ich nicht berühren). Grundsätzlich Eingang stdin ist ein Befehl wie „Solltemperatur auf 100“ oder so ähnlich. Und der Ausgang ist ein Ereignis „Temperatur auf 100 gesetzt worden ist“ oder „Temperatur wird unter dem Sollwert gefallen ist“.

Was möchte ich zu tun ist, eine Anwendung zu schreiben, die ein Bündel von diesen einfachen Programme starten können, für Ereignisse beobachten und dann Befehle, um sie bei Bedarf senden. Mein erster Plan war, so etwas wie popen, aber ich brauche eine Bidrectional popen zu erhalten Lese- und Schreibleitungen. Ich gehackt etwas zusammen, dass ich popen2 nennen, wo ich den Befehl übergeben * laufen und zwei Datei, die mit dem Lese gefüllt werden und Stream schreiben. Dann alles, was ich tun muß, ist eine einfache Schleife zu schreiben, die von jedem des stdouts von jedem des Prozess liest, macht die Logik, die es braucht und dann Befehle wieder auf den richtigen Prozess schreibt.

Hier einige Pseudo-Code

FILE *p1read, *p1write;
FILE *p2read, *p2write;
FILE *p3read, *p3write;

//start each command, attach to stdin and stdout
popen2("process1",&p1read,&p1write);
popen2("process2",&p2read,&p2write);
popen2("process3",&p3read,&p3write);

while (1)
{
   //read status from each process
   char status1[1024];
   char status2[1024];
   char status3[1024];
   fread(status1,1024,p1read);
   fread(status2,1024,p2read);
   fread(status3,1024,p3read);

   char command1[1024];
   char command2[1024];
   char command3[1024];
   //do some logic here

   //write command back to each process
   fwrite(command1,p1write);
   fwrite(command2,p2write);
   fwrite(command3,p3write);
}

Das eigentliche Programm ist komplizierter, wo es in dem Strom späht, um zu sehen, ob etwas wartet, wenn nicht, wird es diesen Prozess überspringt, ebenfalls, wenn es nicht einen Befehl an einen bestimmten Prozess zu senden braucht es nicht . Aber dieser Code gibt die Grundidee.

Jetzt funktioniert dies gut aus auf meiner UNIX-Box und auch ziemlich gut auf einer Windows XP-Box mit Cygwin. Aber jetzt muss ich es nativ auf Win32 zu arbeiten.

Der schwierige Teil ist, dass mein popen2 verwendet fork () und execl (), um den Prozess zu starten und die Ströme zu stdin und stdout der untergeordneten Prozesse zuordnen. Gibt es eine saubere Art, wie ich dies in Windows tun kann? Grundsätzlich würde Ich mag eine popen2 erstellen, die in den Fenstern die gleiche Art und Weise, wie meine Unix-Version funktioniert. Auf diese Weise des einzigen Windows-spezifische Code in dieser Funktion sein würde, und ich konnte mit alles andere arbeiten die gleiche Art und Weise weg.

Irgendwelche Ideen?

Danke!

War es hilfreich?

Lösung

Unter Windows rufen Sie CreatePipe erste (ähnlich Rohr (2)), dann Createprocess. Der Trick dabei ist, dass Createprocess einen Parameter hat, wo man stdin passieren kann, stdout, stderr des neu geschaffenen Prozess.

Beachten Sie, dass, wenn Sie stdio verwenden, müssen Sie tun fdopen das Dateiobjekt danach zu erstellen, die Dateinummern erwartet. In der Microsoft CRT, sind Dateinummern unterscheiden sich von OS Datei-Handles. Also das andere Ende des CreatePipe an den Aufrufer zurückgeben, müssen Sie zuerst _open_osfhandle eine CRT-Dateinummer zu bekommen, und dann fdopen darauf.

Wenn Sie sehen möchten, Code arbeiten Besuche _PyPopen in

http://svn.python.org /view/python/trunk/Modules/posixmodule.c?view=markup

Andere Tipps

Ich glaube, Sie einen sehr guten Start, um Ihr Problem gemacht haben, indem die popen2 () -Funktion zu abstrahieren den plattformübergreifende Fragen. Ich erwarte ‚Steckdosen‘ zu kommen und zu schlagen, aber ich bin sicher, dass nach dem Lesen der Frage nicht relevant ist. Sie könnten Buchsen anstelle von Rohren verwenden -. In der popen2 () Funktion ausgeblendet werden würde

Ich bin 99% sicher, dass Sie die erforderliche Funktionalität auf Windows implementieren können, unter Verwendung von Windows-APIs. Was ich nicht tun kann ist, dass Sie die richtigen Funktionen zuverlässig zeigen. Allerdings sollten Sie sich bewusst sein, die Microsoft die meisten der POSIX-ähnlichen API-Aufrufe zur Verfügung hat, aber der Name ist mit dem Präfix ‚_‘. Darüber hinaus gibt es native API-Aufrufe, die die Auswirkungen von fork und exec erreichen.

Ihre Kommentare deuten darauf hin, dass Sie über Probleme mit der Verfügbarkeit von Daten und möglichen Deadlocks sind - vorsichtig sein

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