LinuxQuestions.org
Share your knowledge at the LQ Wiki.
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices


Reply
  Search this Thread
Old 08-02-2011, 07:09 AM   #1
silentkill89
LQ Newbie
 
Registered: Aug 2011
Posts: 28

Rep: Reputation: Disabled
regarding fork() multiple process


stil a newbie,trying to fork multiple child but the program does not go as i want...
My code :
Code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>


int main()
{
pid_t pid[3];
int i;
 
for(i = 0; i < 3; i++)
{
pid[i]=fork();
if (pid[i] < 0)
{                                     /* Error Message */
printf("Child not created.\n");

}else if (pid[i] == 0)
{
printf("I am child %d,my pid %d,my parent's pid is %d\n",i, getpid(),getppid());

}else{
printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n",getppid(),i,getpid());

}
}
}
the output i wan is lik
Parent, my pid is 6461: Spawned child #1 whose pid is 6462
Parent, my pid is 6461: Spawned child #2 whose pid is 6463
I am child #1, my pid is 6462; my parent's pid is 6461
I am child #2, my pid is 6463; my parent's pid is 6461
I am child #3, my pid is 6464; my parent's pid is 6461
Parent, my pid is 6461: Spawned child #3 whose pid is 6464

but my output runs lik
Parent,my pid is 1907:Spawned child 0 whose pid is 2910
I am child 0,my pid 2911,my parent's pid is 2910
Parent,my pid is 1907:Spawned child 1 whose pid is 2910
Parent,my pid is 2910:Spawned child 1 whose pid is 2911
Parent,my pid is 1907:Spawned child 2 whose pid is 2910
Parent,my pid is 2910:Spawned child 2 whose pid is 2911
I am child 1,my pid 2913,my parent's pid is 1
Parent,my pid is 1:Spawned child 2 whose pid is 2913
sharina@ubuntu:~$ I am child 2,my pid 2916,my parent's pid is 1
I am child 2,my pid 2915,my parent's pid is 1
I am child 2,my pid 2914,my parent's pid is 1
I am child 1,my pid 2912,my parent's pid is 1
Parent,my pid is 1:Spawned child 2 whose pid is 2912
I am child 2,my pid 2917,my parent's pid is 1

can anyone point out the logic?
thx in advance..
 
Old 08-02-2011, 07:37 AM   #2
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
Quote:
Originally Posted by silentkill89 View Post
stil a newbie
Next time indent the code you post to make it more readable and spell out more of the words in your question to make it more readable.

We are able to read stil, wan, lik, and thx. But that style is discouraged here and next time might result in significantly delaying the useful answers.

This time, your main bug seems to be that you didn't put in a break statement after printing that the code is executing in the child.

The output you say you want seems to assume that only the original parent will continue through the loop forking more children. But as you coded it, each process (parent or child) independently continues through the loop.

But you also have several errors in the values you are printing and/or misunderstandings of the meanings of getpid() and getppid(). For example:
Quote:
printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n",getppid(),i,getpid());
getpid and getppid are always from the point of view of the code that is executing (not from the point of view of some fork it might have recently executed). So in that code you say "my pid is" getppid(), but that is the pid of the current process's parent. The current process is the parent side of the fork you are reporting, so its parent is the grandparent from the point of view of the fork.

Then you say "Spawned child" i, but i is 0 to 2 representing positions in the pid[] array, and you say you want 1 based reporting, which would be "Spawned child" i+1.

Then you say "whose pid is" getpid() but that is the current process pid, which is the parent from the point of view of the last fork. You should have "whose pid is" pid[i]

Last edited by johnsfine; 08-02-2011 at 07:51 AM.
 
Old 08-02-2011, 07:42 AM   #3
silentkill89
LQ Newbie
 
Registered: Aug 2011
Posts: 28

Original Poster
Rep: Reputation: Disabled
sory...my bad,1st time posting this forum. i will make it more readable next time. May i know how to exit the condition? i know is using exit(-1) or exit(1), but i tried before and when i compile it gets an error of using the exit() status.sorry im still a newbie..
 
