Linux - NewbieThis 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
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
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
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]
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..
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]);
}
}
}
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.
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^^
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
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.
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?
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.
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()?
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?
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
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.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.