Question

J'ai un projet qui, à mon avis, allait être relativement facile, mais qui s'avère être plus pénible que je l'avais espéré. Premièrement, la plupart du code avec lequel j'interagis est un code hérité sur lequel je n’ai aucun contrôle, je ne peux donc pas faire de grands changements de paradigme.

Voici une explication simplifiée de ce que je dois faire: Disons que j’ai un grand nombre de programmes simples qui lisent à partir de stdin et écrivent sur stdout. (Je ne peux pas les toucher) Fondamentalement, l'entrée dans stdin est une commande du type "Régler la température sur 100". ou quelque chose comme ça. Et la sortie est un événement "La température a été réglée sur 100". ou "La température est tombée en dessous du point de consigne".

Ce que je voudrais faire, c’est écrire une application qui puisse démarrer plusieurs de ces programmes simples, surveiller les événements, puis leur envoyer les commandes nécessaires. Mon plan initial était de faire quelque chose comme Popen, mais il me faut un bouton bidirectionnel pour lire et écrire des pipes. J'ai piraté quelque chose ensemble que j'appelle popen2 où je lui passe la commande à exécuter et deux fichiers * qui sont remplis avec le flux de lecture et d'écriture. Ensuite, tout ce que je dois faire est d’écrire une simple boucle qui lit chacune des sorties standard de chacun des processus, fait la logique dont elle a besoin, puis écrit les commandes dans le bon processus.

Voici un pseudocode

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);
}

Le vrai programme est plus compliqué: il jette un coup d'œil dans le flux pour voir si quelque chose attend, sinon, il ignorera ce processus. De même, s'il n'a pas besoin d'envoyer une commande à un processus donné, il ne le fait pas. . Mais ce code donne l’idée de base.

Maintenant, cela fonctionne très bien sur ma machine UNIX et même très bien sur une machine Windows XP avec cygwin. Cependant, je dois maintenant le faire fonctionner en natif sur Win32.

La partie difficile est que mon popen2 utilise fork () et execl () pour démarrer le processus et attribuer les flux à stdin et stdout des processus enfants. Existe-t-il un moyen propre de le faire sous Windows? En gros, j'aimerais créer un popen2 qui fonctionne sous Windows de la même manière que ma version unix. De cette façon, le seul code spécifique à Windows serait dans cette fonction et je pourrais m'en sortir avec tout le reste fonctionnant de la même manière.

Des idées?

Merci!

Était-ce utile?

La solution

Sous Windows, vous appelez d'abord CreatePipe (similaire à pipe (2)), puis CreateProcess. Le truc ici est que CreateProcess a un paramètre où vous pouvez passer stdin, stdout, stderr du processus nouvellement créé.

Notez que lorsque vous utilisez stdio, vous devez utiliser fdopen pour créer ensuite l’objet fichier, qui attend des numéros de fichier. Dans Microsoft CRT, les numéros de fichier sont différents des descripteurs de fichier du système d'exploitation. Donc, pour renvoyer l’autre extrémité de CreatePipe à l’appelant, vous devez d’abord _open_osfhandle pour obtenir un numéro de fichier CRT, puis fdopen à ce sujet.

Si vous voulez voir du code de travail, consultez _PyPopen dans

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

Autres conseils

Je pense que vous avez très bien commencé votre problème en utilisant la fonction popen2 () pour résumer les problèmes multi-plateformes. Je m'attendais à venir suggérer des «sockets», mais je suis sûr que ce n'est pas pertinent après avoir lu la question. Vous pouvez utiliser des sockets au lieu de pipes - cela serait caché dans la fonction popen2 ().

Je suis sûr à 99% que vous pouvez implémenter la fonctionnalité requise sous Windows, à l'aide des API Windows. Ce que je ne peux pas faire, c'est vous indiquer les bonnes fonctions de manière fiable. Cependant, vous devez savoir que Microsoft dispose de la plupart des appels d'API de type POSIX, mais le nom est préfixé par '_'. Il existe également des appels d'API natifs produisant les effets de fork et de exec .

Vos commentaires suggèrent que vous êtes au courant des problèmes de disponibilité des données et d'éventuelles impasses - soyez prudent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top