一个一个杀死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 函数重新定义行为。 这可能是一个解决方案。 不管怎样,我注意到您的代码中有一些可以改进的地方(以我的拙见):

  1. 我不确定您的程序是否会打印“嗨,我是 parent\n”,因为您无法确定至少有一个 child 具有 pid = 1(除非您由于其他原因确定)
  2. 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如果您想下载它并遵循它的版本控制。