Old 08-02-2011, 07:55 AM   #4
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
Quote:
Originally Posted by silentkill89 View Post
May i know how to exit the condition? i know is using exit(-1) or exit(1), but i tried before and when i compile it gets an error of using the exit() status.
I would have used a break instruction (as I suggested above) to exit the loop after printing the child message. Since the loop is the whole program, exiting the loop is equal to exiting the program.

But if you prefer to use the exit() function, that is also good.

exit() is declared in stdlib.h, so if you want to use exit() you need
#include <stdlib.h>

Corrected code (using break) is
Code:
#include <stdio.h>
#include <sys/types.h>

int main()
{
   pid_t pid[3];
   int i;
 
   for(i = 0; i < 3; i++)
   {
      pid[i]=fork();
      if (pid[i] < 0)
      {                                     /* Error Message */
         printf("Child not created.\n");
      }else if (pid[i] == 0)
      {
         printf("I am child %d,my pid %d,my parent's pid is %d\n",i+1, getpid(),getppid());
         break;
      }else{
         printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n",getpid(),i+1,pid[i]);
      }
   }
}

Last edited by johnsfine; 08-02-2011 at 08:01 AM.
 
Old 08-02-2011, 10:41 AM   #5
silentkill89
LQ Newbie
 
Registered: Aug 2011
Posts: 28

Original Poster
Rep: Reputation: Disabled
thanks to you johnsfine, somehow i managed i get some idea, now i understand much about the logic. According the code,I dun understand this part
Code:
printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n",getpid(),i+1,pid[i]);
the first %d, aren't we suppose to put get parent system call,which is getppid()? I though should have called parent pid, kindly explain the logic flow. Thanks in advanced.

Last edited by silentkill89; 08-02-2011 at 11:32 AM.
 
Old 08-02-2011, 11:46 AM   #6
silentkill89
LQ Newbie
 
Registered: Aug 2011
Posts: 28

Original Poster
Rep: Reputation: Disabled
alright, after been thinking awhile, I finally how it works, thanks johnfine. Now I know parent can only call getpid() because it stand for the process id itself instead of parent,because parent only have 1, however child has a parent pid and its own pid, so 2 system call. Thousand thanks^^
 
Old 08-02-2011, 11:47 AM   #7
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
Quote:
Originally Posted by johnsfine View Post
getpid and getppid are always from the point of view of the code that is executing (not from the point of view of some fork it might have recently executed). So in that code you say "my pid is" getppid(), but that is the pid of the current process's parent. The current process is the parent side of the fork you are reporting, so its parent is the grandparent from the point of view of the fork.
Quote:
Originally Posted by silentkill89 View Post
According the code,I dun understand this part
Code:
printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n",getpid(),i+1,pid[i]);
the first %d, aren't we suppose to put get parent system call,which is getppid()? I though should have called parent pid, kindly explain the logic flow.
I don't have any better explanation than the one I already gave above.
 
Old 08-02-2011, 12:04 PM   #8
silentkill89
LQ Newbie
 
Registered: Aug 2011
Posts: 28

Original Poster
Rep: Reputation: Disabled
OK.But I got 1 last problem, the output show
Code:
Parent,my pid is 8602:Spawned child 1 whose pid is 8603
I am child 1,my pid 8603,my parent's pid is 8602
Parent,my pid is 8602:Spawned child 2 whose pid is 8604
Parent,my pid is 8602:Spawned child 3 whose pid is 8605
I am child 2,my pid 8604,my parent's pid is 8602
I am child 3,my pid 8605,my parent's pid is 1
All works fine except the last line
Code:
I am child 3,my pid 8605,my parent's pid is 1
the parent's pid suppose to be 8602 instead 1. Any idea?
 
Old 08-02-2011, 01:28 PM   #9
GazL
Senior Member
 
