Reputation: 319
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.
Upvotes: 0
Views: 6551
Reputation: 1
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 processfork
gave a positive pid_t
, you are in the parent processfork
failed and gave -1People (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.
Upvotes: 3
Reputation: 4044
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");
}
}
}
}
Upvotes: 2
Reputation: 11
To make 2 child you call fork()2x. So call fork with 2 different variable and then wait for them both.
Upvotes: -1