ver saber procesos proceso los corriendo como comando c multithreading kill popen

saber - matar a un proceso iniciado con popen



saber el pid de un proceso windows (8)

Después de abrir una tubería para un proceso con popen , ¿hay alguna manera de matar el proceso que se inició? (Usar pclose no es lo que quiero porque esperará a que el proceso termine, pero tengo que matarlo).


En realidad, si el proceso está haciendo I / O (que debería ser, de lo contrario, ¿ popen qué popen vez de system (3)?), Entonces, pclose debería pclose con un SIGPIPE la próxima vez que intente leer o escribir, y debería caerse muy bien :-)



La forma obvia es system ("pkill process_name");

Claramente, esto es problemático si tiene más de una instancia del proceso en ejecución.


No use popen () y escriba su propio contenedor que haga lo que le gustaría.

Es bastante sencillo teclear (), y luego reemplazar stdin & stdout usando dup2 (), y luego llamar a exec () en su hijo.

De esta forma, su padre tendrá el PID infantil exacto, y puede usar kill () en eso.

Búsqueda en Google de "implementación de popen2 ()" para ver un ejemplo de código sobre cómo implementar lo que está haciendo popen (). Son solo una docena de líneas largas. Tomado de dzone.com podemos ver un ejemplo que se ve así:

#define READ 0 #define WRITE 1 pid_t popen2(const char *command, int *infp, int *outfp) { int p_stdin[2], p_stdout[2]; pid_t pid; if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) return -1; pid = fork(); if (pid < 0) return pid; else if (pid == 0) { close(p_stdin[WRITE]); dup2(p_stdin[READ], READ); close(p_stdout[READ]); dup2(p_stdout[WRITE], WRITE); execl("/bin/sh", "sh", "-c", command, NULL); perror("execl"); exit(1); } if (infp == NULL) close(p_stdin[WRITE]); else *infp = p_stdin[WRITE]; if (outfp == NULL) close(p_stdout[READ]); else *outfp = p_stdout[READ]; return pid; }

NB: Parece que popen2 () es lo que quieres, pero mi distribución no parece venir con este método.


popen en realidad no inicia un hilo, sino que más bien crea un proceso. Cuando miro la definición, no parece que haya una manera fácil de obtener el PID de ese proceso y matarlo. Puede haber formas difíciles como examinar el árbol de procesos, pero supongo que sería mejor utilizar las funciones de pipe, fork y exec para imitar el comportamiento de popen. Luego puede usar el PID que obtiene de fork () para matar el proceso secundario.


Aquí hay una versión mejorada de popen2 (el crédito se debe a Sergey L.). La versión publicada por slacy no devuelve el PID del proceso creado en popen2, sino el PID asignado a sh .

pid_t popen2(const char **command, int *infp, int *outfp) { int p_stdin[2], p_stdout[2]; pid_t pid; if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) return -1; pid = fork(); if (pid < 0) return pid; else if (pid == 0) { close(p_stdin[WRITE]); dup2(p_stdin[READ], READ); close(p_stdout[READ]); dup2(p_stdout[WRITE], WRITE); execvp(*command, command); perror("execvp"); exit(1); } if (infp == NULL) close(p_stdin[WRITE]); else *infp = p_stdin[WRITE]; if (outfp == NULL) close(p_stdout[READ]); else *outfp = p_stdout[READ]; return pid; }

La nueva versión se llamará con

char *command[] = {"program", "arg1", "arg2", ..., NULL};


Tengo idea de seguir de @slacy que crea la función popen2.
Pero se encontró un problema cuando el proceso hijo se muere, el proceso principal que todavía lee el archivo descriptor outfp no regresa de la función.

Eso podría arreglarse mediante la adición de cerrar el conducto de unuse en el proceso principal.

close(p_stdin[READ]); close(p_stdout[WRITE]);

Podemos obtener el pid correcto de un nuevo proceso usando bash como shell.

execl("/bin/bash", "bash", "-c", command, NULL);

Cuando muere el proceso hijo, la persona que llama de la función popen2 debe recopilar el estado del proceso hijo llamando a pclose2 . si no recopilamos ese estado, el proceso hijo podría ser un proceso zombie cuando finalice.

Este es el código completo que se probó y funciona como se esperaba.

#define READ 0 #define WRITE 1 pid_t popen2(const char *command, int *infp, int *outfp) { int p_stdin[2], p_stdout[2]; pid_t pid; if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) return -1; pid = fork(); if (pid < 0) return pid; else if (pid == 0) { dup2(p_stdin[READ], STDIN_FILENO); dup2(p_stdout[WRITE], STDOUT_FILENO); //close unuse descriptors on child process. close(p_stdin[READ]); close(p_stdin[WRITE]); close(p_stdout[READ]); close(p_stdout[WRITE]); //can change to any exec* function family. execl("/bin/bash", "bash", "-c", command, NULL); perror("execl"); exit(1); } // close unused descriptors on parent process. close(p_stdin[READ]); close(p_stdout[WRITE]); if (infp == NULL) close(p_stdin[WRITE]); else *infp = p_stdin[WRITE]; if (outfp == NULL) close(p_stdout[READ]); else *outfp = p_stdout[READ]; return pid; } int pclose2(pid_t pid) { int internal_stat; waitpid(pid, &internal_stat, 0); return WEXITSTATUS(internal_stat); }


Simplemente puse el guión (bash), en la primera línea:

echo PID $$

luego leo el pid y lo uso para hacer a: kill (pid, 9)