Einen Kindprozess beenden in C
-
Verwenden Sie das Signal
SIGKILL
, um einen Kindprozess in C zu beenden -
Verwenden Sie das Signal
SIGTERM
, um einen untergeordneten Prozess in C zu beenden
Dieser Artikel demonstriert mehrere Methoden, wie man einen Kindprozess in C beenden kann.
Verwenden Sie das Signal SIGKILL
, um einen Kindprozess in C zu beenden
Es gibt mehrere Signale, die einen Prozess bei seiner Übermittlung beenden sollen. Das Senden des Signals SIGKILL
ist jedoch die leistungsstärkste und sicherste Methode, um dies zu tun. Im Allgemeinen kann ein Programm spezielle Funktionen registrieren, die als Signalhandler bezeichnet werden und automatisch aufgerufen werden, sobald das entsprechende Signal an das Programm geliefert wird. Der Benutzer implementiert den Handler-Funktionscode, der normalerweise einige Bereinigungsarbeiten für das Programm ausführt. Abgesehen von Funktionshandlern kann es Standardaktionen für gelieferte Signale wie Blockieren und Ignorieren geben. Das Signal SIGKILL
kann jedoch von der angegebenen Funktion nicht ignoriert, blockiert oder verarbeitet werden. Daher sollte diese Methode der letzte Ausweg sein, wenn versucht wird, einen Prozess zu beenden.
Das Signal SIGKILL
kann mit einem Systemaufruf kill
gesendet werden. Beachten Sie jedoch, dass der im folgenden Codebeispiel registrierte Handler SIGTERM
den gelieferten SIGKILL
nicht abfangen kann und den angegebenen untergeordneten Prozess sofort beendet.
Das folgende Programm erzeugt einen untergeordneten Prozess und registriert den Handler SIGTERM
darin. Dann führt der untergeordnete Prozess eine Endlosschleife aus, es sei denn, das Signal wird geliefert, wodurch die Ausdrucksvariable while
umgedreht wird. Folglich ruft das vom Elternteil übermittelte Signal SIGKILL
den Handler nicht auf und beendet den untergeordneten Prozess sofort.
#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);
}
Verwenden Sie das Signal SIGTERM
, um einen untergeordneten Prozess in C zu beenden
Alternativ kann ein untergeordneter Prozess mit dem Signal SIGTERM
beendet werden, das vom Programm verarbeitet werden kann. Das nächste Codebeispiel wiederholt die vorherige Programmimplementierung, außer dass das Signal SIGKILL
durch SIGTERM
ersetzt wird. Mit der Funktion sigfillset
wird verhindert, dass andere Signale die Ausführung der registrierten Handlerfunktion unterbrechen. Der Handlercode ändert die globale Variable vom Typ sig_atomic_t
, die die Schleife while
im untergeordneten Prozess stoppt und den Wert der Variablen count
druckt. Beachten Sie jedoch, dass es bei der Registrierung der Handler immer besser ist, den Aufruf sigaction
über der Funktion signal
zu verwenden, da letzterer im POSIX-Standard nicht im Detail festgelegt ist.
#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