【问题标题】:Killing first child process when second child process close reading end of pipe当第二个子进程关闭读取管道的末端时杀死第一个子进程
【发布时间】:2018-03-13 16:43:49
【问题描述】:

我的 shell 的特定命令行出现问题: base64 /dev/urandom | head -c 1000

如您所见,第一个进程 base64 将永无止境的字符写入管道,head 将读取前 1000 个字符,然后正确退出。

我知道管道的 fd 在每个子进程中都是重复的,并且如果您在父进程中关闭它们,它们将不会在子进程中关闭,从而导致我遇到的问题。在父进程中关闭管道的读取端时,它不会发送终止第一个进程的 SIGPIPE 信号,因为它在子进程中仍然是打开的。

因此,基本上,在一个永无止境的过程中,它会尝试成功写入管道,因为在fork中,管道的读取端永远不会关闭。

那么,当第二个进程完成管道中的读取后,如何才能成功退出第一个进程,换句话说,如何在子进程之间共享 SIGPIPE 信号。

这段代码是我进行管道、分叉和​​等待的部分:

void            exec_process(t_shell *sh, t_job *job, int *iofile)
{
    t_parse *parse;

    parse = init_parse(sh, job->process->cmd);
    if (check_builtins(parse->argv[0]))
    {
        if (iofile[0] != 0)
            job->process->stdio[0] = iofile[0];
        if (iofile[1] != 1)
            job->process->stdio[1] = iofile[1];
        launch_builtin(sh, parse, job);
    }
    else if ((job->process->pid = fork()) == 0)
    {
        if (iofile[0] != 0)
            job->process->stdio[0] = iofile[0];
        if (iofile[1] != 1)
            job->process->stdio[1] = iofile[1];
        launch_bin(parse, job);
    }
    free_parse(&parse);
    if (iofile[0] != 0)
        close(iofile[0]);
    if (iofile[1] != 1)
        close(iofile[1]);
 }

static void     launch_process(t_shell *sh, t_job *job)
{
    t_process   *process;
    int         iofile[2];
    int         pipefd[2];
    int         i;

    process = job->process;
    iofile[0] = 0;
    i = get_num_process(job->process);
    while (job->process)
    {
        if (job->process->next)
        {
            pipe(pipefd);
            iofile[1] = pipefd[1];
        }
        else
            iofile[1] = 1;
        exec_process(sh, job, iofile);
        iofile[0] = pipefd[0];
        job->process = job->process->next;
     }
     job->process = process;
     wait_for_job(sh, job, i);
 }

我有一个父母和两个孩子,他们只链接到父母。

有什么建议吗?谢谢

【问题讨论】:

    标签: c shell pipe fork wait


    【解决方案1】:

    每个进程必须关闭它不使用的管道末端,以便在其他进程终止时读取或写入调用失败。

    【讨论】:

    • 那么,即使它们只是父管道 fds 的副本,我也应该关闭未在每个孩子的 fork 中使用的末端?编辑:我永远不知道我正在使用管道的哪一端,因为它是一个循环,它可能是使用的写入端或读取端。
    • @Zethir。绝对地。如果父级不打算从管道中读取数据(它不应该!),那么您应该尽快关闭该 fd。
    • 是的,如果正在读取写入端并且父母必须关闭读取端
    • 但是我需要为第二个进程保留管道的读取端,以便它可以从管道中读取。如果它关闭了我不能这样做吗?
    猜你喜欢
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 2021-07-24
    • 2012-03-12
    • 2013-09-19
    • 1970-01-01
    相关资源
    最近更新 更多