gpt4 book ai didi

c++ - 玩具 shell 没有正确管道

转载 作者:行者123 更新时间:2023-11-30 04:13:38 24 4
gpt4 key购买 nike

我不会说谎。这是一道作业题。但是,就我而言,积分已经消失了。现在,我只是在寻找答案,因为我-认为-我可能疯了。

这个程序的目标是执行命令ps -A | grep(输入字符串) | wc -l 以类似于 shell 执行它的方式。所以,我产生了进程,让它们互相等待。最新的进程,曾孙 execlp("ps","ps","-A",NULL) 将自身替换为 ps -A 进程。在它 execlp 之前,我确保它的标准输出将转到管道输出。下一个进程是 wait()ing,它本身已经设置好,输入管道进入标准输入,标准输出进入输出管道,它会执行 grep,然后等等。

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

#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.\n";
exit(-1);
}
if ( pipe(pipeB) < 0 ) {
cerr << "Pipe error.\n";
exit(-1);
}

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

if ( pid > 0 ) { // parent case
wait(&stat);
} else { // child case
if ( (pid = fork()) < 0 ) { cerr << "Fork Error\n"; 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\n"; 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;
}

编辑:更改为我的代码的双管道变体。

最佳答案

我几乎可以肯定这就是您想要做的。为草率的编码提前道歉。这里有点晚了,我现在真的应该 sleep 了:

#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。上面的代码生成完全相同的输出。

关于c++ - 玩具 shell 没有正确管道,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19356075/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com