两个叉子和等待的使用 [英] two forks and the use of wait

查看:23
本文介绍了两个叉子和等待的使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前正在做两个 fork 来管道两个进程,但我认为我的 wait(&status) 做错了,因为在命令之后我的 shell 只是挂起并且没有返回到我的提示.我知道我的管道正在工作,因为如果我取消等待,我可以看到结果.

Currently am doing two forks to pipeline two process, but I think am doing my wait(&status) wrong because after the command my shell just hangs and does not return to my prompt. I know my pipe is working because I can see the result if I remove the wait.

有什么建议吗?

pipe(mypipe);
pid1=fork();
if(pid1==0)
{       
    pid2=fork();
    if(pid2==0)
    {
        close(0);
        dup(mypipe[0]);
        close(mypipe[1]);
        execv(foundnode2->path_dir,arv2);
        exit(0);
    }
    close(1);
    dup(mypipe[1]);
    close(mypipe[0]);
    pid2 = wait(&status2);
    execv(foundnode1->path_dir,arv1);
    exit(0);
}
pid1 = wait(&status2);  

推荐答案

经验法则:如果您使用 dup()dup2() 来映射标准输入或标准输出的管道,您应该 close() 管道本身的两端.你不会那样做;您的等待正在等待程序完成,但程序将无法完成,因为管道打开的过程仍然可以写入管道.此外,创建管道的进程需要关闭管道的两端,因为它本身并不使用管道(子进程正在使用它).另请参阅 C MiniShell — 添加管道.

Rule of Thumb: if you use dup() or dup2() to map one end of a pipe to standard input or standard output, you should close() both ends of the pipe itself. You're not doing that; your waits are waiting for the programs to finish but the programs will not finish because there is still a proess with the pipe open that could write to the pipe. Also, the process which created the pipe needs to close both ends of the pipe since it is not, itself, using the pipe (the child processes are using it). See also C MiniShell — Adding Pipelines.

此外,您不应该在启动第二个孩子之前等待第一个孩子完成(因此 pid2 = wait(&status2); 行是个坏主意).管道的容量相当小;如果要传输的数据总量太大,写子可能会阻塞等待读子读取,但读子还没有开始,因为它在等待写子退出(并且需要很长时间)使这个僵局自行解决).您会看到没有 wait() 调用的输出,因为管道的第二部分执行并处理管道第一部分的数据,但它仍在等待更多数据的到来来自外壳.

Also, you should not be waiting for the first child to finish before launching the second (so the pid2 = wait(&status2); line is a bad idea). Pipes have a fairly small capacity; if the total data to be transferred is too large, the writing child may block waiting for the reading child to read, but the reading child hasn't started yet because it is waiting for the writing child to exit (and it takes a long time for this deadlock to resolve itself). You're seeing the output appear without the wait() calls because the second part of the pipeline executes and processes the data from the first part of the pipeline, but it is still waiting for more data to come from the shell.

考虑到这些提示,您可能会得到:

Taking those tips into account, you might end up with:

pipe(mypipe);
pid1 = fork();
if (pid1 == 0)
{        
    pid2 = fork();
    if (pid2 == 0)
    {
        close(0);
        dup(mypipe[0]);
        close(mypipe[1]);
        close(mypipe[0]);
        execv(foundnode2->path_dir, arv2);
        fprintf(stderr, "Failed to exec %s\n", foundnode2->path_dir);
        exit(1);
    }
    close(1);
    dup(mypipe[1]);
    close(mypipe[0]);
    close(mypipe[1]);
    execv(foundnode1->path_dir, arv1);
    fprintf(stderr, "Failed to exec %s\n", foundnode1->path_dir);
    exit(1);
}
close(mypipe[0]);
close(mypipe[1]);
pid1 = wait(&status1);

注意当命令execv() 失败时向标准错误报告的错误.此外,退出状态 0 应保留为成功;1 是一个方便的错误退出状态,或者您可以使用 中的 EXIT_FAILURE.

Notice the error reporting to standard error when the commands fail to execv(). Also, the exit status of 0 should be reserved for success; 1 is a convenient error exit status, or you can use EXIT_FAILURE from <stdlib.h>.

仍然省略了很多错误检查;fork() 操作可能会失败;pipe() 可能会失败.一个结果是,如果第二个 fork() 失败,您仍然会启动第二个子节点(由 foundnode1->path_dir 标识).

There is a lot of error checking omitted still; the fork() operations could fail; the pipe() might fail. One consequence is that if the second fork() fails, you still launch the second child (identified by foundnode1->path_dir).

并且我注意到,您可以通过将管道创建移到第一个子进程中来节省一些工作(然后父进程不需要——实际上,不能——关闭管道):

And I note that you could save yourself a little work by moving the pipe creation into the first child process (the parent then does not need to — indeed, cannot — close the pipe):

int pid1 = fork();
if (pid1 == 0)
{
    int mypipe[2];      
    pipe(mypipe);
    int pid2 = fork();
    if (pid2 == 0)
    {
        close(0);
        dup(mypipe[0]);
        close(mypipe[1]);
        close(mypipe[0]);
        execv(foundnode2->path_dir, arv2);
        fprintf(stderr, "Failed to exec %s\n", foundnode2->path_dir);
        exit(1);
    }
    close(1);
    dup(mypipe[1]);
    close(mypipe[0]);
    close(mypipe[1]);
    execv(foundnode1->path_dir, arv1);
    fprintf(stderr, "Failed to exec %s\n", foundnode1->path_dir);
    exit(1);
}
pid1 = wait(&status1);

这篇关于两个叉子和等待的使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