【问题标题】:Implementation of multiple pipelines and command executions in C [closed]在 C 中实现多个管道和命令执行 [关闭]
【发布时间】:2023-04-10 12:13:01
【问题描述】:

我有一个作业要求我创建一个 shell,它执行由管道分隔的多个命令。这是我的代码 sn-p 用于派生子和执行命令:

    for (int i = 0; i < commands; i++) {

        place = commandStarts[i];

        if((pid = fork()) < 0) exit(1);
        else if (pid == 0) {
            if(i < pipe_counter && dup2(fds[j + 1], 1) < 0) exit(1);// If this is not the last remaining command

            if(j != 0 && dup2(fds[j-2], 0) < 0) exit(1);        // If this is not the first command

            for(int c = 0; c < 2*pipe_counter; c++) close(fds[c]);

            if(execvp(argv[place], argv+place)) exit(0);        // Execute and if it returns anything, exit!
        }
        j+=2;
    }

    for(int i = 0; i < 2 * pipe_counter; i++) close(fds[i]);

    while ((wait(&status)) != pid);                     // The only program that gets to this point is the 
                                        //     parent process, which should wait for completion

尽管它在简单的例子中似乎工作得很好,在一些更复杂的例子中,分级系统给了我这个提示:在显示提示之前,你应该等待管道链中的所有进程终止,不只是最后一个!

你能告诉我错在哪里吗?

【问题讨论】:

  • 代码在哪里等待每个过程完成?
  • 如你在sn-p的最后看到的,我在一个while循环中等待所有进程完成!
  • 你呢?它是如何工作的?... 没错。我不认为它像你想象的那样有效。
  • 好吧,对于简单的(和小例子。比如:ls | wc | wc)它工作得很好,你的意思是你认为它不像我想的那样工作?能举个例子吗?
  • 你可以看到我的朋友约书亚,答案不在问题中。下次不要只是编译和运行代码,而是在标记任何东西之前先尝试理解问题!

标签: c linux unix pipe


【解决方案1】:

好吧,我的错误是我只等待最后一个分叉的孩子终止。

这是等待每个子节点终止的正确代码 sn-p:

    for (int i = 0; i < commands; i++) {

        place = commandStarts[i];

        if((pid = fork()) < 0) exit(1);
        else if (pid == 0) {
            if(i < pipe_counter && dup2(fds[j + 1], 1) < 0) exit(1);// If this is not the last remaining command

            if(j != 0 && dup2(fds[j-2], 0) < 0) exit(1);            // If this is not the first command

            for(int c = 0; c < 2*pipe_counter; c++) close(fds[c]);

            if(execvp(argv[place], argv+place)) exit(1);            // Execute and if it returns anything, exit!
        }
        j+=2;
    }

    for(int i = 0; i < 2 * pipe_counter; i++) close(fds[i]);

    for(int i = 0; i < commands; i++) wait(&status);            // The only program that gets to this point is the 
                                                                //     parent process, which should wait for completion.

也非常感谢 wallyk 帮助我思考这个问题!

【讨论】:

  • 虽然这更接近于一个健壮的实现,但它的缺点是它会被wait() 收割的任何孙辈破坏。您可以跟踪生成的孩子的 pid,并让等待循环等待那些特定的 id。
猜你喜欢
  • 2014-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-04
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多