`fork()` sons are executing in reverse order [duplicate] - c

This question already has answers here:
In fork() which will run first, parent or child?
(2 answers)
Closed 8 years ago.
I have a code similar to this:
for (i = 0; i < 3; i++)
{
pid = fork();
if (pid == 0)
{
son_function();
}
if (pid < 0)
{
exit(1);
}
}
void son_function(void)
{
printf("my pid=%d\n", getpid());
printf("%d: alpha\n", getpid());
printf("%d: beta\n", getpid());
printf("%d: charlie\n", getpid());
exit(0);
}
For some reason I can't understand, the order of execution of son_function() is in reverse order. What I mean is that son_function() is printing the PID numbers from the largest to the smallest.
Another thing that freaks me is that the prints for every son will be in the one after the other, there's no way that two prints from two different processes will print to the screen at the same time.
Sample can be seen here: http://ideone.com/uBYyRX

Multiple processes can output to the console at the same time, at least under Windows and Linux.
The reason you may see all of one process before all of the other is due to the way your particular OS schedules threads. A better way to see this behavior is to change son_function to look something like the code below, where each child sleeps for a different amount of time. The reason who lines get interleaved (as noted before) is because printf buffers lines of output.
void son_function()
{
srandom(getpid());
int sleepTime = random() % 4; // random sleep between 0 and 3 seconds
printf("pid [%d] sleep time is %d\n", getpid(), sleepTime);
printf("my pid = %d\n", getpid());
sleep(sleepTime);
printf("alpha = %d\n", getpid());
sleep(sleepTime);
printf("beta = %d\n", getpid());
sleep(sleepTime);
printf("charlie = %d\n", getpid());
sleep(sleepTime);
}

To execute the child process in the correct order just add the wait function inside the loop before calling the fork function.
so it will wait till the child terminates and the child process will be terminated in the correct order.
for (i = 0; i < 3; i++)
wait();
pid = fork();
execute the code after adding the wait function.

Related

Fork() code not working as expected - Hierarchy making

