2011-04-12 26 views
15

Estoy tratando de engendrar un proceso que ejecuta un comando del sistema, mientras mi propio programa continúa y dos procesos se ejecutarán en paralelo. Estoy trabajando en Linux.usando exec para ejecutar un comando del sistema en un nuevo proceso

Miré en línea y parece que debería usar la familia exec(). Pero no funciona tan bien como esperaba. Por ejemplo, en el siguiente código, solo veo impreso "antes", pero no "hecho".

Tengo curiosidad si estoy emitiendo algo?

#include <unistd.h> 
#include <iostream> 

using namespace std; 

main() 
{ 
    cout << "before" << endl; 
    execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0); 
    cout << "done" << endl; 
} 

[ACTUALIZACIÓN]

Gracias por sus comentarios chicos. Ahora mi programa se ve así. Todo funciona bien, excepto al final, tengo que presionar enter para terminar el programa. No estoy seguro de por qué tengo que presionar la última entrada?

#include <unistd.h> 
#include <iostream> 

using namespace std; 

main() 
{ 
    cout << "before" << endl; 
    int pid = fork(); 
    cout << pid << endl; 
    if (pid==0) { 
     execl("/bin/ls", "ls", "-r", "-t", "-l", (char *) 0); 
    } 
    cout << "done" << endl; 
} 
+0

su principal debería ser 'int main' y al final se debe añadir un' return 0; ' la forma en que lo tienes, probablemente, su compilador llenará al final, y agregará "presione cualquier botón para continuar" al final – akaltar

Respuesta

14

Te estás perdiendo una llamada al fork. Todo exec hace es reemplace la imagen de proceso actual con la del nuevo programa. Use fork para generar una copia de su proceso actual. Su valor de retorno le dirá si es el hijo o el padre original el que se está ejecutando. Si es el niño, llame al exec.


vez que haya hecho ese cambio, sólo aparece que hay que pulsar Enter para los programas para terminar. Lo que está sucediendo realmente es esto: el proceso principal bifurca y ejecuta el proceso hijo. Ambos procesos se ejecutan, y ambos procesos imprimen a stdout al mismo tiempo. Su salida está distorsionada. El proceso principal tiene menos que hacer que el hijo, por lo que termina primero. Cuando termina, su caparazón, que estaba esperando, se despierta e imprime el aviso habitual. Mientras tanto, el proceso hijo aún se está ejecutando. Imprime más entradas de archivo. Finalmente, termina. El shell no está prestando atención al proceso hijo (su nieto), por lo que el shell no tiene ninguna razón para volver a imprimir el mensaje. Mire con más cuidado el resultado que obtiene, y debería poder encontrar el indicador de comando habitual oculto en el resultado de ls anterior.

El cursor aparece esperando que presione una tecla. Cuando lo haces, el shell imprime un mensaje, y todo se ve normal. Pero en lo que respecta al caparazón, todo ya era normal. Podrías haber escrito otro comando antes.Hubiera parecido un poco extraño, pero el intérprete de comandos lo habría ejecutado normalmente porque solo recibe datos del teclado, no del proceso secundario, imprimiendo caracteres adicionales en la pantalla.

Si utiliza un programa como top en una ventana de consola separada, puede ver y confirmar que ambos programas ya se han ejecutado antes de presionar Entrar.

7

El Exec familia de funciones reemplaza el proceso actual con el nuevo ejecutable.

Para hacer lo que necesita, use una de las funciones fork() y haga que el hijo procese exec la nueva imagen.

[respuesta a actualizar]

Se está haciendo exactamente lo que se dijo: Usted no tiene que pulsar "enter" para finalizar el programa: Ya ha salido. La cáscara ya ha dado un símbolo:

[[email protected] ~]$ ./z 
before 
22397 
done 
[[email protected] ~]$ 0    << here is the prompt (as well as the pid) 
total 5102364 
drwxr-xr-x. 2 wally wally  4096 2011-01-31 16:22 Templates 
... 

La salida de ls toma un tiempo por lo que entierra el símbolo. Si desea que la salida aparezca en un orden más lógico, agregue sleep(1) (o tal vez más) antes del "hecho".

+1

Debe agregar un 'wait' para el niño, en lugar de' sleep' realmente – Hasturkun

2

Te falta la parte donde execl() sustituye a su programa actual en la memoria con /bin/ls

Yo sugeriría mirar popen() que desembolsar y exec un nuevo proceso, y luego dejar de leer o escribir en él a través de un tubo. (O si usted necesita leer y escribir, fork() mismo, entonces exec())

Cuestiones relacionadas