管道和流程管理 [英] Pipe and Process management

查看:107
本文介绍了管道和流程管理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个用C实现的小shell(tsh)(这是一项任务).作业的一部分属于PIPING.我必须将一个命令的输出传递给另一个命令.例如:ls -l | sort

I am working on a tiny shell(tsh) implemented in C(it's an assignment). One part of assignment belongs to PIPING. I have to pipe a command's output to another command. e.g:ls -l | sort

运行外壳程序时,我在外壳程序上执行的每个命令都由其生成的子进程处理.孩子完成后,将返回结果.对于管道,我想首先实现一个经过编码的示例,以检查其工作方式.我写了一个方法,部分有效.问题是当我运行pipe命令时,子进程完成后,整个程序都退出了!显然我没有正确处理子进程信号(下面的方法代码).

When I run the shell, every command that I execute on it, is processed by a child process that it spawns. After the child finishes the result is returned. For piping I wanted to implement a harcoded example first to check how it works. I wrote a method, that partially works. The problems is when I run the pipe command, after child process finishes, the whole program quits with it! Obviously I am not handling the child process signal properly(Method code below).

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

  • How does process management with pipe() works? if i run a command ls -l | sort does it create a child process for ls -l and another process for sort ? From the piping examples that I have seen so far, only one process is created(fork()).

处理第二个命令(在我们的示例中为sort)时,如何获取其进程ID?

When the second command (sort from our example) is processed, how can i get its process ID?

同样在运行此代码时,我得到了两次结果.不知道为什么它运行两次,那里没有循环.

Also while running this code I get the result twice. don't know why it runs twice, there is no loop in there.

这是我的代码:

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必须派生才能执行每个子进程.请记住,当调用execve()系列函数之一时,它将用执行的函数替换当前过程映像.如果外壳程序直接执行子进程,则它无法继续处理其他命令,因为此后它不再存在(作为子进程除外).

Yes, the shell must fork to exec each subprocess. Remember that when you call one of the execve() family of functions, it replaces the current process image with the exec'ed one. Your shell cannot continue to process further commands if it directly execs a subprocess, because thereafter it no longer exists (except as the subprocess).

要修复此问题,只需在pid == 0分支中再次fork(),然后在该子级中执行ls命令.如果您不希望管道异步执行,请记住对两个(所有)子进程都使用wait().

To fix it, simply fork() again in the pid == 0 branch, and exec the ls command in that child. Remember to wait() for both (all) child processes if you don't mean the pipeline to be executed asynchronously.

这篇关于管道和流程管理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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