c - 管道和过程管理

标签 c shell pipe waitpid

我正在研究用 C 语言实现的微型 shell(tsh)(这是一项作业)。作业的一部分属于 PIPING。我必须将一个命令的输出通过管道传递给另一个命令。例如:ls -l |排序

当我运行 shell 时,我在其上执行的每个命令都由它生成的子进程处理。 child 完成后返回结果。对于管道,我想先实现一个硬编码示例来检查它是如何工作的。我写了一个方法,部分有效。问题是当我运行管道命令时,子进程完成后,整个程序随之退出!显然我没有正确处理子进程信号(下面的方法代码)。

我的问题:

  • pipe() 的进程管理是如何工作的?如果我运行命令 ls -l | sort 它是否为 ls -l 创建了一个子进程,为 sort 创建了另一个进程?从我目前看到的管道示例来看,只创建了一个进程(fork())。

  • 当第二个命令(我们示例中的sort)被处理时,我如何获得它的进程 ID?

编辑:同样在运行这段代码时我得到了两次结果。不知道为什么会运行两次,里面没有循环。

这是我的代码:

pid_t pipeIt(void){
    pid_t pid;
    int pipefd[2];

    if(pipe(pipefd)){
        unix_error("pipe");
        return -1;
    }

    if((pid = fork()) <0){
        unix_error("fork");
        return -1;  
    }
    if(pid == 0){
        close(pipefd[0]);
        dup2(pipefd[1],1);
        close(pipefd[1]);
        if(execl("/bin/ls", "ls", (char *)NULL) < 0){
            unix_error("/bin/ls");
            return -1;
        }// End of if command wasn't successful

    }// End of pid == 0
    else{
        close(pipefd[1]);
        dup2(pipefd[0],0);
        close(pipefd[0]);
        if(execl("/usr/bin/tr", "tr", "e", "f", (char *)NULL) < 0){
            unix_error("/usr/bin/tr");
            return -1;
        }
    }

    return pid;

}// End of pipeIt

最佳答案

是的,shell 必须 fork 来执行每个子进程。请记住,当您调用 execve() 函数族之一时,它会用已执行的进程镜像替换当前进程镜像。如果它直接执行子进程,您的 shell 将无法继续处理更多命令,因为此后它不再存在(子进程除外)。

要修复它,只需在 pid == 0 分支中再次使用 fork(),然后在该子分支中执行 ls 命令。如果您不想异步执行管道,请记住为两个(所有)子进程使用 wait()

关于c - 管道和过程管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48350893/

相关文章:

c - C中是否有一个函数可以检查一个字符是字符还是整数等?

c - 为什么这个更快?提交 1 与提交 2

python - 如何在嵌入式系统中使用 REST 客户端 API

c - 我对堆栈不了解

linux - 检测 block 设备是本地磁盘还是移动U盘

string - sed 打印第 N 个字符

c - UNIX 编程、fork 分屏、exec 以及与管道通信

node.js - nodejs 将数据附加到读取流的末尾

macos - bash:ps grep用于Umlaut(OS X)处理

Python,伪造标准输入