我不会撒谎的。这是一个家庭作业问题。然而,就我而言,这些观点已经消失,宝贝。现在,我只是在找答案,因为我-我想-我可能是疯了。
该程序的目标是以类似于shell的方式执行命令ps -A | grep (inputstring) | wc -l。因此,我产生了这些过程,让它们彼此等待。最新的过程,曾孙,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;
}编辑:更改为代码的双管变体。
发布于 2013-10-14 09:35:25
我很确定这就是你想要做的。为草率的编码提前道歉。这里有点晚了,我现在真该睡觉了:
#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 System | wc -l即可验证。上面的代码产生完全相同的输出。
发布于 2013-10-14 09:35:04
我不确定,但也许在等待孩子之前打电话给dup2会解决管道问题。
我不确定的原因是,通常stdin和stdout都是缓冲的,所以我想,即使您在孩子运行完之后将管道与它们连接起来,您也应该得到相同的结果,但是也许(如果有人知道这个问题的答案,请纠正我)缓冲区的stdin和stdout随着子进程的结束而被擦去。
另外,您是否可以更新问题中的代码,使其包含有两组管道的修改代码?
https://stackoverflow.com/questions/19356075
复制相似问题