Reputation: 21
I wish to create a sequential process that will create a specified number of children. For example if parent process ID is 769 the process will be as follows:
769(parent) -> 770(first child) -> 771(grand child) ... -> xx (n*grand child)
based on the number of children I want. PID of the children doesn't matter as long as they are sequential and have no siblings.
int main(int argc, char **argv) {
int i;
int iterations;
if (argc != 2) {
fprintf(stderr, "Usage: forkloop <iterations>\n");
exit(1);
}
iterations = strtol(argv[1], NULL, 10);
int n = fork();
for (i = 0; i < iterations; i++) {
if(n == 0) {
printf("ppid = %d, pid = %d, i = %d\n", getppid(), getpid(), i);
n = fork();
}
if (n < 0) {
perror("fork");
exit(1);
}
//printf("ppid = %d, pid = %d, i = %d\n", getppid(), getpid(), i);
}
// printf("ppid = %d, pid = %d\n", getppid(), getpid());
return 0;
}
I have made this but I believe this is a bit wrong. Could anyone help out?
Upvotes: 0
Views: 1053
Reputation: 753515
Think through the logic carefully. You're close, but need to get closer. This works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char **argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: forkloop <iterations>\n");
exit(1);
}
int iterations = strtol(argv[1], NULL, 10);
if (iterations < 1 || iterations > 20)
{
fprintf(stderr, "invalid iterations %d (1..20 allowed)\n", iterations);
exit(1);
}
printf("Initial process: PID %d (parent %d)\n", (int)getpid(), (int)getppid());
fflush(stdout);
int i;
for (i = 0; i < iterations; i++)
{
int pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
else if (pid == 0)
{
/* Child - report ID */
printf("ppid = %d, pid = %d, i = %d\n", getppid(), getpid(), i);
fflush(stdout);
}
if (pid != 0)
{
/* Parent - break loop and wait for kid (and grandkid, and ...) to die */
break;
}
}
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
{
printf("PID %d: child %d exited with status 0x%.4X\n",
(int)getpid(), corpse, status);
fflush(stdout);
}
return i;
}
(There's no guarantee that pid_t
returned by getpid()
et al is actually an int
, though it is normally equivalent. I added the casts to ensure there is no problem, though in practice you can get away without them. The last fflush()
is not strictly needed; the process exits which flushes the output anyway. The earlier ones are a good idea; you could get confusing output if they were absent and the output of the program was piped to some process to capture it. Before you fork()
, it's a good idea to have no pending output — so fflush(0)
aka fflush(NULL)
is perhaps a good idea, in general, though here it isn't necessary.)
Sample outputs (source code kids17.c
, program name kids17
):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes \
> -Wstrict-prototypes kids17.c -o kids17
$ kids17
Usage: forkloop <iterations>
$ kids17 4
Initial process: PID 2686 (parent 888)
ppid = 2686, pid = 2687, i = 0
ppid = 2687, pid = 2688, i = 1
ppid = 2688, pid = 2689, i = 2
ppid = 2689, pid = 2690, i = 3
PID 2689: child 2690 exited with status 0x0400
PID 2688: child 2689 exited with status 0x0300
PID 2687: child 2688 exited with status 0x0200
PID 2686: child 2687 exited with status 0x0100
$ …some work done…
$ kids17 10
Initial process: PID 2704 (parent 888)
ppid = 2704, pid = 2705, i = 0
ppid = 2705, pid = 2706, i = 1
ppid = 2706, pid = 2707, i = 2
ppid = 2707, pid = 2708, i = 3
ppid = 2708, pid = 2709, i = 4
ppid = 2709, pid = 2710, i = 5
ppid = 2710, pid = 2711, i = 6
ppid = 2711, pid = 2712, i = 7
ppid = 2712, pid = 2713, i = 8
ppid = 2713, pid = 2714, i = 9
PID 2713: child 2714 exited with status 0x0A00
PID 2712: child 2713 exited with status 0x0900
PID 2711: child 2712 exited with status 0x0800
PID 2710: child 2711 exited with status 0x0700
PID 2709: child 2710 exited with status 0x0600
PID 2708: child 2709 exited with status 0x0500
PID 2707: child 2708 exited with status 0x0400
PID 2706: child 2707 exited with status 0x0300
PID 2705: child 2706 exited with status 0x0200
PID 2704: child 2705 exited with status 0x0100
$
I didn't have any other processes actively spawning child processes while I was running this testing.
Upvotes: 1