Good afternoon.
I am currently working on a C program that takes one and only one parameter which designates the number of "child generation"s to be created (the own father counts as 1 already). "wait()" system calls are not to be used for this exercise (the version with "wait" calls happens to work exactly as expected).
For instance, the call $program 4 should generate a hierarchy like this:
Process A creates B
Process B creates C
Process C creates D
The printed messages are not important, as they are merely orientative for the task. With the following code (which happens to work exactly how I want with a "wait()" call) states that all the child processes derive from the same father, which I don't understand why it's happening.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int counter; pid_t result; int i;
/*
We are going to create as many processes as indicated in argv[1] taking into account that the main father already counts as 1!
*/
if (argc > 2 || argc == 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
int lim = atoi(argv[1]);
//We eliminate the impossible cases
if (lim < 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
if (lim == 1) {puts("The father himself constitutes a process all by his own, therefore:\n");
printf("Process%d, I'm %d and my father: %d\n", counter, getpid(), getppid());
}
else {
for (i = 0; i < lim; i++) {
result = fork();
if (result < 0) {
printf("Call%d \n", counter); perror("Has failed!");
exit(-1);
}
else if (result) {
break; //Father process
}
else {
counter++; //Child processes increment the counter
printf("Process%d, I am %d and my father: %d\n", counter, getpid(), getppid());
}
}
}
The hierarchy generated by the code above is not the one I expected...
All help is greatly appreciated.
Thank you
With the following code (which happens to work exactly how I want with
a "wait()" call) states that all the child processes derive from the
same father, which I don't understand why it's happening.
I don't see that in my tests, nor do I have any reason to expect that it's actually the case for you. HOWEVER, it might appear to be the case for you if what you see is some or all of the child processes reporting process 1 as their parent. That would happen if their original parent terminates before the child's getppid() call is handled. Processes that are orphaned in that way inherit process 1 as their parent. If the parent wait()s for the child to terminate first then that cannot happen, but if instead the parent terminates very soon after forking the child then that result is entirely plausible.
Here's a variation on your loop that will report the original parent process ID in every case:
pid_t my_pid = getpid();
for (i = 0; i < lim; i++) {
result = fork();
if (result < 0) {
printf("Call%d \n", counter); perror("Has failed!");
exit(-1);
} else if (result) {
break; //Father process
} else {
pid_t ppid = my_pid; // inherited from the parent
my_pid = getpid();
counter++; //Child processes increment the counter
printf("Process%d, I am %d and my father: %d\n", counter, (int) my_pid, (int) ppid);
}
}
You are missing a crucial function call.
for (i = 0; i < lim; i++) {
fflush(stdout); // <============== here
result = fork();
Without it, your fork duplicates parent's stdout buffer into the child process. This is why you are seeing parent process output repeated several times --- its children and grandchildren inherit the output buffer.
Live demo (with fixed formatting for your reading convenience).

using fork() to make 3 children out of 1 parent in C (not C++)

Hi there I've been working on a program that forks children and later will fork more children from each child but that's not what I need help with. When I run my program (in here it is a function but works the same) I am supposed to have one parent(PPID) spawn 3 children (PIDS= 1,2,3) but what I get is either the same PID and PPID 3 times (my current code) or before I was getting 3 parents with each parent having one child and the PPIDS were different as well as the PIDS, but the PPIDs were just the same as the previous child PIDs. In my latest attempts it never displays the parent(dad) message above the child(son). It should look like this
[dad] hi am I PID 1234 and I come from ####(dont care what this number is)
[son] hi i am PID 1111 and I come from PPID 1234
[son] hi i am PID 1112 and I come from PPID 1234
[son] hi i am PID 1113 and I come from PPID 1234
here is my code. I'm just looking for hints if possible unless it's just a silly mistake I've made like "oh just move the fork() to the child process" or something like that.
Also I have a child_count just so I can easily count the children.
int forking(null)
{
void about(char *);
int i=0;
int j=0;
int child_count =0;
about("dad");
for(i = 0; i < 3; i++ ){
pid_t child = 0;
child = fork();
if (child < 0) { //unable to fork error
perror ("Unable to fork");
exit(-1);}
else if (child == 0){ //child process
about ("son");
printf("I am child #%d \n",child_count);
child_count++;
exit(0);}
else { //parent process (do nothing)
}
}
for(j = 0; j < 3; j++ ){
wait(NULL);//wait for parent to acknowledge child process
}
return 0;
}
The parent needs to
- print a message
- call fork three times
- wait for the three children to exit
Each child needs to
- print a message
- exit
So the code is as simple as
int main( void )
{
printf( "[dad] pid %d\n", getpid() );
for ( int i = 0; i < 3; i++ )
if ( fork() == 0 )
{
printf( "[son] pid %d from pid %d\n", getpid(), getppid() );
exit( 0 );
}
for ( int i = 0; i < 3; i++ )
wait( NULL );
}
which generates this output
[dad] pid 1777
[son] pid 1778 from pid 1777
[son] pid 1779 from pid 1777
[son] pid 1780 from pid 1777
The one thing you have to remember is that, when you fork, both the parent and child will continue on running the code at that point.
So, if you don't do child/parent detection correctly, the children will most likely start up their own children.
One good way for you to start up three children and no grandchildren is to use a counter in conjunction with the returned process ID from the fork call, along the lines of the following:
#include <stdio.h>
#include <unistd.h>
#define COUNT 3
int main(void) {
# Desired and actual count.
int count = COUNT, children = 0;
// Force parent initially.
pid_t retpid = 1;
// Only fork if limit not reached AND is parent (children
// will exit loop with retpid == 0).
while (count-- > 0 && retpid > 0)
// Adjust actual count if successful.
if ((retpid = fork()) > 0)
children++;
// Detect parent, all forks returned non-zero.
if (retpid != 0) {
printf("Parent %d spawned %d/%d children\n",
getpid(), children, COUNT);
// Wait for children to finish.
while (children-- > 0)
wait(NULL);
} else {
// Otherwise you were one of the children.
printf("Child %d, sired by %d\n", getpid(), getppid());
}
return 0;
}
This outputs what you seem to be after though, due to the vagaries of scheduling, not necessarily in that order:
Parent 26210 successfully spawned 3/3 children
Child 26212, sired by 26210
Child 26213, sired by 26210
Child 26211, sired by 26210
The checking of the returned PID will ensure only the parent does any forking, and the count will limit it to a specific quantity.
One thing you also need to watch out for is output buffering. When you fork, you may end up with two processes with buffered output data.
Where the output device can be detected to be a terminal, flushing will normally occur on a newline being output, so your printf calls probably won't duplicate output for a normal run.
You just need to be aware that you may get interesting results if you redirect your output to a file, for example.

Using fork() and execl() in a program to execute other C programs as processes

I am new using both fork() and exec() and I was trying to run three different processes from a C file called Fork.c so that I could execute the code within other three .c files. Each one of those c files would approximate the value of pi using different methods, but that's not important at all.
My main problem is basically not knowing how the execl() works when it comes to C files and I haven't found anything that could clarify my doubts here in stack overflow nor on the internet. So, I would like to make each child compute pi in a different way using the code in those three different files.
By now, what I have in my fork.c is the following:
for(i = 0; i < CHILDREN_N; i++)
{
pid = getpid();
pid = fork();
if (pid == 0) /* child process is always 0 */
{
//do something
printf("I am the child %d and my pid is %d \n", i, getpid());
execl();
exit(0);
}
else if (pid == -1) /*error*/
{
printf("Error ocurred.");
return 0;
}
else /* parent process is non-zero (child's pid) */
{
fprintf(stdout, "child pid = %d\n", pid);
fprintf(stdout, "waiting for child\n");
wait(NULL);
fprintf(stdout, "child terminated\n");
}
fprintf(stdout, "parent exiting\n");
}
So, I am not sure how to make that execl() execute the different pi approximation programs as different processes.
Hope I was clear enough and thanks.

Code (with fork) that shouldn't loop is looping

So I have the following C code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main(){
int i = 0, n;
n = 5;
pid_t pid;
printf("i=%d Right before the loop\n", i, getpid(), getppid());
for (i = 0; i < n; i++){
pid = fork();
if (pid <= 0){
printf("something happens in loop #%d. pid = %d\n", i, pid);
break;
}
printf("End of loop #%d\n", i);
}
printf("i=%d My process ID = %d and my parent's ID = %d\n", i, getpid(), getppid());
return 0;
}
I have only one question:
Why does
printf("i=%d My process ID = %d and my parent's ID = %d\n", i, getpid(), getppid());
get executed many times as if it was inside the loop? I have tried to figure out through so many ways but I cannot find the reason.
The reason is that fork() works by making a child process that is a copy of the parent that starts running at the fork() call. So every child process runs that printf command.
Example:
Here's a less complicated example:
#include <stdio.h>
int main(){
int pid = fork();
if (pid == 0){
// child code
printf("child pid: 0\n");
}else{
// parent code
printf("parent pid: %d\n", pid);
}
// executed by both
printf("This text brought to you by process %d.\n", pid);
}
You have to do something like this if you want to restrict some code to only be run by the child or parent.
On my machine, when I just ran it, it outputs:
parent pid: 12513
This text brought to you by process 12513.
child pid: 0
This text brought to you by process 0.
My operating system ran the parent process first, but it didn't have to.
If you are not aware of fork() and using it, it is dangerous.
This is one of the basic system calls in Linux used for creating a new process. Refer to Man page to know what it does. And here is one helpful link to make you understand better. fork().
To know more about it you could also refer here- fork() wiki. It uses methods like copy-on-write and shares the resources with child.
Once you have used fork() to create the new process, you can use exec(...) to change the program that the process is executing. After reading about each of them, you may refer to this post on so.

increase variable from within another block

I'm currently writing a simple C program to create a specified number of child-processes from the parent process, and I'm trying to keep track over how many of them that was actually successfully initiated by increasing the variable active every time a child-process was successful.
However, the stupid piece of #!%€ variable won't let me modify it.. I'm new to C (hence the simplicity and questionable usability of the program) and I'm having a bit of a problem understanding the different variable-scopes and when, and how you can modify them so that the new value sticks...
So, my questions is; how do I make the variable "active" increase by 1?
I've already made sure that the newChild() function returns 1 as it should, and other code within that if-statement works, so it's not that. And, I've also tried using pointers, but without success... :(
# include <stdio.h>
# include <unistd.h>
# include <stdlib.h>
# include <sys/wait.h>
main()
{
printf("Parent CREATED\nRunning code...\n");
// INITIATE Variables
int children = 5;
int active = 0;
int parentID = getpid();
// INITIATE Random Seed
srand(time(NULL));
// CREATE Children
int i, cpid, sleepTime;
for (i = 0; i < children; i++)
{
// Only let the parent process create new children
if (getpid() == parentID)
{
// GET Random Number
sleepTime = rand() % 10;
// CREATE Child
if (newChild(sleepTime) == 1)
{
// Mark as an active child process
active++;
}
}
}
// CLEAN UP
if (getpid() == parentID)
{
// Let the parent process sleep for a while...
printf("Parent is now SLEEPING for 20 seconds...\n");
sleep(20);
printf("Parent is now AWAKE\nActive children: %d\n", active);
// WAIT for Children
int cpid, i;
int status = 0;
for (i = 0; i < active; i++)
{
// WAIT for Child
cpid = wait(&status);
// OUTPUT Status
printf("WAITED for Child\nID: %d, Exit Status: %d\n", cpid, status);
}
printf("All children are accounted for.\nEXITING program...\n");
}
}
int newChild(int sleepTime)
{
// INITIATE Variable
int successful = 0;
// CREATE Child Process
int pid = fork();
if (pid == -1)
{
// OUTPUT Error Message
printf("The child process could not be initiated.");
}
else if (pid == 0)
{
// Mark child process as successfully initiated
successful = 1;
// OUTPUT Child Information
printf("Child CREATED\nID: %d, Parent ID: %d, Group: %d\n", getpid(), getppid(), getpgrp());
// Let the child process sleep for a while...
printf("Child %d is now SLEEPING for %d seconds...\n", getpid(), sleepTime);
sleep(sleepTime);
printf("Child %d is now AWAKE\n", getpid());
}
return successful;
}
There are three outcomes from calling fork() which your code is incorrectly condensing down to two:
A return value of -1 indicates that fork failed. This is an uncommon error condition.
A return value of 0 indicates that fork succeeded and you're now in the child process.
A return value of >0 indicates that fork succeeded and you're in the parent process.
Notice how cases 2 and 3 are both "successful". But your newChild() function returns 1 for case 2 and returns 0 for case 3. Instead what it should do is return 1 for case 3, and for case 2 it shouldn't even return. If you're in case 2 then you're in the child process and so you should just do your child process stuff and then exit, never returning to the caller.
if (pid == -1)
{
// OUTPUT Error Message
printf("The child process could not be initiated.");
}
else if (pid == 0)
{
// OUTPUT Child Information
printf("Child CREATED\nID: %d, Parent ID: %d, Group: %d\n", getpid(), getppid(), getpgrp());
// Let the child process sleep for a while...
printf("Child %d is now SLEEPING for %d seconds...\n", getpid(), sleepTime);
sleep(sleepTime);
printf("Child %d is now AWAKE\n", getpid());
// This is the child process, so we should NOT EVEN RETURN from newChild().
exit(0);
}
else
{
successful = 1;
}
The key observation here is that when you call fork() your process is going to split into two separate processes that both continue executing from the point where fork() returns. The difference between them is that one will get a 0 return value and the other will get a >0 return value. The former is the child and the latter is the parent.
After fork() you now have two copies of the same code running, with two separate invocations of newChild() running, and with two separate copies of the active variable. After forking there are two of everything.

Resources