I'm taking an intro to C course and I've become a bit stumped on the first assignment. We've been tasked with creating a parent processes and two child processes. All of the examples the text has shown us so far involve switch statements with one parent and one child. I'm a bit confused about how to translate this into one parent and two child processes. Here is what I have so far:
#include <stdio.h>
int main() {
int i, pid, status;
pid = fork();
switch(pid) {
case -1:
/* An error has occurred */
printf("Fork Error");
break;
case 0:
/* This code is executed by the first parent */
printf("First child process is born, my pid is %d\n", getpid());
printf("First child parent process is %d\n", getppid());
for (i=1; i<=10; i++)
printf("First child process, iteration: %d\n", i);
printf("First child dies quietly.\n");
break;
default:
/* This code is executed by the parent process */
printf("Parent process is born, my pid is %d\n", getpid());
wait(&status);
printf("Parent process dies quietly.\n");
}
}
This works perfect for this one process:
Parent process is born, my pid is 10850
First child process is born, my pid is 10851
First child parent process is 10850
First child process, iteration: 1
First child process, iteration: 2
First child process, iteration: 3
First child process, iteration: 4
First child process, iteration: 5
First child process, iteration: 6
First child process, iteration: 7
First child process, iteration: 8
First child process, iteration: 9
First child process, iteration: 10
First child dies quietly.
Parent process dies quietly.
Essentially I just need to do the same thing with a second process... something like:
printf("Second child process is born, my pid is %d\n", getpid());
printf("Second child parent process is %d\n", getppid());
for (k=1; k<=10; k++)
printf("Second child process, iteration: %d\n", i);
printf("Second child dies quietly.\n");
break;
But I'm just not sure how to get there from what I have so far. Am I approaching this correct way? Is there a better method I should be using? Thanks so much.
There is a general rule. When you use fork(2) you should always handle the three cases below:
fork gave 0, you are in the child process
fork gave a positive pid_t, you are in the parent process
fork failed and gave -1
People (newbies) sometimes tend to forget the last (failure) case. But it does happen, and you might easily test that case by using setrlimit(2) with RLIMIT_NPROC in your grand-parent process to lower the limit on processes, often that grand-parent process is your shell (e.g. using ulimit Bash builtin with -u).
Now, how to handle the three cases is a matter of coding style. You can use switch but you can use two if. Your code uses a switch and is right to do so.
As a general rule, most system calls (listed in syscalls(2)) can fail, and you almost always need to handle the failure case (see errno(3) and use perror(3)).
Read also Advanced Linux Programming (freely downloadable).
I'm a bit confused about how to translate this into one parent and two child processes.
The fork system call is creating (on success) exactly one child process. So if you need two children, you should call it twice (and test failure on both calls) in a row. If you need one child and one grand child, you should do the second fork only when the first one gave 0. Of course you need to keep both (successful and positive) pid_t -e.g. in two variables- returned by your two calls to fork.
To avoid zombie processes, every successful fork should later have its wait system call (e.g. waitpid(2) or wait or wait4(2) or wait3). Where you do that wait depends if you want to have both children running at the same time or not. But every successful fork should have a corresponding successful wait call.
Read also signal(7) (and signal-safety(7)) about SIGCHLD if you want to be asynchronously notified about child processes change - notably termination. A common way is to install a SIGCHLD signal handler (e.g. using sigaction(2) or the old signal(2)) which just sets some global volatile sigatomic_t flag and test then clear that flag in convenient place in your code (e.g. in some event loop using poll(2)).
NB: notice that fork is not about C programming (fork is not defined in the C11 standard n1570 or its predecessor C99). It is a POSIX and Linux thing. Windows or z/OS or an Arduino microcontroller don't have it natively, but are programmable in some standard C.
You can put fork and switch case in loop so that it forks multiple processes, something like below:
Edit: You can remove if condition to call wait after each fork, alternately if you want to launch all children then wait for them to terminate, in each iteration you can collect pid of each child (in parent process ie in default switch case) in an array and in last iteration call waitpid in a loop(for each pid) to ensure each child process has exited
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
int main() {
int i, pid, status;
int j = 0;
int numChildren = 2;/*Change it to fork any number of children*/
for(j = 0;j< numChildren;j++)
{
pid = fork();
switch(pid) {
case -1:
/* An error has occurred */
printf("Fork Error");
break;
case 0:
/* This code is executed by the first parent */
printf("First child process is born, my pid is %d\n", getpid());
printf("First child parent process is %d\n", getppid());
for (i=1; i<=10; i++)
printf("First child process, iteration: %d\n", i);
printf("First child dies quietly.\n");
exit(0);/*Otherwise it will fork its own child*/
break;
default:
/* This code is executed by the parent process */
printf("Parent process is born, my pid is %d\n", getpid());
if(j == (numChildren - 1))/*You can remove this condition to wait after each fork*/
{
wait(&status);
printf("Parent process dies quietly.\n");
}
}
}
}
To make 2 child you call fork()2x. So call fork with 2 different variable and then wait for them both.
Related
I'm trying to write a c program that create N-parent process with their children, but what happens instead is that I create several child processes that are linked to a parent. I need help changing the code to create as many parents as children. In addition, the program will await all child processes. Thanks for your help! Below u see my code that which certainly needs to be changed.
int main(void)
{
pid_t pid;
int i, N=0;
scanf("%d", &N);
for(i=0;i<N;i++)
{
pid = fork();
switch(pid) {
case -1:
fprintf(stderr,"fork failed");
exit (1);
case 0:
printf("I am the child with pid = %d\n",getpid());
printf("My parent has pid = %d\n", getppid());
sleep (20);
exit(0);
default:
wait (0);
}
}
return 0;
}
You are missing is the basic understanding of parent and child processes. I will try to help with that and I am sure you will be able to correct your program yourself.
Except "init" process every process has a parent. You want to create N parent process but those N processes will have to have a parent until they are not "init" process and also you can not have more than one "init" process.
In your case "main" should be the parent, of your N parent processes(which are nothing but the children of "main" process) and then these N parent processes can have their children processes.
I hope this information helps. Happy Coding :)
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
printf("pid : %d\n", getpid());
if( pid == 0)
{
printf("child: pid : %d \n", getpid());
while(1);
}
else
{
printf("parent: pid : %d \n", getpid());
//while(1);
}
}
In the above code snippet inside if statement if we put while(1), it doesn't remains blocked and when enter key is pressed program is exited, but in case of parent if we put while(1), parent remains blocked until we give ctrl+c. Please clarify this behaviour of child.
In the above code snippet inside if statement if we put while(1), it doesn't remains blocked
The child process doesn't exit actually; it just becomes an orphan process because its parent exits. The orphaned chuld process will be adopted by the init process of your system. You can see it via ps command.
But if you put the while(1); in the parent process it remains blocked.
Basically whichever process has while(1); infinite loop, it's still running. When parent exits you get the prompt back and the child becomes orphan. But the child process is still running.
In general, you need to wait(2) for the child process in the parent process to reap child processes.
I have a small program written in C on linux. It's purpose is to examine the behaviour of the fork() call and the resulting child processes
Upon first inspection everything seems simple enough. However
Sometimes output is written in a funny order
Sometimes the child PPID is '1' not whatever the parent PID is.
I can't find any pattern or correlation between when it works as expected and when it does not.
I think that point 2. is probably caused by the parent process dying before the child process has executed fully. If so, is there a way to stop this from happening.
However I have no idea what is causing point 1.
Code below:
#include <stdio.h>
#include <unistd.h>
int main()
{
int x = fork();
if (x == 0)
{
printf("Child:");
printf ("\nChild PID : %d", getpid());
printf ("\nChild PPID: %d", getppid());
printf("\nHello Child World\n");
}
if (x != 0)
{
printf("Parent :");
printf ("\nParent PID : %d", getpid());
printf ("\nParent PPID: %d", getppid());
printf("\nHello Parent World\n");
}
return 0;
}
this behaviour is seen because of scheduling policy of operating system. if you are aware of process management concepts of os, then if your parent code is running and fork() is encountered, child is created, but if within that time, parent's time slice has not been completed, then parent continues running and if within its time slice, parent executes and terminates, then child becomes orphan precess and after parent process' time slice completes, child's execution starts, thats why getppid() function returns 1, because child is an orphan process and it it now adopted by init process which starts first when operating system boots and is having process id 1.
Explanation of Behaviour 1:
The order of output cannot be controlled by the program normally. That's the point of parallel process. The OS decides which process to execute at any point of time and both processes are executed simultaneously (to the human eye).
Thus the output would generally be inter-tweened.
Explanation of Behaviour 2:
You guessed that right.
The parent process has finished before the forked one.
If you want the parent pid, you can use waitpid(x, &status, 0) in the parent process if you need the parent to stay alive till child execution. This link may help you.
Since each process is doing its own thing, which to me feels more like a "brothers/sisters" relationship. Is there a specific reason behind calling them parent process and child process?
Also, is it true that the parent process always run before the child process?
The parent owns the process group and thus spawns and reaps the children. Usually this process does a little bit of administrative work, while the children act as peers and siblings.
The naming is just convention for describing which process spawned the other, though.
The parent process and child process does the work based on your code but not because of parent or child relationship. When you execute fork() in the main thread it will create a child process, here the fork returns a value which is different in parent process and child process which can be used to differentiate the work of parent and child processes accordingly.
fork() always return pid of child in parent process and 0 in child process.
Coming to your second question it always depends on the scheduler as soon as the fork() is called and we cannot predict which process gets to run first after fork() function call.
Is there a specific reason behind calling them parent process and child process?
Well, since it one process (the parent) that creates the second one (the child), that might be the reasoning for the naming.
Also, is it true that the parent process always run before the child process?
The short answer. Nope.
I have been using this in all of my C-code
pid_t pid = fork();
if(pid == 0){ // child
// Child stuff
}else{ // parent
// Parent stuff
}
You might also want to use the
waitpid(pid, NULL, 0);
Parents are always before child. Sort and sweet!!!
fork() creates a copy of the current process which is a part of the process control group. The new process is subordinate to the originating process, for example when a child process dies, SIGCHLD is sent to the parent. Also, the clone is an inferior copy: for instance, any stored getpid() results will be inaccurate in the child; the child has a different parentid, the child has copies of the parent's file descriptors, and has independent resource usage counters.
The parent process, then, is always the one that made the call to fork(), if that's what you mean by run first. If you mean "will the scheduler always give the parent process slices first" then the answer is no.
See: http://gauss.ececs.uc.edu/Courses/c694/lectures/ForksThreads/forks.html, http://linux.die.net/man/2/fork
#include <stdio.h>
#include <unistd.h>
int main(int argc, const char* argv[])
{
pid_t otherPid;
printf("parent pid = %u\n", getpid());
otherPid = fork();
// in the parent, otherPid = the child's (new) process ID
// in the child, otherPid = 0.
switch (otherPid) {
case -1:
printf("Fork failed: %d\n", errno);
return errno;
break;
case 0: // child
sleep(2);
printf("child: my pid is %u\n", getpid());
break;
default:
printf("parent: pid is %u, child should have %u\n", getpid(), otherPid);
sleep(3);
break;
}
return 0;
}
Can someone please explain to me what does fork() != 0 mean? From what I understand I think it means if fork is not false? Or if fork is true then.... I don't understand how Fork() can be true or false, seeing that it just creates a copy of a process into a parent and child. Also if a program where to say if (Fork() == 0) what would that mean?
#include "csapp.h"
int main(void)
{
int x = 3;
if (Fork() != 0)
printf("x=%d\n", ++x);
printf("x=%d\n", --x);
exit(0);
}
fork() returns -1 if it fails, and if it succeeds, it returns the forked child's pid in the parent, and 0 in the child. So if (fork() != 0) tests whether it's the parent process.
From man fork
Return Value
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
Assuming success, fork returns twice: once in the parent, and once in the child.
OK, I did the OP a disservice: I don't know where csapp.h comes from, but if it's this one then it isn't doing you any favours. I guess it is a thin wrapper on POSIX (eg. around fork()), but maybe works on other platforms too?
Because you mentioned fork() before Fork(), I assumed the latter was a typo, whereas it's actually a library function.
If you had been using fork() directly, it would be reasonable to expect you to check the manpage.
Since you're using a Fork() function provided by some library, that library really ought to document it, and doesn't seem to.
Standard (non csapp) usage is:
pid_t child = fork();
if (child == -1) {
printf("fork failed - %d - %s\n", errno, strerror(errno));
exit(-1);
}
if (child) {
printf("I have a child with pid %d, so I must be the parent!\n", child);
} else {
printf("I don't have a child ... so I must be the child!\n")
}
exit(0);
Let's try explaining it differently... When the function starts there's 1 process, this process has a int x = 3
Once you hit this line of code:
if (fork() != 0)
Now, assuming the fork() worked, we have two processes. They both have the same execution space, they both are going to run the same code (to a point), but the child will get its own copy of x to play with.
fork() will return a 0 to the child process, so from the child processes' prospective, the rest of the function is this:
printf(("x=%d\n", --x);
exit(0);
The parent process on the other hand, will get a valid value back from the fork() command, thus it will execute:
printf("x=%d\n", ++x);
printf("x=%d\n", --x);
exit(0);
What the output at this point will be is anyone's guess... You can't tell if parent or child will run first
But if we assume the parent hits the ++x is the next operation then the output is:
x=4
x=3
x=2
As both parent and child will hit the --x. (the parent's x was 4 after the ++x, will be 3 at the end. The child's x was 3, will be 2 at the end)
From fork() manual:
Upon successful completion, fork() returns a value of 0 to the child process and returns the process ID of the child process to the parent
process. Otherwise, a value of -1 is returned to the parent process, no child process is created, and the global variable errno is set to indi-
cate the error.
After the code execution you have two execution threads. Into the if statement you have the parent process' thread and in else statement you have the child process' thread.
if ( fork() ) {
printf("I am the parent!\n");
} else {
printf("I am the child\n");
}
EDIT
For clarification purpose: fork starts a process, which has a thread, memory and may have other resources. I tried (it seems like that without success) to emphasize the flows of execution by adding the "thread" word.
However, by no means, one can say that "parent" relates to "thread" in "parent process' thread".
Of course, my answer could be improved but I think there are already enough good answers here.
Fork returns 0 for the child process and the process id of the child to the parent process. Hence commonly code has if(fork){ }else code. Which implies that the code inside the if is going to be executed only in a parent.
The better way to deal with it is
pid = fork()
if(pid){
// I am parent. Let us do something that only the parent has to do
}else{
// I am child. Let us do something only the child has to do
}
// This code is common to both
The child pid may be useful to wait upon later or to detach from the parent.
I recommend replacing the if with a switch because there are 3 possible results:
#include <sys/types.h>
#include <unistd.h>
pid_t pid;
switch ((pid = fork ())) {
case -1: /* error creating child. */
break;
case 0: /* I am the child process. */
break;
default: /* I am the parent process. */
break;
}