-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpiping_test.cpp
More file actions
131 lines (107 loc) · 3.14 KB
/
piping_test.cpp
File metadata and controls
131 lines (107 loc) · 3.14 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include<iostream>
#include<unistd.h>
#include<sys/wait.h>
#include<vector>
std::vector<char*> makeArgs(const std::vector<std::string>& tokens)
{
std::vector<char*>argv;
for(auto& s: tokens)
{
argv.push_back(const_cast<char*>(s.c_str()));
}
argv.push_back(nullptr);
return argv;
}
int main()
{
std::vector<std::vector<std::string>> commands = {
{"printf", "c\nb\na\n"},
{"sort"},
{"tr", "a-z", "A-Z"},
{"uniq"}
};
int n = commands.size();
// Create N-1 pipes for N commands
std::vector<std::array<int,2>> pipes(n - 1);
for (int i = 0; i < n - 1; i++)
pipe(pipes[i].data());
// FORK N processes
for(int i = 0; i < n; i++)
{
pid_t pid = fork();
if(pid == 0)
{
// i > 0. means this is a middle pipe so expect input from previous pipe
if(i> 0)
dup2(pipes[i-1][0],STDIN_FILENO);
// i<n-1 means all the middle pipes so forward to the next pipe for the next child
if(i < n-1)
dup2(pipes[i][1], STDOUT_FILENO);
//close all file FDs
for(auto& p : pipes)
{
close(p[0]);
close(p[1]);
}
auto argv = makeArgs(commands[i]);
execvp(argv[0], argv.data());
perror("execvp");
_exit(1);
}
}
// parent closes all pipe fds, cuz each process has its own pipes for all of em
for (auto& p : pipes)
{
close(p[0]);
close(p[1]);
}
// wait for all children. we can use wait cuz 1 wait waits for 1 child only so n waits will wait till all n children are done.
for (int i = 0; i < n; i++)
wait(nullptr);
}
//this was wrong cuz we were using the same pipe also waiting too early. it was wrong. the children run concurrently not serially
//run the first fork and put output in a pipe.
// int fd[2];
// pipe(fd);
// pid_t p1 = fork();
// if (p1 == 0)
// {
// dup2(fd[1],STDOUT_FILENO);
// close (fd[0]);
// close (fd[1]);
// std::vector<char*> argv = makeArgs(commandVector[0]);
// execvp(argv[0],argv.data());
// perror("execvp");
// }
// else{
// int status;
// waitpid(p1, &status, 0);
// }
// for(int i = 1; i < len-1; i ++)
// {
// pid_t pi = fork();
// if (pi == 0)
// {
// dup2(fd[0],STDIN_FILENO);
// dup2(fd[1], STDOUT_FILENO);
// close(fd[0]);
// close(fd[1]);
// std::vector<char*> argv = makeArgs(commandVector[i]);
// execvp(argv[0],argv.data());
// perror("execvp");
// }
// }
// pid_t pn = fork();
// if (pn == 0)
// {
// dup2(fd[0], STDIN_FILENO); // stdin <- pipe read
// close(fd[1]);
// close(fd[0]);
// std::vector<char*> argv = makeArgs(commandVector[len-1]);
// execvp(argv[0],argv.data());
// perror("execvp");
// }
// else{
// int status;
// waitpid(pn, &status, 0);
// }