【问题标题】:How a child process kill other child process and then terminate?子进程如何杀死其他子进程然后终止?
【发布时间】:2020-01-11 13:31:29
【问题描述】:

这是代码,父进程在管道中写入字符串输入,子进程从管道中读取。如果子进程从管道中读取单词“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);
}

【问题讨论】:

    标签: c linux pipe fork kill


    【解决方案1】:

    除了@G 识别的未初始化buf 的问题。 Sliepen,pipe() 需要在 fork() 之前调用,因为在分叉子进程时文件描述符保持打开状态。这也是管道的工作原理。

    您可以尝试更改您的代码 sn-p 以将 pipe() 放在 fork() 之前。

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

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

    这个帖子fork() and pipes() in c 也解释了这一点。

    终止进程的更新

    这个子进程不知道它的兄弟进程是否存在,但是它的父进程知道。如果没有明确要求,您可以让父进程这样做,即“结束”所有子进程。

    顺便说一句,最好发送 SIGTERM 信号,而不是发送信号 SIGUSR1。虽然 SIGUSSR1 可以导致目标进程默认终止(参见signal(7))。

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

    【讨论】:

    • 非常感谢。是的,你是对的,我改变了这个,但它仍然没有终止进程。
    【解决方案2】:

    您正在声明一个指针buf,但没有对其进行初始化。对read()scanf() 的后续调用将失败,因为指针无效。

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

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

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

    注意潜在的缓冲区溢出:如果您声明 char buf[10],请确保您写入的字节数永远不会超过 10 个。另外,检查read()write()scanf()等函数的返回值,确保没有遇到错误,否则缓冲区或输出文件的内容可能与预期不符。

    【讨论】:

    • 非常感谢。我改变了这个,但它确实有效。我认为这与子进程在父进程写入管道之前读取有关。
    猜你喜欢
    • 1970-01-01
    • 2012-09-19
    • 2017-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多