Registered: May 2008
Posts: 4,369
Blog Entries: 7

Rep: Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815
Quote:
Originally Posted by silentkill89 View Post
the parent's pid suppose to be 8602 instead 1. Any idea?
My guess is that the parent process is ending before the 3rd child gets up and running, by which time the child has been inherited by init (PID 1)

Have a read of the man-page for wait() There's an example program at the end which should help.
 
Old 08-02-2011, 01:30 PM   #10
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
Quote:
Originally Posted by silentkill89 View Post
All works fine except the last line
Code:
I am child 3,my pid 8605,my parent's pid is 1
the parent's pid suppose to be 8602 instead 1. Any idea?
Easy to understand, a bit harder to fix well.

You get that behavior because parent process exits before the child process asks the system for the identity of its parent.

getppid() is giving you the pid of the parent at the moment getppid() is called, not the original parent. If the original parent is gone then getppid() returns 1.
 
Old 08-03-2011, 12:01 AM   #11
silentkill89
LQ Newbie
 
Registered: Aug 2011
Posts: 28

Original Poster
Rep: Reputation: Disabled
Ok, i understand what's the problem. But when i change
Code:
i <= 3
it will ends up in an unstoppable loop, so possibly I will try to put a wait() system call inside to see how it goes, or is there anyway to issue the parent process to exit after it's pid display or just only using wait()?
 
Old 08-03-2011, 07:27 AM   #12
GazL
Senior Member
 
Registered: May 2008
Posts: 4,369
Blog Entries: 7

Rep: Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815
Changing the conditional from '<' to '<=' really doesn't have any relevance to the problem you're seeing.

You can change your approach and pass the parents pid across the fork() instead of letting each child call getppid()
Code:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>

int main()
{
   pid_t pid[3];
   pid_t forkedby, mypid;
   int i;
 
   forkedby = mypid = getpid();
    
   for(i = 0; i < 3; i++)
   {
      pid[i]=fork();
      if (pid[i] < 0)
      {                                     /* Error Message */
         printf("Child not created.\n");
      }else if (pid[i] == 0)
      {
         mypid=getpid();
         printf("I am child %d,my pid %d,my parent's pid is %d\n", i+1, mypid, forkedby);
         break;
      }else{      
         printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n", mypid, i+1, pid[i]);
      }
   }
   return 0;
}
or you can keep the parent alive and let it manage its children with wait():
Code:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

#define NUM_CHILDREN 3

int main()
{
   pid_t pid[NUM_CHILDREN];
   pid_t wait_pid;
   int i;
   int status;
 
   for(i = 0; i < NUM_CHILDREN ; i++)
   {
      pid[i]=fork();
      if (pid[i] < 0)
      {                                     /* Error Message */
         printf("Child not created.\n");
      }else if (pid[i] == 0)
      {
         printf("I am child %d,my pid %d,my parent's pid is %d\n",i+1, getpid(),getppid());
         break;
      }else{
         printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n",getpid(),i+1,pid[i]);
         if ( i == (NUM_CHILDREN - 1) ) {
           for ( errno=0 , wait_pid=0 ; wait_pid != -1 ; errno=0 ) {
             wait_pid=wait(&status);
             if (errno == ECHILD)
               printf("Parent, all children have finished.\n");
             else if ( WIFEXITED(status) )
               printf("Parent, child %d has exited...\n", wait_pid);
           }
         } 
      }
   }

   return 0;
}
... which is obviously more involved.

Last edited by GazL; 08-03-2011 at 07:27 AM. Reason: spelling
 
1 members found this post helpful.
Old 08-03-2011, 07:46 AM   #13
silentkill89
LQ Newbie
 
Registered: Aug 2011
Posts: 28

Original Poster
Rep: Reputation: Disabled
Quote:
Originally Posted by GazL View Post
Changing the conditional from '<' to '<=' really doesn't have any relevance to the problem you're seeing.

