PDA

View Full Version : Forking multiple child processes in C++


md5fungi
Oct25-09, 03:25 PM
1. The problem statement, all variables and given/known data

Need to split a file up into four parts, have four child processes assigned to a different part and sum that part, and then send the data to the parent process, which will then sum the four sums.

2. Relevant equations

Basic Fork() Knowledge and C++ Knowledge.


3. The attempt at a solution

I keep on having the same problem, regardless of how I code the program. The first child process does what it should, but the second, third, and fourth just print 0 for a sum. There must be some fundamental misunderstanding of the material I have, but I can't figure out what that is.

#include <iostream>
#include <unistd.h>
#include <fstream>
#include <sys/wait.h>
#include <iostream>
#include <fstream>
using namespace std;

int main()
{
int i,n=0,total_numbers=0,number, status, split_numbers;
int previous_number[4];
int my_number[4];
int current_number[4] = {1,1,1,1};
int sum[4] = {0,0,0,0};
pid_t pid;
ifstream myfile;
myfile.open("test.dat");
while (myfile >> number) {
total_numbers++;
}
split_numbers = total_numbers/4;
myfile.close();
pid = fork();

for (i=0; i<4; i++) {
if (pid == 0) {
cout << "Child Process " << i << " " << getpid() << endl;
myfile.open("test.dat");
my_number[i] = split_numbers * (i+1);
previous_number[i] = split_numbers * i + 1;
while (myfile >> number) {
if (my_number[i] >= current_number[i] && previous_number[i] <= current_number[i]) {
sum[i]+=number;
current_number[i]++;
}
}
cout << sum[i] << endl;
myfile.close();
exit(0);
} else {
waitpid(pid, &status, 0);
cout << "Parent Process " << getpid() << endl;
pid = fork();
}
}
return 0;
}

1. The problem statement, all variables and given/known data



2. Relevant equations



3. The attempt at a solution

Hurkyl
Oct25-09, 03:47 PM
I can't figure out what you were trying to do with your while loop. But the reason the sum is zero is because the test
previous_number[i] <= current_number[i]
always fails, since the latter is always 1 and the latter is larger than 1. (If split_numbers is positive, anyways)


About your multi-threading, I have three questions about your setup:
(1) Was the assignment specifically to use fork()?

(2) How were you planning on having the children return their partial sum to the parent?

(3) Did you really intend to spawn children one at a time, rather than spawn all four at once?

md5fungi
Oct25-09, 04:10 PM
I don't see how previous_number[i] is always 1... When "i" increases, the value of previous_number[i] should increase; I even cout'd the value to make sure. Then it's supposed to go through the file line by line until previous_number <= current_number, and then start summing until my_number >= current_number.

1.) Yes, the assignment was specifically to use fork.

2.) We are supposed to "pipe" the sums back to the parent, and then the parent is supposed to add them up.

3.) Actually, I intended to spawn all the children at the same time. I'd do this, I assume, by removing the "wait" command I have in there. This way it is easier to see if it's working, though.

md5fungi
Oct25-09, 04:20 PM
Ohh.... I figured it out. I'm supposed to increment current_number[i] every time the loop reads the next line... but I was only doing it if it passed the test, which makes no sense..

Aha, I'm an idiot. Thanks for nudging me in the right direction!

Hurkyl
Oct25-09, 05:01 PM
2.) We are supposed to "pipe" the sums back to the parent, and then the parent is supposed to add them up.

3.) Actually, I intended to spawn all the children at the same time. I'd do this, I assume, by removing the "wait" command I have in there. This way it is easier to see if it's working, though.
Okay. This is a very sound approach to the problem -- I just wanted to make sure you weren't just making a mistake. (there is a wide variety of skill levels here, and fork() can be surprising to people who are used to things like java.lang.Thread or pthreads)

md5fungi
Oct25-09, 05:09 PM
So, I have everything correctly implemented, except possibly my processes running concurrently. I got rid of the waitpid function, and it still seems like the order is Process 0, 1, 2, and then 3. Is there something else I need to do to make them run at the same time? Is there an easy way to tell?

Hurkyl
Oct25-09, 05:13 PM
Fork is a "slow" operation -- your first child probably finished its task before the second child got created.

If you want to see the concurrency, you could try adding a timed loop to the child task -- make child #n spin-wait for 5-n seconds or something like that, just to see if child 3 really finishes first.

md5fungi
Oct25-09, 05:24 PM
Alright; thanks a lot for your help!

md5fungi
Oct25-09, 06:03 PM
One last quick question: When I run my program in Linux, it doesn't quit automatically; I have to Ctrl-C out of the program. This is problematic, because I want to use "time ./a.out" to see how long my program runs, and I can only see that result after I push Ctrl-C, thereby giving me an incorrect result.