Pregunta

Tengo un proyecto que pensé que iba a ser relativamente fácil, pero está resultando ser un dolor más de lo que esperaba. Primero, la mayoría del código con el que estoy interactuando es un código heredado sobre el que no tengo control, por lo que no puedo hacer grandes cambios de paradigma.

Aquí hay una explicación simplificada de lo que necesito hacer: Digamos que tengo una gran cantidad de programas simples que leen desde stdin y escriben a stdout. (Estos no puedo tocar). Básicamente, la entrada a stdin es un comando como " Ajustar temperatura a 100 " o algo así. Y la salida es un evento "La temperatura se ha establecido en 100" o " la temperatura ha caído por debajo del punto de ajuste " ;.

Lo que me gustaría hacer es escribir una aplicación que pueda iniciar un montón de estos simples programas, ver eventos y luego enviarles comandos según sea necesario. Mi plan inicial era algo como popen, pero necesito un popen bidrectional para leer y escribir tubos. Hacké algo junto a lo que llamo popen2 donde le paso el comando para ejecutar y dos ARCHIVO * que se rellenan con la secuencia de lectura y escritura. Luego, todo lo que debo hacer es escribir un bucle simple que lea cada uno de los stdouts de cada uno de los procesos, haga la lógica que necesita y luego vuelva a escribir los comandos en el proceso adecuado.

Aquí hay un pseudocódigo

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

El programa real es más complicado donde se ve en la secuencia para ver si hay algo esperando, si no, omitirá ese proceso, de la misma manera si no necesita enviar un comando a un determinado proceso, no lo hace. . Pero este código da la idea básica.

Ahora esto funciona muy bien en mi caja de UNIX e incluso bastante bien en una caja de Windows XP con cygwin. Sin embargo, ahora necesito que funcione en Win32 de forma nativa.

La parte difícil es que mi popen2 usa fork () y execl () para iniciar el proceso y asignar las secuencias a stdin y stdout de los procesos secundarios. ¿Hay una manera limpia de hacerlo en Windows? Básicamente, me gustaría crear un popen2 que funcione en Windows de la misma manera que mi versión de Unix. De esta manera, el único código específico de Windows estaría en esa función y podría salirme con todo lo demás funcionando de la misma manera.

¿Alguna idea?

¡Gracias!

¿Fue útil?

Solución

En Windows, primero invoca CreatePipe (similar a pipe (2)), luego CreateProcess. El truco aquí es que CreateProcess tiene un parámetro donde puedes pasar stdin, stdout, stderr del proceso recién creado.

Observe que cuando usa stdio, necesita hacer fdopen para crear el objeto de archivo posteriormente, que espera los números de archivo. En el CRT de Microsoft, los números de archivo son diferentes de los manejadores de archivos del sistema operativo. Entonces, para devolver el otro extremo de CreatePipe a la persona que llama, primero necesita _open_osfhandle para obtener un número de archivo CRT, y luego fdopen en eso.

Si desea ver el código de trabajo, consulte _PyPopen in

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

Otros consejos

Creo que has hecho un muy buen comienzo para tu problema usando la función popen2 () para abstraer los problemas multiplataforma. Esperaba venir y sugerir 'sockets', pero estoy seguro de que eso no es relevante después de leer la pregunta. Podría usar sockets en lugar de tuberías, ya que estaría oculto en la función popen2 ().

Estoy 99% seguro de que puede implementar la funcionalidad requerida en Windows, utilizando las API de Windows. Lo que no puedo hacer es indicarle las funciones correctas de manera confiable. Sin embargo, debe tener en cuenta que Microsoft tiene la mayoría de las llamadas de API similares a POSIX disponibles, pero el nombre tiene el prefijo '_'. También hay llamadas de API nativas que logran los efectos de fork y exec .

Sus comentarios sugieren que está al tanto de los problemas con la disponibilidad de los datos y los posibles puntos muertos. Tenga cuidado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top