Reputation: 3197
I am learning about pipes and forks. I am trying to get the count of kworker processes by using pipes and forks to represent ps -A | grep kworker | wc -l
. My code is working correctly until the point where I am doing the pipes for the grep statement.
I run my code like this: ./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
What could be causing this issue? I looked through other questions here and could not find a solution to this.
Upvotes: 0
Views: 696
Reputation: 58929
Look:
close(pipefd[1]);
dup2(pipefd[1], STDOUT_FILENO);
You close one of the FDs. Then you use dup2 with it. Because the FD is closed, dup2 returns an error code and doesn't do anything. So grep's stdout is still the normal stdout.
Your code has other problems. This is the one you asked about.
Elaboration about "other problems": Your code tries to use the same pipe twice. ps
and grep
read from the pipe, and grep
and wc
read from the pipe. This means data can go from ps
directly to wc
, or from grep
back to itself, which isn't what you want. You should use two separate pipes - one to connect ps
to grep
and one to connect grep
to wc
.
Upvotes: 1