Mata a un niño Proceso en C
-
Utilice la señal
SIGKILL
para finalizar un proceso secundario en C -
Utilice la señal
SIGTERM
para finalizar un proceso secundario en C
Este artículo demostrará varios métodos sobre cómo eliminar un proceso hijo en C.
Utilice la señal SIGKILL
para finalizar un proceso secundario en C
Hay múltiples señales diseñadas para terminar un proceso en el momento de su entrega, pero enviar la señal SIGKILL
es el método más poderoso y seguro para hacerlo. Generalmente, un programa puede registrar funciones especiales llamadas manejadores de señales que se invocan automáticamente una vez que se entrega la señal correspondiente al programa. El usuario implementa el código de la función del controlador que generalmente realiza algún trabajo de limpieza para el programa. Además de los controladores de funciones, puede haber acciones predeterminadas en las señales entregadas, como bloquear e ignorar. Aunque, la señal SIGKILL
no puede ser ignorada, bloqueada o manejada por la función dada. Por tanto, este método debería ser el último recurso al intentar finalizar un proceso.
La señal SIGKILL
se puede enviar con una llamada al sistema kill
. Sin embargo, tenga en cuenta que el controlador SIGTERM
registrado en el siguiente ejemplo de código no puede capturar el SIGKILL
entregado, e inmediatamente mata el proceso hijo dado.
El siguiente programa genera un proceso hijo y registra el controlador SIGTERM
en él. Luego, el proceso hijo ejecuta un bucle infinito a menos que se entregue la señal, lo que invierte la variable de expresión while
. En consecuencia, la señal SIGKILL
entregada por el padre no invoca al controlador y finaliza el proceso hijo al instante.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
volatile sig_atomic_t shutdown_flag = 1;
void cleanupRoutine(int signal_number) { shutdown_flag = 0; }
int main(void) {
int wstatus;
pid_t c_pid = fork();
if (c_pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (c_pid == 0) {
printf("printed from child process - %d\n", getpid());
int count = 0;
struct sigaction sigterm_action;
memset(&sigterm_action, 0, sizeof(sigterm_action));
sigterm_action.sa_handler = &cleanupRoutine;
sigterm_action.sa_flags = 0;
// Mask other signals from interrupting SIGTERM handler
if (sigfillset(&sigterm_action.sa_mask) != 0) {
perror("sigfillset");
exit(EXIT_FAILURE);
}
// Register SIGTERM handler
if (sigaction(SIGTERM, &sigterm_action, NULL) != 0) {
perror("sigaction SIGTERM");
exit(EXIT_FAILURE);
}
while (shutdown_flag) {
count += 1;
}
printf("count = %d\n", count);
exit(EXIT_SUCCESS);
} else {
printf("printed from parent process - %d\n", getpid());
int ret;
sleep(5);
ret = kill(c_pid, SIGKILL);
if (ret == -1) {
perror("kill");
exit(EXIT_FAILURE);
}
if (waitpid(c_pid, &wstatus, WUNTRACED | WCONTINUED) == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
}
exit(EXIT_SUCCESS);
}
Utilice la señal SIGTERM
para finalizar un proceso secundario en C
Alternativamente, un proceso hijo se puede terminar usando la señal SIGTERM
, que puede ser manejada por el programa. El siguiente ejemplo de código repite la implementación del programa anterior, excepto que sustituye la señal SIGKILL
por SIGTERM
. La función sigfillset
se utiliza para evitar que otras señales interrumpan la ejecución de la función del controlador registrado. El código del controlador modifica la variable de tipo global sig_atomic_t
que detiene el bucle while
en el proceso hijo e imprime el valor de la variable count
. Sin embargo, tenga en cuenta que siempre es mejor utilizar la llamada sigaction
por encima de la función señal
al registrar los controladores, ya que esta última no está especificada en detalle por el estándar POSIX.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
volatile sig_atomic_t shutdown_flag = 1;
void cleanupRoutine(int signal_number) { shutdown_flag = 0; }
int main(void) {
int wstatus;
pid_t c_pid = fork();
if (c_pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (c_pid == 0) {
printf("printed from child process - %d\n", getpid());
int count = 0;
struct sigaction sigterm_action;
memset(&sigterm_action, 0, sizeof(sigterm_action));
sigterm_action.sa_handler = &cleanupRoutine;
sigterm_action.sa_flags = 0;
// Mask other signals from interrupting SIGTERM handler
if (sigfillset(&sigterm_action.sa_mask) != 0) {
perror("sigfillset");
exit(EXIT_FAILURE);
}
// Register SIGTERM handler
if (sigaction(SIGTERM, &sigterm_action, NULL) != 0) {
perror("sigaction SIGTERM");
exit(EXIT_FAILURE);
}
while (shutdown_flag) {
count += 1;
}
printf("count = %d\n", count);
exit(EXIT_SUCCESS);
} else {
printf("printed from parent process - %d\n", getpid());
int ret;
sleep(5);
ret = kill(c_pid, SIGTERM);
if (ret == -1) {
perror("kill");
exit(EXIT_FAILURE);
}
if (waitpid(c_pid, &wstatus, WUNTRACED | WCONTINUED) == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
}
exit(EXIT_SUCCESS);
}
Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.
LinkedIn Facebook