You can change your approach and pass the parents pid across the fork() instead of letting each child call getppid()
Code:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>

int main()
{
   pid_t pid[3];
   pid_t forkedby, mypid;
   int i;
 
   forkedby = mypid = getpid();

    
   for(i = 0; i < 3; i++)
   {
      pid[i]=fork();
      if (pid[i] < 0)
      {                                     /* Error Message */
         printf("Child not created.\n");
      }else if (pid[i] == 0)
      {
         mypid=getpid();
         printf("I am child %d,my pid %d,my parent's pid is %d\n", i+1, mypid, forkedby);
         break;
      }else{      
         printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n", mypid, i+1, pid[i]);
      }
   }
   return 0;
}
or you can keep the parent alive and let it manage its children with wait():
Code:
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>

#define NUM_CHILDREN 3

int main()
{
   pid_t pid[NUM_CHILDREN];
   pid_t wait_pid;
   int i;
   int status;
 
   for(i = 0; i < NUM_CHILDREN ; i++)
   {
      pid[i]=fork();
      if (pid[i] < 0)
      {                                     /* Error Message */
         printf("Child not created.\n");
      }else if (pid[i] == 0)
      {
         printf("I am child %d,my pid %d,my parent's pid is %d\n",i+1, getpid(),getppid());
         break;
      }else{
         printf("Parent,my pid is %d:Spawned child %d whose pid is %d\n",getpid(),i+1,pid[i]);
         if ( i == (NUM_CHILDREN - 1) ) {
           for ( errno=0 , wait_pid=0 ; wait_pid != -1 ; errno=0 ) {
             wait_pid=wait(&status);
             if (errno == ECHILD)
               printf("Parent, all children have finished.\n");
             else if ( WIFEXITED(status) )
               printf("Parent, child %d has exited...\n", wait_pid);
           }
         } 
      }
   }

   return 0;
}
... which is obviously more involved.
wow...i guess first idea make more simple and directive. However the second idea just having parent to finish their job,which is more efficient. Thanks in advance GAZL. By the way, at the 2nd idea where
Code:
else if ( WIFEXITED(status) )
statement, WIFEXITED is a reserved word for <sys/wait.h> library or just normal initialization?
 
Old 08-03-2011, 07:52 AM   #14
GazL
Senior Member
 
Registered: May 2008
Posts: 4,369
Blog Entries: 7

Rep: Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815Reputation: 1815
It's a macro from wait.h provided to be used with the wait() call. It's all on the man-page.
 
Old 08-03-2011, 07:55 AM   #15
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
Quote:
Originally Posted by silentkill89 View Post
WIFEXITED is a reserved word for <sys/wait.h> library or just normal initialization?
You could have gotten the answer to that faster with google than by asking in the forum.

google WIFEXITED and many of the hits are online copies of
man 3 wait
such as the one at:
http://linux.die.net/man/3/wait

In that man page you can find the description of WIFEXITED

Code:
the following macros, which are defined in <sys/wait.h>
...
WIFEXITED(stat_val)

    Evaluates to a non-zero value if status was returned for a child process that terminated normally.
Quote:
Originally Posted by GazL View Post
Have a read of the man-page for wait()
The OP might not have known that the command to get that man page is
man 3 wait
Or the OP might not have that man page installed on his Linux system (I don't have it on any of my Linux systems. Not sure why. Most man 3 pages I've tried are there.)

When missing a man page, google (to find an online copy of the man page) is usually faster than finding out what package you need to install.

Last edited by johnsfine; 08-03-2011 at 08:04 AM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
process using fork punit_beriwal Programming 5 03-22-2011 03:08 AM
Change in Process Id after fork sankumar Programming 1 12-24-2008 03:20 AM
Create a process using fork()? Ashkan_s Programming 5 08-22-2008 11:46 AM
how to fork a process? Punker99 Programming 2 07-28-2003 11:21 AM
fork() by Process 0 Manish Programming 0 02-23-2002 05:03 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 05:25 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration