【发布时间】:2020-11-04 16:29:01
【问题描述】:
我正在学习管道和叉子。我试图通过使用管道和叉子来表示 ps -A | grep kworker | wc -l 来获取 kworker 进程的计数。我的代码工作正常,直到我为 grep 语句做管道。
我这样运行我的代码:./a.out kworker
#include <iostream>
#include <unistd.h> // for fork()
#include <sys/wait.h> // for wait()
using std::cout;
using std::endl;
int main(int num = 1, char * args[] = NULL)
{
int pipefd[2];
pipe(pipefd);
char * p[3];
/*
wait for grandchild to complete ps - A
wait for child to complete grep kworker
execute wc -l
*/
p[2] = NULL;
pid_t id1 = fork(); // get child process
if(id1 == -1)
{
perror("fork");
close(pipefd[0]);
close(pipefd[1]);
}
else if(id1 == 0) // child process
{
pid_t id2 = fork(); // get grandchild process
if(id2 == 0) // grandchild process
{
p[0] = "ps";
p[1] = "-A";
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[0]); // close read
close(pipefd[1]);
execvp(p[0], p);
perror("exec");
exit(1);
}
else if(id2 > 0) // child process
{
// The problem is in this if-statement
close(pipefd[1]);
wait(0);
p[0] = "grep";
p[1] = args[1];
// I get output from the STDOUT
dup2(pipefd[0], STDIN_FILENO); // read from pipe
dup2(pipefd[1], STDOUT_FILENO); // write to pipe
close(pipefd[1]);
execvp(p[0], p);
}
}
else if(id1 > 0) // parent process
{
// close pipes first
close(pipefd[1]); // close unused write end
wait(0);
p[0] = "wc";
p[1] = "-l";
dup2(pipefd[0], STDIN_FILENO); // read from pipe
close(pipefd[1]);
close(pipefd[0]);
if(execvp(p[0], p) == -1)
{
perror("exec");
exit(1);
}
}
}
代码给我的输出:
6 ? 00:00:00 kworker/0:0H-events_highpri
20 ? 00:00:00 kworker/1:0H-kblockd
26 ? 00:00:00 kworker/2:0H-kblockd
32 ? 00:00:00 kworker/3:0H-kblockd
50 ? 00:00:00 kworker/1:1-events
172 ? 00:00:00 kworker/u17:0-rb_allocator
289 ? 00:00:00 kworker/3:1H
290 ? 00:00:00 kworker/1:1H-events_highpri
296 ? 00:00:00 kworker/0:1H-kblockd
360 ? 00:00:00 kworker/2:1H-events_highpri
550 ? 00:00:00 kworker/u17:1-rb_allocator
1340 ? 00:00:01 kworker/2:4-events
1374 ? 00:00:00 kworker/0:0-events
2751 ? 00:00:00 kworker/3:2-events
2782 ? 00:00:00 kworker/1:2-mm_percpu_wq
5389 ? 00:00:00 kworker/0:1-events
6539 ? 00:00:00 kworker/u16:3-events_unbound
6599 ? 00:00:00 kworker/3:1
6618 ? 00:00:00 kworker/2:1-events
6705 ? 00:00:00 kworker/u16:0-events_unbound
6815 ? 00:00:00 kworker/u16:1-events_unbound
7283 ? 00:00:00 kworker/u16:2-events_unbound
0
我希望输出与以下内容相同:
ps -A | grep kworker | wc -l
21
什么可能导致此问题?我在这里查看了其他问题,但找不到解决方案。
添加第二个管道解决了这个问题。我们不能同时读取和写入同一个管道。
【问题讨论】:
-
我想知道当一个进程从它输出到的同一管道输入时会发生什么?
-
您的
pipefd对在所有三个进程之间共享。在等效的 shell 命令中,每个管道应该有一对。 -
@Botje 非常感谢您指出这一点。这是一个愚蠢的错误。
-
@user253751 感谢您指出这一点。现在想起来真是一件愚蠢的事情。
-
我的工作解决方案是这样的:pipe1 为 ps -A 写入,pipe1 为 grep kworker 读取,pipe2 为 grep kworker 写入,pipe2 为 wc -l 读取
标签: c++ linux operating-system pipe fork