玩具外壳管道不正确

2022-01-02 00:00:00 process shell c++ dup2

我不会撒谎.这是一道作业题.然而,就我而言,这些点都不见了,宝贝不见了.现在,我只是在寻找答案,因为我-认为-我可能疯了.

I'm not going to lie. This is a homework question. However, as far as I'm concerned, the points are gone baby gone. Right now, I'm just looking for an answer, because I -think- I might be insane.

这个程序的目标是执行命令 ps -A |grep (输入字符串) |wc -l 的方式与 shell 的工作方式类似.因此,我生成了这些进程,并让它们相互等待.最新的进程,曾孙进程,execlp("ps","ps","-A",NULL) 将自身替换为 ps -A 进程.在它execlp 之前,我确保它的标准输出将进入管道输出.下一个进程是wait()ing,它本身已经设置好输入管道进入标准输入,标准输出进入输出管道,它将执行grep,并且以此类推.

The goal of this program is to execute the command ps -A | grep (inputstring) | wc -l in a way similar to how the shell does it. So, I spawn the processes, and have them wait on each other. The newest process, the great-grandchild, execlp("ps","ps","-A",NULL) which replaces itself with the ps -A process. Before it execlp, I make sure its standard output is going to the pipe output. The next process in line is wait()ing, and already has itself set up so that the input pipe goes to standard in, and standard out goes to the output pipe, and it will execute grep, and so on.

我几乎可以肯定我已经正确设置了它.然而......该程序确实如此.不是.工作.

I'm almost positive I have it set up correctly. And yet... the program does. Not. Work.

#include <stdlib.h>
#include <iostream>
#include <string>

#define MAXLINE 1500
#define READ 0
#define WRITE 1

using namespace std;

int main( int argc, char** argv ) {
//* start of input block
if ( argc != 2 ) {
    cout << "Usage: ./a.out arg1" << endl;
    return 0;
}
string in = argv[1];
// end of input block */
int pipeA[2], pipeB[2], pid, stat;

// get our first set of pipes
if ( pipe(pipeA) < 0 ) {
    cerr << "Pipe error.
";
    exit(-1);
}
if ( pipe(pipeB) < 0 ) {
    cerr << "Pipe error.
";
    exit(-1);
}

// make the first fork
if ( (pid = fork() ) < 0 ) { cerr << "Fork error.
"; exit(-1); }

if ( pid > 0 ) {    // parent case
    wait(&stat);
} else {            // child case
    if ( (pid = fork()) < 0 ) { cerr << "Fork Error
"; exit(-1); }
    if ( pid > 0 ) {    // child
        wait(&stat);
        dup2(pipeA[READ],READ);
        execlp("wc","wc","-l",NULL);
    } else {    // grand-child
        if ( (pid = fork()) < 0 ) { cerr << "Fork Error
"; exit(-1); }
        if ( pid > 0 ) {    // still grand-child
            wait(&stat);
            dup2(pipeB[READ],READ);  
            dup2(pipeA[WRITE],WRITE); 
            close(pipeB[READ]);
            execlp("grep","grep",in.c_str(),NULL);
        } else {    // great grand-child
            dup2(pipeB[WRITE],WRITE); // t now goes to pipeB[1]
            close(READ);
            close(pipeB[READ]);
            execlp("ps", "ps", "-A", NULL);
        }
    }
}
return 0;
}

更改为我的代码的双管道变体.

Changed to the two-pipe variant of my code.

推荐答案

我几乎确定这就是您想要做的.为草率的编码提前道歉.现在有点晚了,我现在真的应该睡觉了:

I'm virtually certain this is what you're trying to do. Apologies in advance for the sloppy coding. its somewhat late here and I really should be sleeping right now:

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <unistd.h>

#define READ 0
#define WRITE 1

// ps -A | grep argv[1] | wc -l

int main( int argc, char** argv )
{
    // start of input block
    if ( argc != 2 )
    {
        std::cout << "Usage: ./a.out arg1" << std::endl;
        return 0;
    }
    
    // make local copy of argument
    std::string in = argv[1];
    int fd1[2], fd2[2], pid;
    
    // allocate two pipe sets
    if (pipe(fd1) < 0 || pipe(fd2) < 0)
    {
        perror("Failed to create pipe.");
        return EXIT_FAILURE;
    }
    
    // launch first child process.
    if ((pid = fork()) < 0)
    {
        perror("Failed to fork child(1)");
        return EXIT_FAILURE;
    }
    
    if (pid == 0)
    {
        // wc -l process. 
        //  stdin  = fd2(read)
        close(fd1[READ]);
        close(fd1[WRITE]);
        close(fd2[WRITE]);
        dup2(fd2[READ],STDIN_FILENO);
        execlp("wc","wc","-l",NULL);
    }
    
    // fork again. this time for grep
    if ((pid = fork()) < 0)
    {
        perror("Failed to fork child(2)");
        return EXIT_FAILURE;
    }
    
    if (pid == 0)
    {
        // grep argv[1] process.
        //  stdin  = fd1(read)
        //  stdout = fd2(write)            
        close(fd1[WRITE]);
        close(fd2[READ]);
        dup2(fd2[WRITE], STDOUT_FILENO);
        dup2(fd1[READ], STDIN_FILENO);
        execlp("grep", "grep", in.c_str(), NULL);
    }
    
    //  fork once more. this time for ps -A
    if ((pid = fork()) < 0)
    {
        perror("Failed to fork child(3)");
        return EXIT_FAILURE;
    }
    
    if (pid == 0)
    {
        // ps -A process.
        //  stdout = fd1(write)
        close(fd2[WRITE]);
        close(fd2[READ]);
        close(fd1[READ]);
        dup2(fd1[WRITE], STDOUT_FILENO);
        execlp("ps", "ps", "-A", NULL);
    }
    
    int stat=0;
    wait(&stat);

    return EXIT_SUCCESS;
}

在我的系统上,ps -A 报告了 141 行,其中 41 行中有 System 字样,只需运行 ps -A | 即可验证.grep系统|wc -l.上面的代码生成完全相同的输出.

On my system, ps -A reports 141 lines, of those 41 have the word System somewhere within, verified by simply running ps -A | grep System | wc -l. The above code generates precisely the same output.

相关文章