Averaging the output of multiple processes in C - c

I've been searching around about the topic, but it's kinda confusing for me with how many different techniques there are and I'm not sure how to approach my problem.
I have a function that computes some value, but it's based on random numbers and I want to compute that value multiple times, let's say few dozen or hundred times and take the average of it, but since it takes quite a while I've wanted to use multiprocessing, with each process executing that function, saving the result and then I'd simply sum the results and divide by the amount of worker processes in the main process.
Quite simple in theory, but I have no idea how to do it - it seems that a simple way would be to just do something like
loop that creates pipes
if (fork())
loop that reads the outputs of pipes
else
code of function that computes the desired value
but that somehow seems wrong? I'm really not sure how to do it
EDIT:
To adress the comments, I've been thinking about something like this:
for (int i = 0; i < n_children; ++i) {
if (fork() == 0) { //child process
x += estimation();
}
}
for (int i = 0; i < n_children; ++i) //waiting for each process to end
wait(NULL);
x /= n_children;
but I know that it won't work properly, I don't know how to store/synchronize the results

As William Pursell mentioned in the comments, a single pipe is what you want. The parent will close the write end, and each forked child will close the read end. Each child writes its result to the pipe. The parent calls wait(2) on each child and, if the status indicates data was written to the pipe, reads the pipe and updates the average.
It could also be done with Posix anonymous shared memory. Allocate an array of results in shared memory. Each child will have a unique value of the loop variable i when its process is created. The child writes to array[i]. The parent waits for each child. When they have all completed, iterate over the array and compute.

Related

Process tree / Number of processes for fork()

I want to know the number of processes created for the below code. I got to know from my instructor the answer is 41 but I am unable to follow the same. Please explain the same with a process tree.
void main() {
for (i=0;i<2;i++){
fork();
if(!fork()) {
execl("/bin/ls","ls",NULL);
fork();
}
fork();
}
fork();
}
This looks like a homework question. If we would draw a process tree for you, you might get some points now, but you will not learn how to analyze a program, and this may hurt you later. You will learn more by understanding how the program works. (Of course, this program is an academic example and not very useful except for learning.)
I suggest to mark the fork calls with letters.
int main(void) {
for (int i = 0; i < 2; i++) {
fork(); /* A */
if(!fork()) { /* B */
execl("/bin/ls","ls",NULL);
fork(); /* C */
}
fork(); /* D */
}
fork(); /* E */
}
Take paper and pencil, write down what happens and draw a tree using the loop counter and the marked fork calls.
Example:
The program runs a loop for two cycles (0 and 1), the loop continues in all processes.
In parent P, loop cycle 0, fork A will create child 1.
P -(0,A)-> 1
Still in loop cycle 0, both P and 1 will run the fork B inside the condition, creating a new child each.
P -(0,B)-> 2, 1 -(0,B)-> 3.
Think about the meaning of the condition and decide which processes run the conditional block.
Think about what happens after execl, e.g. process x executes ls, resulting in ...
Some processes (name them) will reach D and create a child each, all will continue with loop cycle 1...
etc.
To see what happens you could add some output after every fork to display what happens: which loop index, which fork, is the process parent or child of this fork, PID, parent PID. And before the execl display which PID is about to call it. (Note that buffered output like printf may show unexpected behavior in combination with fork, so it might be better to use sprintf and write.) Running the program will produce output that could help you to draw a process tree. It is even possible to format the output in a way that a tree could be generated automatically using graphviz or PlantUML. All these are advanced topics.

C: Read and write between parent and multiple child processes

Say I have a function called worker(int in, int out) that performs some task based on the given in file descriptor and takes the result and writes it to out.
It might look something like:
while (read(in, buffer, some_max_length) > 0){
// Do something with buffer
.
.
write(out, some_other_info, some_size);
}
Say I also have a main process that spawns a variable amount of processes that might look something like:
// Assume I have done error checking.
array_of_write_pipes[n][2];
array_of_read_pipes[n][2]; // Assume these have already been populated.
while(there is a word from stdin){
// Spawn n processes
for(int i = 0; i < n; i++){
n = fork();
if(n == 0){
write(array_of_read_pipes[i][1], some_data, some_max_length);
worker(some_other_data, array_of_read_pipes[i][0], array_of_write_pipes[i][1]);
exit(0);
}
}
// Block of code waiting for all children to terminate.
// Collect the results of each child process
for(i = 0; i < n; i++){
while (read(array_of_write_pipes[i][0], buffer, some_max_length) > 0){
// Do something with buffer
.
.
}
}
}
At the moment, it seems to hang.
My end goal is to have the main process send the same word to each child process. Each child process then performs the task via worker(). Then, the child process sends its results back to the main process for further processing.
At this moment, I'm not even sure if I'm even remotely going in the right direction.
I tried to keep this question as general as possible except for the parts dealing with piping. If I'm missing any information, please let me know. Just a disclaimer, this is a homework related problem and I do not want the full answer, just whether or not my thought process is correct. If not, what am I missing?
Any help is appreciated.

Managing multi processes to do the same jobs in C

I write a code that some processes use an array, sort it and then print it. In fact What I would like to do is that each process should sort a line of integer numbers that main process gives to them and print them, then send them back to the main process. The algorithm works fine without process and forking. But when I add forking, some process cause printing or performing some instruction more than one time or more. Please let me know how to manage it.
Here is the code:
if (N<=NumberOfLines)
{
PortionOfProcess=NumberOfLines/N;
for (int i=0;i<N;i++)//making N process using fork
{
for (int j=0; j<PortionOfProcess; j++)//For using from function by a single process
{
int pointer=i*PortionOfProcess+j;//this points to the line for each process
printf("poniter: %d . the i is %d, the j is: %d and the portionprocess is : %d\n",pointer,i,j,PortionOfProcess);
fileopener(B_result,pointer);
mypid=fork();
if (mypid==0)//child
{
///////////do the sorting
for (int j=0 ; j<(y-1) ; j++)
{
for (int i=0 ; i<(y-1) ; i++)
{
if (B_result[i+1] < B_result[i])
{
t = B_result[i];
B_result[i] = B_result[i + 1];
B_result[i + 1] = t;
}
}
}
for (int j=0 ; j<y ; j++)
{
printf("SORTED %d \n",B_result[j]);
}
//////////////////end sorting
}
}
}
}
I am new in C programming. I write a code that some processes use an array, sort it and then print it. The algorithm works fine with out process and forking
Here is what fork() does: it creates an entire new copy of the process that, in most ways, is completely independent of the original. However, the original parent process does not wait for the children to finish. Nor has it any way of communicating with the children.
What you want to do is actually quite complex. The parent and child processes needs to create some sort of communications channel. This is most usually done by creating a pipe between them. The child will then write to the pipe like a normal file and the parent will read from the pipe. The logic will look something like this:
create pipe
fork
if parent close write end of the pipe
if child close read end of pipe
The children then do their stuff and exit normally. The parent, however, has a load of files to read and it doesn't know which order to read them in. In your case the children are fairly simple, so you could probably just read each one in the order you create it, but you may also want to look at select so that you read the results in the order they are ready.
Finally, you need to call wait or waitpid so that you get the return status of each child and you do not end up with zombie processes which is a possibility because with the parent blocking on input from various pipes, any mistake you make could lead to it waiting forever (or until killed).

C unnnamed pipes and fork for calculation

So I'm trying to create program that accepts user input (price for example 50) and then first child passes it to second, second one add 10 (price is now 60), third one then 50 (price is now 110) and 4 one just prints/returns final price. I have fork in loop and I'm creating pipes, but price is always the same, only 10 is added in each child. What is wrong or how to fix so that it's going to work as I want to.
My code:
int main(int argc,char *argv[])
{
int anon_pipe[2];
int n,N=4;
char value_price[100];
if(argc>1)
{
int price=atoi(argv[1]);
printf("%d\n",price);
if(pipe(anon_pipe)==-1){
perror("Error opening pipe");
return -1;
}
for(n = 0; n < N; n++){
switch(fork()){
case -1:
perror("Problem calling fork");
return -1;
case 0:
close(anon_pipe[1]);
read(anon_pipe[0],value_price,100);
price+=10;
sprintf(value_price,"%d \n",price);
printf("Price: %d\n",atoi(value_price));
write(anon_pipe[1],value_price,sizeof(value_price));
_exit(0);
}
}
close(anon_pipe[0]);
sleep(1);
close(anon_pipe[1]);
}
return 0;
}
You seem to think that forking makes the child start from the beginning of the program. This is not the case, forking makes the child start at the same line when the fork() was called
For instance look at this code here:
read(anon_pipe[0],value_price,100);
price+=10;
sprintf(value_price,"%d \n",price);
printf("Price: %d\n",atoi(value_price));
See you increase the value of price but you never read that value form the pipe. So all children will always output +10 to their respective pipe.
You should check the return values of your function calls for error codes. If you had done, you would have detected the error arising from this combination of calls:
close(anon_pipe[1]);
// ...
write(anon_pipe[1],value_price,sizeof(value_price));
Very likely, you would also have detected that many of these calls ...
read(anon_pipe[0],value_price,100);
... signal end-of-file without reading anything. At the very least, you need read()'s return value to determine where to place the needed string terminator (which you fail to place before using the buffer as a string).
As a general rule, it is mandatory to handle the return values of read() and write(), for in addition to the possibility of errors / EOF, these functions may perform short data transfers instead of full ones. The return value tells you how many bytes were transferred, which you need to know to determine whether to loop to attempt to transfer more bytes.
Moreover, you have all of your processes using the same pipe to communicate with each other. You might luck into that working, but it is probable that at least sometimes you'll end up with garbled communication. You really ought to create a separate pipe for each pair of communicating processes (including the parent process).
Furthermore, do not use sleep() to synchronize processes. It doesn't work reliably. Instead, the parent should wait() or waitpid() for each of its child processes, but only after starting them all and performing all needed pipe-end handling. Waiting for the child processes also prevents them from remaining zombies for any significant time after they exit. That doesn't much matter when the main process exits instead of proceeding to any other work, as in this case, but otherwise it constitutes a resource leak (file descriptors). You should form the good habit of waiting for your child processes.
Of course, all of that is moot if you don't actually write the data you mean to write; #SanchkeDellowar explains in his answer how you fail to do that.

How to make multiple `fork()`-ed processes comunicate using shared memory?

I have a parent with 5 child processes. I'm wanting to send a random variable to each child process. Each child will square the variable and send it back to the parent and the parent will sum them all together.
Is this even possible? I can't figure it out...
edit: this process would use shared memory.
There are a great number of ways to do this, all involving some form of inter-process communication. Which one you choose will depend on many factors, but some are:
shared memory.
pipes (popen and such).
sockets.
In general, I would probably popen a number of communications sessions in the parent before spawning the children; the parent will know about all five but each child can be configured to use only one.
Shared memory is also a possibility, although you'd probably have to have a couple of values in it per child to ensure communications went smoothly:
a value to store the variable and return value.
a value to store the state (0 = start, 1 = variable ready for child, 2 = variable ready for parent again).
In all cases, you need a way for the children to only pick up their values, not those destined for other children. That may be as simple as adding a value to the shared memory block to store the PID of the child. All children would scan every element in the block but would only process those where the state is 1 and the PID is their PID.
For example:
Main creates shared memory for five children. Each element has state, PID and value.
Main sets all states to "start".
Main starts five children who all attach to the shared memory.
Main stores all their PIDs.
All children start scanning the shared memory for state = "ready for child" and their PID.
Main puts in first element (state = "ready for child", PID = pid1, value = 7).
Main puts in second element (state = "ready for child", PID = pid5, value = 9).
Child pid1 picks up first element, changes value to 49, sets state to "ready for parent"), goes back to monitoring.
Child pid5 picks up second element, changes value to 81, sets state to "ready for parent"), goes back to monitoring.
Main picks up pid5's response, sets that state back to "start.
Main picks up pid1's response, sets that state back to "start.
This gives a measure of parallelism with each child continuously monitoring the shared memory for work it's meant to do, Main places the work there and periodically receives the results.
The nastiest method uses vfork() and lets the different children trample on different parts of memory before exiting; the parent then just adds up the modified bits of memory.
Highly unrecommended - but about the only case I've come across where vfork() might actually have a use.
Just for amusement (mine) I coded this up:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/wait.h>
int main(void)
{
int i;
int array[5];
int square[5];
long sum = 0;
srand(time(0));
for (i = 0; i < 5; i++)
{
array[i] = rand();
if (vfork() == 0)
{
square[i] = array[i] * array[i];
execl("/bin/true", "/bin/true", (char *)0);
}
else
wait(0);
}
for (i = 0; i < 5; i++)
{
printf("in: %d; square: %d\n", array[i], square[i]);
sum += square[i];
}
printf("Sum: %d\n", sum);
return(0);
}
This works. The previous trial version using 'exit(0)' in place of 'execl()' did not work; the square array was all zeroes. Example output (32-bit compilation on Solaris 10, SPARC):
in: 22209; square: 493239681
in: 27082; square: 733434724
in: 2558; square: 6543364
in: 17465; square: 305026225
in: 6610; square: 43692100
Sum: 1581936094
Sometimes, the sum overflows - there is much room for improvement in the handling of that.
The Solaris manual page for 'vfork()' says:
Unlike with the fork() function, the child process borrows
the parent's memory and thread of control until a call to
execve() or an exit (either abnormally or by a call to
_exit() (see exit(2)). Any modification made during this
time to any part of memory in the child process is reflected
in the parent process on return from vfork(). The parent
process is suspended while the child is using its resources.
That probably means the 'wait()' is unnecessary in my code. (However, trying to simplify the code seemed to make it behave indeterminately. It is rather crucial that i does not change prematurely; the wait() does ensure that synchronicity. Using _exit() instead of execl() also seemed to break things. Don't use vfork() if you value your sanity - or if you want any marks for your homework.)
Things like the anti thread might make this a little easier for you, see the examples (in particular the ns lookup program).

Resources