parent local variable acting as shared variable between three child - c

How come in the below program the local variable of parent process is acting as a shared variable between three child processes.
int main()
{
int turn = 0;
int i;
for (i = 0; i < 3; i++)
{
if (fork() == 0)
{
int me = i;
while (turn != me)
/*do nothing*/ ;
// my turn
printf("Process %d ran\n", me);
turn++;
}
}
return 0;
}
Output:
Process 0 ran
Process 1 ran
Process 2 ran
But according to me the last two processes should hang as the value of turn should never change for them.
Also if i put a exit(0); after turn++, I am returned immediately to my shell prompt with only one line of output i.e:
Process 0 ran
But still the other two processes keep running in the background and no output by any of the other two processes.

What's going on:
main process is 0.
process 0 calls fork. i = 0;
process 0 returns from fork = 1;
process 0 calls fork. i = 1;
process 0 returns from fork = 2;
process 0 calls fork. i = 2;
process 0 returns from fork = 3;
process 0 exists;
process 1 returns from fork. i = 0;
process 1 hits the while loop turn = 0, i = 0, me = 0, while loop exists;
process 1 calls printf.
process 1 increments turn, turn = 1;
process 1 goes back to the for loop;
process 1 calls fork, i = 1;
process 1 returns from fork = 4;
process 1 calls fork, i = 2;
process 1 returns from fork = 5;
process 1 exists;
process 2 returns from fork. i = 1;
process 2 hits the while loop turn = 0, i = 1, me = 0, while loop spins forever;
process 3 returns from fork, i = 2;
process 3 hits the while loop turn = 0, i = 2, me = 0, while loop spins forever;
process 4 (spawned from process 1) returns from fork, i = 1, turn = 1 (inherited from process 1).
process 4 hits the while loop turn = 1, i = 1, me = 1, while loop exits;
process 4 calls printf;
process 4 increments turn, turn = 2;
process 4 goes back to the for loop;
process 4 calls fork, i = 2, turn = 2;
process 4 returns from fork = 6;
process 4 exits;
process 5 (spawned from process 1) return from fork, i = 2, turn = 1 (inherited from process 1)
process 5 hits the while loop turn = 1, i = 2, me = 2, while loop spins forever;
process 6 (spawned from process 4) returns from fork i = 2, turn = 2 (inherited from process 4)
process 6 hits the while loop turn = 2, i = 2, me = 2, while loop exists;
process 6 calls printf;
process 6 drops out of the for loop
process 6 exits;
Basically, you need to remember that all processes you will continue running the for loop, not just the main one. After that it's not too hard to figure out what's going on. You spawn 6 processes in total and three of them will have the right state of i and turn.

Refactor your code like this:
#include <unistd.h>
#include <stdio.h>
int main()
{
int turn = 0;
int i;
for (i = 0; i < 3; i++)
{
printf("forking i = %d, turn = %d\n", i, turn);
if (fork() == 0)
{
int me = i;
while (turn != me)
/*do nothing*/ ;
// my turn
printf("Process %d ran\n", me);
turn++;
}
}
return 0;
}
It may come as a shock to you but as Art's refactoring above shows pretty clearly your code will spawn 6 processes. Putting some more printfs in there should get your understand what's really going on.

Variable declared before fork() is shared for child processes. You may check it by printing &turn in loop. It will be same.

Related

Forking in a loop and printing the correct process number

