I'm trying to create the process tree shown in the picture. Basically if the level is even I want to create one child process and terminate the parent process. If the level is odd I wanna create two child processes and then terminate the parent process. I have written a program right now but I think it's so hard to visualize what process tree my program is actually creating. I've written some comments to the code to explain how I've been thinking. I also want to output the PID of the bottom children of the tree which my code doesn't do correctly.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char *argv[]){
pid_t pid, ppid;
int n, i;
int childstate;
int count = 0;
if(argc != 2){
printf("Wrong number of arguments");
exit(-1);
}
n = atoi(argv[1]);
fork(); //start process 0
for(i = 1; i < n + 1; i++){
if(i % 2 != 0){
fork(); //if odd level start 1 child process
if(getpid() == 0){
kill (getppid(), 9); //terminate parent process
}
} else {
if(fork() > 0){ //start new process
fork(); //if new process is not a child start another process
if(getpid() == 0){
kill (getppid(), 9); //terminate parent process
}
}
}
if(i == n){ //print pid of leaves (not working correctly)
printf("Process: %d \n", getpid());
}
}
return 0;
}
I also want to output the PID of the bottom children of the tree which my code doesn't do correctly.
Have your processes output the tree in Dot language, and use Graphviz to output the tree.
For example, if you save the following as say tree.c:
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
int process(const unsigned int level, const unsigned int maxlevel, FILE *dot)
{
int status = EXIT_SUCCESS, childstatus;
unsigned int children, i;
pid_t p, child[2];
if (dot) {
/* Output a node for this child, */
fprintf(dot, " \"%ld\" [ label=\"Process %ld\" ];\n", (long)getpid(), (long)getpid());
/* and if not at the top level (0), an edge from our parent. */
if (level)
fprintf(dot, " \"%ld\" -> \"%ld\";\n", (long)getppid(), (long)getpid());
fflush(dot);
}
/* No more forking? */
if (level >= maxlevel) {
if (level)
exit(status);
else
return status;
}
/* Odd levels create two child processes, even one. */
if (level & 1)
children = 2;
else
children = 1;
/* Fork the child processes, */
for (i = 0; i < children; i++) {
child[i] = fork();
if (child[i] == -1) {
fprintf(stderr, "Cannot fork: %s.\n", strerror(errno));
exit(EXIT_FAILURE);
} else
if (!child[i]) {
/* have each child run process() and nothing else, */
exit(process(level + 1, maxlevel, dot));
}
/* This line is run in parent only. */
}
/* and wait for them. */
for (i = 0; i < children; i++) {
if (child[i] != -1) {
do {
p = waitpid(child[i], &childstatus, 0);
} while (p == -1 && errno == EINTR);
if (p != child[i])
status = EXIT_FAILURE;
} else
status = EXIT_FAILURE;
}
if (level)
exit(status);
else
return status;
}
int dot_process_tree(const int levels, FILE *out)
{
int retval = EXIT_SUCCESS;
if (out) {
fprintf(out, "digraph {\n");
fflush(out);
}
if (levels > 0)
retval = process(0, levels - 1, out);
if (out) {
fprintf(out, "}\n");
fflush(out);
}
return retval;
}
int main(void)
{
return dot_process_tree(5, stdout);
}
and compile and run it using
reset ; gcc -Wall -Wextra -O2 tree.c -o tree && ./tree | dot -Tx11
you'll get a nice graphic process tree. (Use dot -Tsvg > out.svg or dot -Tpng > out.png to save it as an SVG or PNG image.) On my system:
Do note that there is no reason why the process IDs should be in the tree order. Although e.g. Linux hands them off in a rather ordered fashion, they can be in any order, even totally random. So do not make any assumptions on the PIDs.
The Dot language itself is simple. The output of the above program is something like
digraph {
"12375" [ label="Process 12375" ];
"12377" [ label="Process 12377" ];
"12375" -> "12377";
"12378" [ label="Process 12378" ];
"12377" -> "12378";
"12379" [ label="Process 12379" ];
"12377" -> "12379";
"12380" [ label="Process 12380" ];
"12378" -> "12380";
"12381" [ label="Process 12381" ];
"12379" -> "12381";
"12382" [ label="Process 12382" ];
"12380" -> "12382";
"12384" [ label="Process 12384" ];
"12381" -> "12384";
"12383" [ label="Process 12383" ];
"12380" -> "12383";
"12385" [ label="Process 12385" ];
"12381" -> "12385";
}
which should be obvious; nodes are named by the process ID, and [ label="Title" ] sets the text in the node. It is not from the same run as the diagram above, so the process IDs differ.
In Dot, numbers do need to be quoted if used as a name, but if a name starts with a letter, you don't need to quote it. See Graphviz documentation for further details. (The Node, Edge and Graph Attributes page is the one you usually need.)
If you want the level display in each node, use
fprintf(dot, " \"%ld\" [ label=\"Process %ld, level %u\" ];\n", (long)getpid(), (long)getpid(), level + 1);
in process(). (It uses level 0 forwards, with all nonzero levels being child processes, and level 0 being the original process. That's why level 0 returns, and all other levels exit().)
From you description, your basic logic should be:
void fork_loop(int level, int stop) {
if (level > stop) return;
if (is_even(level)) {
fork_child(level, stop);
exit(0);
} else {
fork_child(level, stop);
fork_child(level, stop);
exit(0);
}
}
Where fork_child() calls fork(). The child process would call fork_loop(level+1, stop), while the parent would return.
fork(); //if odd level start 1 child process
if (getpid() == 0){
kill (getppid(), 9); //terminate parent process
}
This logic is wrong: getpid() does not return 0 / fork doesn't return a pid in the child process - it just returns 0 to signify that it is the child process - it can know parent's pid by calling getpid before.
The logic should be:
pid_t child = fork();
if (child > 0) {
// use exit instead of kill! exit terminates this process
exit(0);
}
if (child < 0) {
... an error occurred in fork ...
}
The getpid can never be zero. As I mentioned in my top comments, you want the parent to wait on children, not the other way round and too many forks.
Here's a cleaned up version that I think works:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
pid_t pid;
pid_t ppid;
int i;
int n;
int pcur;
int pcnt;
if (argc != 2) {
printf("Wrong number of arguments");
exit(-1);
}
n = atoi(argv[1]);
pid = fork(); // start process 0
if (pid != 0) {
wait(NULL);
n = -5;
}
for (i = 1; i < n + 1; i++) {
// odd/even level -- get number of children to start
// NOTE: you may need to reverse this if
if (i % 2 != 0)
pcnt = 1;
else
pcnt = 2;
// get parent pid
ppid = getpid();
// do the forks
for (pcur = 0; pcur < pcnt; ++pcur)
fork();
// get current pid
pid = getpid();
// parent should wait on children
if (pid == ppid) {
while (wait(NULL) >= 0);
break;
}
// print pid of leaves (not working correctly)
if (i == n) {
printf("Process: %d\n", pid);
}
}
return 0;
}
Related
Generalities and explanations about the functioning of my program
I wrote a program whose aim is to create processes until it can't do it anymore (id est : it must glue the OS and completely fill the processes table). However, when OS is glued, a message like "fork can't be done anymore" appears, and all the processes can be killed by the final user thanks to CTRL+Z.
My program contains two important processes : the main one, which creates the second. The first is called "MAIN_P" in my code and the latter "P_ROOT". P_ROOT's aim is to fork until he can't do it anymore. When a fork error appears (id est : when my program has succeeded !), the final user can send a CTRL-Z signal to MAIN_P, which will kill P_ROOT and its children.
I precise that P_ROOT and its children have the same GPID (inheritance). But the latter is different than the MAIN_P's one, of course (setsid applied to P_ROOT).
My problem
When I launch my program, it fork the first child, which fork its children until the OS is glued (ie. : until the processes table is completely filled). The only problem is that I can't CTRL + Z in my console to stop it... And of course, if I just exit the terminal, it doesn't kill all these processes (and others continue to be forked moreover).
Thus, I don't recommend you to execute it...
What is wrong with my code ?
Source
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/resource.h>
int main(int argc, char* argv[]) {
pid_t pid_first_child = 0;
if((pid_first_child = fork()) == -1) { // We `fork` the first child, which will always `fork` (more precisely : until the OS is glued, processes table completely filled)
perror("fork");
exit(EXIT_FAILURE);
}
if(pid_first_child == 0) { // BEGINNING OF <FirstChild>'S CODE
pid_t pid_session_leader = 0;
if((pid_session_leader = setsid()) == -1) { // FirstChild is its process group's leader
perror("setsid");
exit(EXIT_FAILURE);
}
if(setpriority(PRIO_PGRP, pid_session_leader, -10) == -1) { // The priority of FirstChild (which is the group's leader)
perror("setpriority");
exit(EXIT_FAILURE);
}
unsigned children_counter = 0;
pid_t pid_calculation_process = 0;
while((pid_calculation_process = fork()) != -1) { // Now, FirstChild will `fork` until the limit ! When the limit is reached, -1 is returned : there isn't anymore `fork` and we exit the loop
if(pid_calculation_process > 0) {
children_counter++;
fprintf(stdout, "%u\n", children_counter);
} else { // BEGINNING OF <FirstChild's children>'s CODE (Why ? Consequently to the `while` and the `if` !)
float j=1;
while(1) { // Children can't die
int i = 0;
for(; i < 1000; i++) {
j /= 3;
}
usleep(1000);
}
} // END OF <FirstChild's children>'s CODE (FirstChild's children)
}
perror("fork"); // It's what we wanted ! This message will tell the user "OS is glued, program worked correctly"
exit(EXIT_SUCCESS); // `EXIT_SUCCESS` ? Because we reached the limit !
} // END OF <FirstChild>'S CODE
}
Comments:
To reach your fork() limit quickly, you have to make sure that each forked process doesn't consume too much resources. Your forked processes are spinning in the for-loop and taking up too much resources. If you remove the for-loop, you will hit your process limit more quickly since the processes will be blocked on the sleep() call instead of spinning.
You don't need the wait loop to wait for the processes to complete after the fork() error. That will happen automatically.
The updated source:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main(int argc, char* argv[]) {
// This (first !) child, say "P_ROOT", will create its own children, which will glue the system (thus, MAIN_P is freed
int p_root = fork();
if(p_root == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
// P_ROOT's PGID will be set to its PID (so we have : P_ROOT's PGID != MAIN_P's PGID)
if (p_root == 0) {
if(setpgid(p_root, p_root) == -1) {
perror("setpgid");
exit(EXIT_FAILURE);
}
int p_root_number_of_created_children = 0;
pid_t p_root_child = 0;
while((p_root_child = fork()) != -1) { // P_ROOT forks until it can't do it anymore...
if(p_root_child != 0) {
p_root_number_of_created_children++;
} else {
#ifdef CONSUME_RESOURCES
int i = 0;
while(i < 1000000000000000000) {
i++;
}
#endif
sleep(6000);
exit(EXIT_FAILURE);
}
}
// NOW it's impossible to create new child processes
perror("fork");
fprintf(stdout, "\nImpossible to create more children. Their number is : %d\n", p_root_number_of_created_children);
exit(EXIT_SUCCESS);
} else {
printf("Waiting, top level, root = %d\n", p_root);
wait(NULL); // MAIN_P waits for P_ROOT
char cmd = 0;
if(scanf("%c", &cmd) < 0) {
perror("scanf");
exit(EXIT_FAILURE);
}
if(cmd == '\n' && kill(-p_root, SIGKILL) == -1) {
perror("kill");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
In my code below, I'm running a parent process which forks off into two child processes. After child(getpid());, both children exit with a status.
However, when I run the parent process, it somehow always decides to run the parent section twice (sets two different pid values), and I just can't get it to run just once. Is there a way to make wait stop after getting one value?
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
void child(int n) { //n: child pid
printf("\nPID of child: %i \n", n);
//random number rand
int randFile = open("/dev/random", O_RDONLY);
int r;
if(rand < 0)
printf("ERROR: %s\n", strerror(errno));
else {
unsigned int seed;
read(randFile, &seed, 4); //&rand is a pointer, 4 bytes
int randClose = close(randFile);
srand(seed); //seeds rand() with random from /dev/random
r = rand();
if(randClose < 0)
printf("ERROR: %s\n", strerror(errno));
//range between 5 and 20 seconds
r = r % 20;
if( r < 5)
r = 5;
}
// printf("\n%i\n", r);
sleep(r);
// sleep(1);
printf("\n child with pid %i FINISHED\n", n);
exit( r );
}
int main() {
printf("\nPREFORK\n");
int parentPID = getpid();
int child0 = fork();
if(child0 < 0)
printf("ERROR: %s\n", strerror(errno));
int child1 = fork();
if(child1 < 0)
printf("\nERROR: %s\n", strerror(errno));
if(getpid() == parentPID)
printf("\nPOSTFORK\n");
//if children
if(child1 == 0) //using child1 as child-testing value b/c when child1 is set, both children are already forked
child(getpid());
int status;
int pid = wait(&status);
//parent
if(getpid() != 0) {
if( pid < 0)
printf("\nERROR: %s\n", strerror(errno));
if ( pid > 0 && pid != parentPID) {
printf("\nPID of FINISHED CHILD: %i\n Asleep for %i seconds\n", pid, WEXITSTATUS(status));
printf("PARENT ENDED. PROGRAM TERMINATING");
}
}
return 0;
}
The parent is doing:
int child0 = fork(); // + test if fork failed
int child1 = fork(); // + test if fork failed
First you only have the parent.
After 1st fork you have the parent and the 1st child, both at the same execution point, so just before the next fork.
So just after that the parent re-creates a child, and the 1st child creates its own child (and will act like the parent).
You have to use if/else so that you are sure that the child don't fork. i.e.:
child0 = fork(); // add check for errors
if (child0 == 0) {
// the 1st child just have to call that
child(getpid());
exit(0);
}
// here we are the parent
child1 = fork();
if (child1 == 0) {
// the 2nd child just have to call that
child(getpid());
exit(0);
}
You can do that differently, of course, this is just an example. The main point is to not call fork() within the child.
I'm trying to use the multiple fork() calls to create several children with different task
I found a code on
Multiple child process
Which is really close for what I want , yet I couldn't fully understand it
pid_t firstChild, secondChild;
firstChild = fork();
if(firstChild != 0)
{
// In parent
secondChild = fork();
if(secondChild != 0)
{
// In parent
}
else
{
// In secondChild
}
}
else
{
// In firstChild
}
My questions are:
How many process have been created (I assume that we have 4 since it's 2 forks!)?
In this part of the code
firstChild = fork();
if(firstChild != 0)
{
// In parent
secondChild = fork();
if(secondChild != 0)
{
// In parent
}
Does "//in parent" mean both of them are the same process (they have the same PID when I tried to test it).
How can I create 3 children using 2 forks?( I can draw the tree that ends with 4 leaves 3 of them are children and 1 parent)
Thank you (please feel free to tell me if I'm not totally getting the Fork concept)
How many process have been created (I assume that we have 4 since it's 2 forks!)?
Depending on the result of your forks it should be 0 to 2. Probably 2 if nothing goes wrong. There's a parent process that forks 2 children processes.
Does "//in parent" mean both of them are the same process (they have the same PID when I tried to test it).
Yes. In your case the code is checking for a return value of fork being non zero. That's not a very good idea since it covers 2 distinct cases:
It could be less than zero indicating an error, or ...
It could be greater than zero indicating to the parent the pid of the newly spawned process
Anyway ... considering all goes well and both the forks succeed, you will end up with a parent process having 2 different children.
How can I create 3 children using 2 forks?( I can draw the tree that ends with 4 leaves 3 of them are children and 1 parent
Something like this should do the trick:
firstChild = fork();
if (firstChild < 0) {
exit(EXIT_FAILURE);
perror("fork");
}
secondChild = fork();
Notice that by not checking the return value of fork() any more I'm getting a child process continuing execution at the same place as the parent. So the next fork will actually be executed by both the parent and the children each spawning a new process. So I'll get something like this ...
parent─┬─child1───(child1's child)
└─child2
I can't think of any way you can get this with only 2 forks though:
parent─┬─child1
├─child3
└─child2
Note: It's customary on stackoverflow to only limit yourself to one question per topic.
The following code shows how to create 4 process (1 parent 3 children) with only 2 forks
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int *list;
void calculate_average(int );
void calculate_maximum(int);
void calculate_minimum(int);
void calculate_average(int count)
{
int i, total = 0;
for (i = 0; i < count; i++)
total += list[i];
double average = total / count;
printf("average is %f\n",average);
}
void calculate_maximum(int count)
{
int i;
int maximum = list[0];
for (i = 1; i < count; i++)
if (list[i] > maximum)
maximum = list[i];
printf("maximum is %d\n",maximum);
}
void calculate_minimum(int count)
{
int i;
int minimum = list[0];
for (i = 1; i < count; i++)
if (list[i] < minimum)
minimum = list[i];
printf("minimum is %d\n",minimum);
}
int main(int argc, char *argv[])
{
pid_t pid, pid1;
int num_of_args = argc-1;
int i;
/* allocate memory to hold array of integers */
list = malloc(sizeof(int)*num_of_args);
for (i = 0; i < num_of_args; i++)
list[i] = atoi(argv[i+1]);
printf("The %d number of input ingeters are\n",num_of_args);
for (i = 0; i < num_of_args; i++)
printf("%d\n",list[i]);
/* fork a child process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed\n");
return 1;
}
else if (pid == 0) { /* P2 */
pid1=getppid();
calculate_average(num_of_args);
}
else { /* P1 */
pid1=getpid();
wait(NULL);
}
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed\n");
return 1;
}
else if (pid == 0) { /* could be either P3 or P4 */
if (getppid() == pid1) { /* P3 */
calculate_minimum(num_of_args);
}
else { /* P4 */
calculate_maximum(num_of_args);
}
}
else {
wait(NULL);
}
return 0;
}
Note that one of the children will be a parent for a grandchild
Im new in C programming and i have to do this:
Write a program that creates a second process, and then in both processes outputs the process ID and the owners user ID.
I don't know if thats right and how to continue from here. Here is what i have:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main(void) {
int ChildPID;
printf("This is the parent process number %d\n",getpid());
if ((ChildPID = fork()) == -1) {
perror("Could not fork");
exit(EXIT_FAILURE);
}
if (ChildPID == 0) {
//----In the child process
printf("This is the child process, number %d parent number %d\n", getpid(), getppid());
}
return(EXIT_SUCCESS);
}
The piece of code given below gives your solution. Here you can clearly identify parent code and child process code. Both are printing their corresponding pids.
void ExecuteChild(void);
void ExecuteParent(void);
int main(void)
{
pid_t pid;
pid = fork();
if (pid == 0)
ExecuteChild();
else
ExecuteParent();
}
void ExecuteChild(void)
{
int i;
for (i = 1; i <= 200; i++)
printf("CHILD[%d]: UserID[%d] printing - %d\n", getpid(),getuid(),i);
printf(" ------------- Child Exiting -------------\n");
}
void ExecuteParent(void)
{
int i;
for (i = 1; i <= 200; i++)
printf("PARENT[%d]: UserID[%d] printing - %d\n", getpid(),getuid(),i);
printf(" ------------- Parent Exiting -------------\n");
}
I know I'm going to need to use fork(), but this just creates a single child process. Do i simply call fork again from within the child process? Also, I need them to communicate through a signal or pipe, which is easier to implement and what do i need to know for doing that (functions, etc..)
To create a second process, call fork() again - either within the parent or the child (but not both!). Which you choose depends on whether you want this process to be a child of the original parent or a child of the first child process (it is usual for it to be a child of the original parent).
Communicating through a pipe is much simpler and more reliable than using signals. pipe(), close(), read(), write() and select() are the key functions here.
For example, to have the parent create two child processes, you would do something like:
pid_t child_a, child_b;
child_a = fork();
if (child_a == 0) {
/* Child A code */
} else {
child_b = fork();
if (child_b == 0) {
/* Child B code */
} else {
/* Parent Code */
}
}
Another fancy code using && operator:
pid_t c1_pid, c2_pid;
(c1_pid = fork()) && (c2_pid = fork()); // Creates two children
if (c1_pid == 0) {
/* Child 1 code goes here */
} else if (c2_pid == 0) {
/* Child 2 code goes here */
} else {
/* Parent code goes here */
}
#include <stdio.h>
#include <unistd.h>
void main(){
int pi_d ;
int pid ;
pi_d = fork();
if(pi_d == 0){
printf("Child Process B:\npid :%d\nppid:%d\n",getpid(),getppid());
}
if(pi_d > 0){
pid = fork();
if(pid > 0){
printf("\nParent Process:\npid:%d\nppid :%d\n",getpid(),getppid());
}
else if(pid == 0){
printf("Child Process A:\npid :%d\nppid:%d\n",getpid(),getppid());
}
}
}
output :
Parent Process:
pid:3648
ppid :2379
Child Process B:
pid :3649
ppid:3648
Child Process A:
pid :3650
ppid:3648
You can put the fork in a loop and generate as many child processes as you need.
I did that on a project recently.
for(nSon=0; nSon < nSonsAsked; nSon++) {
Log_Print("Setup son #%.2u ", nSon+1);
if((pid = fork()) == 0) {
/* Do child stuff init, like connect the pipes, close shared handles */
return iTMInChild(...); /* A specific function of the child work */
/* The life of the child should not go beyond that point, i.e. the loop is over
or else the child will spawn even more processes. */
}
else if(pid > 0) {
/* Father process stuff. Here I initialise an array with the pid of the forked */
/* processes, this way I can index with the number of processes.*/
pid[nSon] = pid;
}
else
return Err_Print(ERR_FORK_FAILED, "fork failed. errno=%d \"%s\"\n", errno, strerror(errno));
}
Log_Print() and Err_Print() are internal functions but quite obvious so I let them like they are.
There is one aspect with the variables that has to be explained. nSon and nSonAsked should be declared as globals not as stack variables. This way, their value persists in the forked process. This means that the nSon variable will have a different value in each of the children. This allows it to have a simpler numbering scheme than the ownpid() number.
To get it completely right, there are a lot of details to get right. You will have to set signal handlers in the father process to detect the death of a child, likewise the other way round (only possible on Linux, other Unix (at least Solaris) do not support parent death signals).
You have to be aware that open file descriptors in the father process will be also open in the child after fork and it will be the same one. This opens a lot of concurrency problems if you're not aware of it (the solution is using dup() and close() in the right places).
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
system ("clear");
int i ;
pid_t childa,childb,childa1,childa2,childb1,childb2;
printf("\n \t \t I am the parent process with ID %d \n",getpid());
childa=fork();
if (childa == 0 )
{
printf("\nI am a child A with PID %d and my parent ID is %d\n",getpid(),getppid());
}
else
{
childb = fork();
if (childb == 0)
{
printf("\nI am Child B with ID %d and my parent ID is %d\n",getpid(),getppid());
}
else
{
sleep(1);
}
}
}
In this example they are just sleeping for a few random sec. It also has all the pid, so we can send SIGNAL to communicate... Most of the #includes are commented cause they were useless where I compiled.
#include <stdlib.h> // exit() ...
#include <stdio.h> // printf() ...
// Compile with -lrt -> cc file_name.c -lrt
//#include <fcntl.h>
//#include <sys/stat.h>
//#include <sys/types.h>
//#include <sys/wait.h> // may need this for wait()
//#include <time.h>
//#include <unistd.h> // and this one for fork()
// In the start function you can do whatever you want.
void start (const int azon) {
// For children processes
srand( time(NULL) );
unsigned t = rand()%5; // printf("%d\n", t);
sleep(t);
printf("%d. process reached the end.\n", azon);
exit(0);
}
int main() {
const int N = 5;
pid_t pids[N];
int i;
// The 'for' loop make 'N' process with 'fork()'.
// The children processes will call the start function.
// Since after fork() you will get 2 process. One Parent, and One Child
// The returning value from fork() is saved in "pids" which is an
// integer AND it is (<0) IF something went wrong.
// it is (>0) IF 'we are' in the Parent process,
// because this number is the Child process' ID (pid).
// and Last it is (==0) IF 'we are' in the Child process.
for (i = 0; i < N; i++) {
pids[i] = fork();
sleep(1);
if (pids[i] == 0) start(i+1); // ... OR you can make a switch(..)
}
// This 'for' loop in the wait(NULL) statement ONLY move on when a
// process ended, so it waits until 'N' proc ends.
for (i = 0; i < N; i++)
wait(NULL);
printf("Partent process reached the end\n");
return 0;
}
Just a little contribution, if you want to create 2 childs from the same parent you could use this code below. In which one father create 2 child processes (lazy and active).
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
int main (){
pid_t lazy_child;
lazy_child = fork();
if(lazy_child == 0){ // This is the lazy child process.
printf("LAZY CHILD:%d\n", getpid());
}
else if(lazy_child > 0){ // This is the father process.
pid_t active_child = fork();
if(active_child == 0){ // This is the active child process.
printf("ACTIVE CHILD:%d\n", getpid());
}
else if(active_child > 0){ // This is the father process.
printf("FATHER:%d\n", getpid());
}
else{ // Fork doesnt work.
printf("fork error\n");
exit(1);
}
}
else{ // Fork doesnt work.
printf("fork error\n");
exit(1);
}
return 0;
}
If you run this code, you should get a similar output:
$ ./a.out
FATHER:14501
ACTIVE CHILD:14503
LAZY CHILD:14502
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
pid_t AliceID, BobID;
double n=0;
int i1 =0;
/* fork a child process */
AliceID = fork();
if (AliceID < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (AliceID == 0) { /* child Alice code */
for(int i=1; i<11; i++)
{n = n+i;
i1++; }
double avg1 = n/i1;
printf("From Alice: the average of 1,2, …, 10 is the-average-she-calculated");
printf(" sum = %.2f and avg = %.2f \n",n, avg1);
}
else {
BobID = fork();
if (BobID == 0) { /* Child Bob code */
printf("From Bob: I am born to print this and then die.\n");
} else { /* Parent Code */
/* parent will wait for the child to complete */
wait(NULL);
printf("From parent: AliceID is %d \n", AliceID);
printf("From parent: Bob is %d \n", BobID);
printf("Parent ID %d \n", getpid());
}
}
return 0;
}