子进程如何杀死其他子进程然后终止?

时间:2020-01-11 13:31:29

标签: c linux pipe fork kill

这是代码,其中父进程在管道中写入字符串输入,子进程从管道中读取字符串。如果子进程从管道中读取单词“ end”,那么我想终止所有进程,然后终止自身,如果读取了“ finish”这个单词,我想向父亲发出信号,要求杀死所有进程,然后退出。我运行代码,但遇到了段错误。为什么错了?

#define _POSIX_SOURCE
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
void measure_time(int sig)
{
    printf("child [%d] received signal %d\n", getpid(), sig);
}
int main(int argc, char *argv[])
{
    int n_task = 4;
    pid_t pid;
    pid_t pid_array[n_task];
    int fd[2];
    for (int i = 0; i < n_task; i++)
    {
        pid = fork();
        if (pipe(fd) == -1)
        {
            perror(" pipe ");
            exit(1);
        }
        if (pid < 0)
        {
            perror("fork");
            exit(1);
        }
        if (pid == 0) //child
        {
            char *buf;
            close(fd[1]);
            read(fd[0], buf, 10);
            printf("I read: %s", buf);
            if (strcmp(buf, "end") == 0)
            {
                for (int i = 0; i < n_task; i++)
                    kill(pid_array[i], SIGUSR1);
            }else if(strcmp(buf,"finish") == 0){
                /*Here i want father to kill all children and then exit.*/
            }
            exit(0);
        }
        close(fd[0]);
        char *buf;
        printf("Give the input string: \n");
        scanf("%s", buf);
        write(fd[1], buf, strlen(buf));
        close(fd[1]);
        pid_array[i] = pid;
    }
    sleep(1);
    for (int i = 0; i < n_task; i++)
        wait(NULL);
    return (0);
}

2 个答案:

答案 0 :(得分:1)

除了由@G标识的未初始化buf的问题。 Sliepen,pipe()必须在fork()之前调用,因为在派生子进程时文件描述符保持打开状态。这也是管道的工作方式。

您可以尝试更改代码段,将pipe()放在fork()之前。

...
        if (pipe(fd) == -1)
        {
            perror(" pipe ");
            exit(1);
        }
        pid = fork();
        if (pid < 0)
        {
            perror("fork");
            exit(1);
        }
...

请阅读pipe(2)的手册页,其中提供了示例。

SO的帖子fork() and pipes() in c也对此进行了解释。

更新终止过程

此子进程不知道其兄弟姐妹的存在,但其父进程知道。如果没有明确要求,则可以让父级这样做,即“结束”所有子进程。

顺便说一句,最好是发送SIGTERM信号,而不是发送信号SIGUSR1。尽管SIGUSSR1可能导致目标进程在默认情况下被终止(请参见signal(7))。

要“完成”,即杀死(或终止)所有子进程以及父进程,可以简单地杀死父进程。它的所有后代也被杀死。或者,您可以将信号发送到同一过程组。参见kill(2)

答案 1 :(得分:0)

您正在声明指针buf,但未初始化它。由于指针无效,随后对read()scanf()的调用将失败。

您需要确保buf已初始化并指向有效内存。修改代码的一种简单方法是:

char buf[10];
read(fd[0], buf, 10);

如果使用-Wall启用编译器警告,则编译器将警告您有关初始化变量。

请注意潜在的缓冲区溢出:如果声明char buf[10],请确保不要将十个以上的字节写入其中。另外,检查诸如read()write()scanf()之类的函数的返回值,以确保没有遇到错误,否则缓冲区或输出文件的内容可能与预期不符。