The C script is supposed to take x amount of CPU bound forks and x amount of IO bound forks, so then lets say 10 total processes if you there's 5 of each. If I fork 10 times, then 5 of those should go to working on the CPU bound "fake work" and 5 of those should go to the IO bound "fake work". Waitstats is a custom function that serves the purpose of wait while also displaying rtime and wtime.
My problem is that I've tried multiple configurations and I'm not sure how to get the Process Number printf to correctly print, only 10 times, if there's only 10 forks? I also feel as if I'm not doing my fake work correctly for the CPU/IO bound work.
Any help here would be appreciated!
`
int main(int argc, char* argv[])
{
int cpuNum = atoi(argv[2]);
int ioNum = atoi(argv[4]);
int const MAX_PROC = cpuNum + ioNum;
printf("\nMax Proc %d", MAX_PROC);
int totRunTime = 0;
int totWaitTime = 0;
uint rTime = 0;
uint wTime = 0;
int pid = 0;
//Create Max_Proc Forks
for(int n=0; n < MAX_PROC; n++)
{
pid = fork();
//If Child, Exceute Command
if(pid == 0)
{
break;
}
}
if (cpuNum > 0) {
//CPU Busy Work
for (volatile int i = 0; i < 1000000000; i++){}
cpuNum--;
}
else if (ioNum > 0) {
//IO Busy Work
sleep(200);
ioNum--;
}
for(int p=0; p < MAX_PROC; p++)
{
printf("\n Process %d finished", p);
if(waitStats(0, &rTime, &wTime) >= 0)
{
totRunTime += rTime;
totWaitTime += wTime;
}
}
printf("\nAverage rtime %d, wtime %d", rTime, wTime);
exit(0);
}
`
I've tried multiple configurations, but can't seem to get the printf to print the correct process/fork number. For instance forking 10 times would mean I would need to printf every time one of those forks finished their task (10 total times).
The code shown doesn't print pids, so I'm assuming you mean "process number" as in 1st child, 2nd child etc.
Every one of your processes is running this:
for(int p=0; p < MAX_PROC; p++)
{
printf("\n Process %d finished", p);
...
So it looks like each process will print the numbers 0 .. MAX_PROC-1 (with no indication of which pid is printing)
Have you tried putting the waitStats for loop inside of your "Create Max_Proc Forks" for loop? So then basically everything should be inside of the first loop, probably giving you a good way to keep track of the process number?

How to create n threads, each one creates n - 1 threads

I am working with a large project and I am trying to create a test that does the following thing: first, create 5 threads. Each one of this threads will create 4 threads, which in turn each one creates 3 other threads. All this happens until 0 threads.
I have _ThreadInit() function used to create a thread:
status = _ThreadInit(mainThreadName, ThreadPriorityDefault, &pThread, FALSE);
where the 3rd parameter is the output(the thread created).
What am I trying to do is start from a number of threads that have to be created n = 5, the following way:
for(int i = 0; i < n; i++){
// here call the _ThreadInit method which creates a thread
}
I get stuck here. Please, someone help me understand how it should be done. Thanks^^
Building on Eugene Sh.'s comment, you could create a function that takes a parameter, which is the number of threads to create, that calls itself recursively.
Example using standard C threads:
#include <stdbool.h>
#include <stdio.h>
#include <threads.h>
int MyCoolThread(void *arg) {
int num = *((int*)arg); // cast void* to int* and dereference
printf("got %d\n", num);
if(num > 0) { // should we start any threads at all?
thrd_t pool[num];
int next_num = num - 1; // how many threads the started threads should start
for(int t = 0; t < num; ++t) { // loop and create threads
// Below, MyCoolThread creates a thread that executes MyCoolThread:
if(thrd_create(&pool[t], MyCoolThread, &next_num) != thrd_success) {
// We failed to create a thread, set `num` to the number of
// threads we actually created and break out.
num = t;
break;
}
}
int result;
for(int t = 0; t < num; ++t) { // join all the started threads
thrd_join(pool[t], &result);
}
}
return 0;
}
int main() {
int num = 5;
MyCoolThread(&num); // fire it up
}
Statistics from running:
1 thread got 5
5 threads got 4
20 threads got 3
60 threads got 2
120 threads got 1
120 threads got 0

Forked 10 child processes, how can the parent process collect their return values?

I have to find the biggest value in an array of a 1000 numbers with 10 child processes (so that every one of them only checks a hundred values), and the parent only has to collect the data.
I'm already done with the whole thing, but I'm stuck at reading the values.
Here's the code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int main(){
int array[1000];
int i, j;
int pids[10];
int searchminindex;
int searchmaxindex;
int maxindex;
srand(time(NULL));
//fill up array with random numbers
for(i = 0; i < 1000; i++)
{
tomb[i] = random() % 5000;
}
//create 10 child processes
for (i = 0; i < 10; i++) {
if ((pids[i] = fork()) < 0) {
perror("fork");
abort();
}
else if (pids[i] == 0) {
searchminindex = i * 100;
searchmaxindex = (i+1) * 100;
//finding the biggest value
maxindex = searchminindex;
for(j = searchminindex+1; j < maxindex; j++) {
if( array[maxindex] < array[j])
maxindex = j;
}
}
}
for(i = 0; i < 10; i++){
//here's where I'd read the return values of the subarrays
}
return 0;
}
I've tried using pipes and also using WEXITSTATUS, but I'm really confused and don't know where to close one end of the pipe and things like that, and with WEXITSTATUS I'm completely lost.
Any way you could help?
You need to test the pid returned from fork, and branch your code so your main process doesn't act like a child, and so that your children don't spawn children of their own. Once that's taken care of...
An alternative to mmap or setting up shared memory at all is to use WEXITSTATUS. According to the man page, it'll only return the least significant 8 bits, so if your return values can be greater than 127, this is likely not your best option. Can be made to work up to 255, but be careful about signedness of char, it's not standard.
int returned_values[10];
for(int i = 0; i < 10; ++i)
{
int status;
wait(&status);
if(WIFEXITED(status))
returned_values[i] = WEXITSTATUS(status);
else {
//Do something more meaningful here
//This means a child received a signal, or any of the other ways wait returns other than a child exiting.
--i;
}
You need to test the pid returned from fork, and branch your code so your main process doesn't act like a child, and so that your children don't spawn children of their own. Once that's taken care of...
Sharing memory between forked processes is explained well here
I would use mmap to create shared memory between the processes, you'll need to specify for each process where to put it's result, then use wait to determine when all children have exited, and a good program would evaluate the exit status and inform the user if any child exited abnormally.
Don't forget to clean up the shared memory before the parent exits.

Sum the number of children with vfork()

I want to write a program with vfork() and parent creates n children, I want to insert number of sons with parameter. And then I want to sum the number of sons for example:
./sum 4
The sum of the child: 10
The sum of the parent: 10
(1+2+3+4)
This is the small code I came up, but I get infinite loop.
int n = atoi(argv[1]);
int i = 1;
pid_t pid;
int sumchild = 0;
int sumparent = 0;
while(i <= n){
pid = vfork();
if(pid == 0){
sumchild = sumchild + i;
}
i++;
}
printf("The sum of the child: %i ", sumchild);
sumparent = (1 + n) * (n / 2);
printf("The sum of the parent: %i \n", sumparent);
I heard that you don't need wait() like in fork(), but I don't know why do I get infinite loop here.
How should I use vfork()?
Did I even write the code right or I made some mistakes?
The following code
pid = vfork();
if(pid == 0){
sumchild = sumchild + i;
will cause undefined behavior, according to vfork:
The vfork() function has the same effect as fork(2), except that the behavior is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit(2) or one of the exec(3) family of functions.

Outcome of a small C program

We need to tell the outcome of the following C program:
main()
{
int pid, k, som;
som = 0; k = 2;
pid = fork();
if(pid == 0)
k=5;
else
wait(0);
for(int i = 1; i <= k; i++)
som += i;
printf("%d", som);
}
My first expectation is 3. When a the fork call is made, the memory of the process is copied, and both programs go running. The child process then executes, but k still equals 2. So at the end, it executes 1 + 2 = 3;
But when this program is executed, it outputs 153. I haven't got the nearest clue why it outputs that.
Can anyone tell why?
The reason why is you have 2 processes printing out to the same console. "fork" is a unix/linux command that is called once and returns twice. One of the returns will be in the original process which called fork and will return the PID of the child process that was spawned. The second return will be 0 and this indicates it is the child process.
One of the programs, the child i believe, executes first and calculates 15 as the value and prints it to the console last. The parent program executes second because of the wait(0) and produces the value 3.
15 is printed by child, and 3 by parent.
A is parent, B is the child, here are the important lines:
A: pid = fork(); // returns 0 for the child process
A: wait(0);
B: k = 5;
B: for(int i = 1; i <= k; i++) som += i; // som = 15
B: printf("%d", som); // prints 15, B finishes, goes back to A
A: for(int i = 1; i <= k; i++) som += i; // som = 3
A: printf("%d", som); // prints 3
There's no newline being printed between the values so the parent's answer appears right after the child's answer.
Jared's correct about the cause of the values.

Resources