一个一个杀死child个进程
Killing child process one by one
首先,我使用 for 循环创建多个 child 进程。然后,我将所有 child 进程置于睡眠状态(通过添加无限睡眠块)。
void kill_child(int sig);
int main(void){
signal(SIGHUP, kill_child);
for(int i = 0; i < max_child; i++){
pid_t id = fork();
if(id == 0){
printf("Hi, i am a child\n");
while(1){sleep(1);}
}
if(id == 1){
printf("Hi, i am a parent\n");
}
}
}
void kill_child(int sig){
if(sig==SIGHUP){
//do stuff to kill single child
}
}
接下来我打算做什么,从终端发送 kill -HUP parent 来一个一个地杀死 child 进程。最后,如果没有child进程终止程序。
我就想知道在这种情况下有没有什么办法可以一次性杀死一个child
我认为你可以使用一个全局范围的数组来保护 children 的 pid,然后将它用于函数 kill_child 调用:int kill(pid_t pid, int sig ).
在 kill_child 里面,我想你可以发送 SIGKILL 给 children 或者如果你想发送 SIGTERM 的话可以用 signal 函数重新定义行为。
这可能是一个解决方案。
不管怎样,我注意到您的代码中有一些可以改进的地方(以我的拙见):
- 我不确定您的程序是否会打印“嗨,我是 parent\n”,因为您无法确定至少有一个 child 具有 pid = 1(除非您由于其他原因确定)
- while 循环会产生大量开销,因为每一秒你都会重新激活一个进程,而这个进程迟早会占用 CPU 仅用于调用 sleep 等待一秒钟
希望对你有所帮助!
来自您的代码:
int main(void){
signal(SIGHUP, kill_child);
for(int i = 0; i < max_child; i++){
pid_t id = fork();
if(id == 0){
printf("Hi, i am a child\n");
while(1){sleep(1);}
}
if(id == 1){
当 fork()
returns 到 parent 时,你从哪里得到 id == 1
?那绝不是真的。为此,您必须 fork()
init
进程,而对于用户进程而言,这绝不是正确的。内核 returns 将 child 进程的 pid(这就是为什么你称它为 id
)到 parent,所以你永远不会进入下面的代码段。
printf("Hi, i am a parent\n");
}
}
}
您需要安排一个数组(如另一个答案中所述)并保存您分叉的所有进程的所有 pids。而不是上面的printf()
,只需执行以下操作。
kc.c
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define MAX_CHILDREN 10
pid_t chld_pids[MAX_CHILDREN];
size_t chld_pids_sz = 0;
void kill_children(int sig, int delay);
void signal_handler(int sig);
int main()
{
while (chld_pids_sz < MAX_CHILDREN) {
pid_t chld_id = fork();
if (chld_id < 0) { /* error in fork() */
fprintf(stderr,
"Error in fork: %s (errno == %d)\n",
strerror(errno), errno);
kill_children(SIGHUP, 0); /* kill all children with
* no delay */
break; /* stop processing */
} else if (chld_id == 0) { /* child */
/* avoid signal SIGHUP so no child is killed when the
* process group leader is killed. This is sent
* automatically by the kernel to end a job. */
signal(SIGHUP, SIG_IGN);
for(;;) {
/* print our pid on stdout each second to
* indicate we are alive. */
printf("[%d]", getpid());
fflush(stdout); /* force buffer flush */
sleep(1);
}
/* NOTREACHED */
} else { /* parent */
printf("Parent: started child %d\n", chld_id);
chld_pids[chld_pids_sz++] = chld_id;
}
}
signal(SIGHUP, signal_handler);
/* now we wait for all children to finish, no need to know
* the pids, as we are waiting until wait(2) returns an error
* (no children to wait for) */
int chld_id, status;
while ((chld_id = wait(&status)) >= 0) {
if (WIFEXITED(status)) {
printf("Child %d exited with status %d\n",
chld_id, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("Child %d was killed with signal %d\n",
chld_id, WTERMSIG(status));
if (WCOREDUMP(status)) {
printf("Child %d dumped a core file\n",
chld_id);
}
}
}
} /* main */
void kill_children(int sig, int delay)
{
printf("kill_children: Using delay %d\n", delay);
for (int i = 0; i < chld_pids_sz; ++i) {
if (delay > 0) { /* only sleep if delay > 0 */
sleep(delay);
}
printf("Killing pid=%d\n", chld_pids[i]);
int res = kill(chld_pids[i], sig);
if (res < 0) {
printf("Error killing pid %d: %s (errno = %d)\n",
chld_pids[i], strerror(errno), errno);
}
}
}
void signal_handler(int unused)
{
kill_children(SIGINT, 3);
}
此代码的副本已发布here如果您想下载它并遵循它的版本控制。
首先,我使用 for 循环创建多个 child 进程。然后,我将所有 child 进程置于睡眠状态(通过添加无限睡眠块)。
void kill_child(int sig);
int main(void){
signal(SIGHUP, kill_child);
for(int i = 0; i < max_child; i++){
pid_t id = fork();
if(id == 0){
printf("Hi, i am a child\n");
while(1){sleep(1);}
}
if(id == 1){
printf("Hi, i am a parent\n");
}
}
}
void kill_child(int sig){
if(sig==SIGHUP){
//do stuff to kill single child
}
}
接下来我打算做什么,从终端发送 kill -HUP parent 来一个一个地杀死 child 进程。最后,如果没有child进程终止程序。
我就想知道在这种情况下有没有什么办法可以一次性杀死一个child
我认为你可以使用一个全局范围的数组来保护 children 的 pid,然后将它用于函数 kill_child 调用:int kill(pid_t pid, int sig ). 在 kill_child 里面,我想你可以发送 SIGKILL 给 children 或者如果你想发送 SIGTERM 的话可以用 signal 函数重新定义行为。 这可能是一个解决方案。 不管怎样,我注意到您的代码中有一些可以改进的地方(以我的拙见):
- 我不确定您的程序是否会打印“嗨,我是 parent\n”,因为您无法确定至少有一个 child 具有 pid = 1(除非您由于其他原因确定)
- while 循环会产生大量开销,因为每一秒你都会重新激活一个进程,而这个进程迟早会占用 CPU 仅用于调用 sleep 等待一秒钟
希望对你有所帮助!
来自您的代码:
int main(void){
signal(SIGHUP, kill_child);
for(int i = 0; i < max_child; i++){
pid_t id = fork();
if(id == 0){
printf("Hi, i am a child\n");
while(1){sleep(1);}
}
if(id == 1){
当 fork()
returns 到 parent 时,你从哪里得到 id == 1
?那绝不是真的。为此,您必须 fork()
init
进程,而对于用户进程而言,这绝不是正确的。内核 returns 将 child 进程的 pid(这就是为什么你称它为 id
)到 parent,所以你永远不会进入下面的代码段。
printf("Hi, i am a parent\n");
}
}
}
您需要安排一个数组(如另一个答案中所述)并保存您分叉的所有进程的所有 pids。而不是上面的printf()
,只需执行以下操作。
kc.c
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#define MAX_CHILDREN 10
pid_t chld_pids[MAX_CHILDREN];
size_t chld_pids_sz = 0;
void kill_children(int sig, int delay);
void signal_handler(int sig);
int main()
{
while (chld_pids_sz < MAX_CHILDREN) {
pid_t chld_id = fork();
if (chld_id < 0) { /* error in fork() */
fprintf(stderr,
"Error in fork: %s (errno == %d)\n",
strerror(errno), errno);
kill_children(SIGHUP, 0); /* kill all children with
* no delay */
break; /* stop processing */
} else if (chld_id == 0) { /* child */
/* avoid signal SIGHUP so no child is killed when the
* process group leader is killed. This is sent
* automatically by the kernel to end a job. */
signal(SIGHUP, SIG_IGN);
for(;;) {
/* print our pid on stdout each second to
* indicate we are alive. */
printf("[%d]", getpid());
fflush(stdout); /* force buffer flush */
sleep(1);
}
/* NOTREACHED */
} else { /* parent */
printf("Parent: started child %d\n", chld_id);
chld_pids[chld_pids_sz++] = chld_id;
}
}
signal(SIGHUP, signal_handler);
/* now we wait for all children to finish, no need to know
* the pids, as we are waiting until wait(2) returns an error
* (no children to wait for) */
int chld_id, status;
while ((chld_id = wait(&status)) >= 0) {
if (WIFEXITED(status)) {
printf("Child %d exited with status %d\n",
chld_id, WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("Child %d was killed with signal %d\n",
chld_id, WTERMSIG(status));
if (WCOREDUMP(status)) {
printf("Child %d dumped a core file\n",
chld_id);
}
}
}
} /* main */
void kill_children(int sig, int delay)
{
printf("kill_children: Using delay %d\n", delay);
for (int i = 0; i < chld_pids_sz; ++i) {
if (delay > 0) { /* only sleep if delay > 0 */
sleep(delay);
}
printf("Killing pid=%d\n", chld_pids[i]);
int res = kill(chld_pids[i], sig);
if (res < 0) {
printf("Error killing pid %d: %s (errno = %d)\n",
chld_pids[i], strerror(errno), errno);
}
}
}
void signal_handler(int unused)
{
kill_children(SIGINT, 3);
}
此代码的副本已发布here如果您想下载它并遵循它的版本控制。