Spawning C child process for different jobs? - c

So I am trying do a application which fork()s 2 children.
first does a for(i=1; i<=50000; i++) loop
the second a for(i=50000; i<=100000; i++) loop
the parent does for(asciic=65; asciic<=90; asciic++)-> loop for printing A to Z letters
I need all three to do they're work simultaneous not one after another.
I've looked over the internet and I couldn't found a proper way, all I could find are loops which create the children processes but they do almost the same thing and most are created one after another.
Any help is appreciated.
To be more understood, this is what I've done before posting:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
pid_t child_pid,child_pid1;
int i=0;
int stare;
int asciic;
child_pid=fork();
child_pid1=fork();
if (child_pid==0) {
//printf("Father PID: %d -> Child 1: %d\n",getppid(),getpid());
for(i=1; i<=50000; i++){
printf("%d-%d\n",getpid(),i);
}
exit(0);
} else if (child_pid1==0) {
//printf("Father PID: %d -> Child 2: %d\n",getppid(),getpid());
for(i=50000; i<=100000; i++) {
printf("%d-%d\n",getpid(),i);
}
exit(0);
} else {
//printf("PID-ul procesului parinte: %d\n", getpid());
pid_t rez=waitpid(child_pid,&stare,WNOHANG);
pid_t rez1=waitpid(child_pid1,&stare,WNOHANG);
while(rez==0 || rez1==0){
for(asciic=65; asciic<=90; asciic++){
printf("%d- %c\n",getpid(),asciic);
}
rez=waitpid(child_pid,&stare,WNOHANG);
rez1=waitpid(child_pid1,&stare,WNOHANG);
}
}
return 0;
}
If I comment out the loops I can see that the children have different PIDs, 1 child has the right parent PID and other it has other parent PID.

Your 2 lines with forks:
child_pid=fork();
child_pid1=fork();
do not create 2 children, but three: the parent creates a first child in the first fork(). From that moment there are 2 processes: parent and child. And each of them executes the second fork(). You will have in total 1 parent, 2 children and 1 grandchild.
In order to have just 1 parent and 2 children, you will have to:
pid1 = fork();
if (pid1 < 0) {
/* Error in fork() */
} else if (pid1 == 0) {
/* first child */
exit(0);
}
pid2 = fork();
if (pid2 < 0) {
/* Error in fork() */
} else if (pid2 == 0) {
/* second child */
exit(0);
}
/* parent */
Moreover, even when your code is correct, you cannot "see" if the processes are running concurrently or not just looking at their outputs. In fact, even if there are multiple processes executing "at the same time", you may see that one of the processes finishes before another one starts. That is because typically the kernel does time multiplexing to offer each child some CPU time. You can see concurrency if the processes take longer to complete, for example adding some sleep().

The problem is here:
child_pid=fork();
child_pid1=fork(); // This line will be executed by both parent and first child!!!
You need to move the second fork into the parent part of the first if, and then have a separate if for the second child.

fork() returns the pid_t of the child to the caller (parent), or -1 if it failed. In the child, 0 is returned. You can simply test
if (fork())
{
//do one thing
}
else
{
//do something else
}

Related

The initial process creates 5 child processes, and waits for them to finish. Each child process performs 5 repetitions, where in each repetition

I'm a bit confused with the creation of processes with fork(), sleep() and wait() in c. Take the following piece of code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
void childProcess(void);
void childProcess(void)
{
for(int i = 0; i < 5; i++)
{
printf("pid: %d email: myemail\n", getpid());
sleep(1);
}
}
int main(int argc, char *argv[])
{
for (int i = 0; i < 5; i++)
{
pid_t childpid;
if ((childpid = fork()) == 0)
{
childProcess();
exit(0);
}
}
int status;
while (wait(&status) > 0)
{
}
return 0;
}
After this piece of code has been executed,executes processes but does not remove repetitions from 5 processes. I'm a little confused with the process.
The initial process creates 5 child processes, and waits for them to finish.
Each child process performs 5 repetitions, where in each repetition:
Prints the message
pid: PID email: USER_EMAIL
where PID is the child PID of the process, while USER_EMAIL is the email
Suspends its operation for 1 second (at a time) with the sleep call
The parent process prints the children's PIDs when they are finished
P.S I EDIT THE CODE
#mixalispetros, you have multiple things to fix, and they all have to be fixed together for your code to work as intended.
exit(0);
for (int i = 0; i < 5; i++) {
wait(NULL);
}
The process ends on exit(0). wait is never called.
if (fork() == 0) {
// what code runs here? The code in the new process
}
What code runs within the fork() conditional? The new process's code. Which process should run wait()? The original process. So in addition to being after an exit, the wait() is also in the wrong process.
Where to move it? The for loop wait()s for 5 child processes. Why would there be 5 child processes for which to to wait()? Because we had already started all 5 child processes before we went into our loop of 5 wait()s.
The wait()s must happen not just outside the child process conditional block, but also outside the loop around the call to fork().
I'm a bit confused with the creation of processes with fork(), sleep() and wait() in c
It is confusing. Refer to the documentation often to keep it straight.
Remember, fork() returns twice - in the original process (returning the process ID of the new process), and in the new process (returning 0). wait(), will wait for the next child process to exit.
In summary, put the wait loop outside the loop that fork()s child processes. This will also move it ouside the block of code that executes in the child process.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
// this loop creates 5 processes
for (int i = 0; i < 5; i++) {
if (fork() == 0) {
printf("Child %d, PID %d\n", i, getpid());
sleep(i);
exit(0);
}
}
// now, all subprocesses were started
// wait for the same number of child processes to end
for (int i = 0; i < 5; i++) {
wait(NULL);
}
}

Fork() code not working as expected - Hierarchy making

Good afternoon.
I am currently working on a C program that takes one and only one parameter which designates the number of "child generation"s to be created (the own father counts as 1 already). "wait()" system calls are not to be used for this exercise (the version with "wait" calls happens to work exactly as expected).
For instance, the call $program 4 should generate a hierarchy like this:
Process A creates B
Process B creates C
Process C creates D
The printed messages are not important, as they are merely orientative for the task. With the following code (which happens to work exactly how I want with a "wait()" call) states that all the child processes derive from the same father, which I don't understand why it's happening.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
int counter; pid_t result; int i;
/*
We are going to create as many processes as indicated in argv[1] taking into account that the main father already counts as 1!
*/
if (argc > 2 || argc == 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
int lim = atoi(argv[1]);
//We eliminate the impossible cases
if (lim < 1) {puts("IMPOSSIBLE EXECUTION\n"); exit(-1);}
if (lim == 1) {puts("The father himself constitutes a process all by his own, therefore:\n");
printf("Process%d, I'm %d and my father: %d\n", counter, getpid(), getppid());
}
else {
for (i = 0; i < lim; i++) {
result = fork();
if (result < 0) {
printf("Call%d \n", counter); perror("Has failed!");
exit(-1);
}
else if (result) {
break; //Father process
}
else {
counter++; //Child processes increment the counter
printf("Process%d, I am %d and my father: %d\n", counter, getpid(), getppid());
}
}
}
The hierarchy generated by the code above is not the one I expected...
All help is greatly appreciated.
Thank you
With the following code (which happens to work exactly how I want with
a "wait()" call) states that all the child processes derive from the
same father, which I don't understand why it's happening.
I don't see that in my tests, nor do I have any reason to expect that it's actually the case for you. HOWEVER, it might appear to be the case for you if what you see is some or all of the child processes reporting process 1 as their parent. That would happen if their original parent terminates before the child's getppid() call is handled. Processes that are orphaned in that way inherit process 1 as their parent. If the parent wait()s for the child to terminate first then that cannot happen, but if instead the parent terminates very soon after forking the child then that result is entirely plausible.
Here's a variation on your loop that will report the original parent process ID in every case:
pid_t my_pid = getpid();
for (i = 0; i < lim; i++) {
result = fork();
if (result < 0) {
printf("Call%d \n", counter); perror("Has failed!");
exit(-1);
} else if (result) {
break; //Father process
} else {
pid_t ppid = my_pid; // inherited from the parent
my_pid = getpid();
counter++; //Child processes increment the counter
printf("Process%d, I am %d and my father: %d\n", counter, (int) my_pid, (int) ppid);
}
}
You are missing a crucial function call.
for (i = 0; i < lim; i++) {
fflush(stdout); // <============== here
result = fork();
Without it, your fork duplicates parent's stdout buffer into the child process. This is why you are seeing parent process output repeated several times --- its children and grandchildren inherit the output buffer.
Live demo (with fixed formatting for your reading convenience).

maximum concurrent processes active on a system at a time with fork()

this program is used to create maximum no. of processes system is allowed to create
Ok fine but i didn't get the else part what is going in there
When i execute it my system hangs boot itself automatically??
Can someone please explain it how the following code works??
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
pid_t pid;
int i = 1;
for(;;)
{
pid = fork();
if(pid < 0)
printf("MAX no of concurrent process are %d\n",i);
if(pid == 0)
i++;
else
{
wait(0);
exit(0);
}
}
return 0;
}
On entering the for loop, the process is tried to be forked.
On success, in the parent process, fork() returns something > 0, the PID of the child. The child returns 0.
On failure, fork() returns < 0. This case should be handled appropriately.
In your code, the child process increments the "inherited" i and goes on with the next loop run, but the parent waits for its child and exits.
This all goes well up to the point where fork() fails. Then you get an output, but the code is continued nevertheless, up to wait(0). There it hangs, and so do all its parents.
If you would do
if(pid < 0) {
printf("MAX no of concurrent process are %d\n",i);
exit(0); // or return 0
}
the child which was unable to create another child would exit properly and so would do all of its parents.

Theory,Processes fork()

Goodmorning, i would like to ask 2 things..
1) what returns a fork() did on a child which has already a pid==0 ? if i continue to fork on every son, each of them will have 0 as pid ?? or not ?
2) this is my file Buffer.c and it runs on a single process.
At the beginning it forks() out some Producers who produce() and some Consumers who consume() ,but I am afraid that every producers enters in the next for cicle and it starts to produce himself other consumers!! because it write pid=-1 so...
I want that this piece of code produce only P producers and C consumers, but i need to know why every producer do not create other consumers!
Can you help me,maybe giving me a scheme of how many processes i will create with this code?
Maybe doing a scheme as this:
Father:
8 producers
-
-
-
...
each of them produces: 5 consumers
etc etc......
int main(int argc, char **argv) {
/....
pid_t pid;
pid_t cons_pid[C];
/* fork producers */
pid = -1;
for(i=0; i<P && pid!=0; i++)
pid=fork();
switch(pid) {
case -1:
...
case 0:
/* GENERIC PRODUCER i */
...
/* PRODUCE() */
printf("Producer %d exits\n",i);
...
return 0;
}
/* fork consumers */
pid = -1;
for (j=0; j<C && pid!=0; j++)
pid = cons_pid[j] = fork();
switch(pid) {
case -1:
....error
case 0:
/* GENERIC CONSUMER j */
CONSUME()....
}
return 0;
}
what returns a fork() did on a child which has already a pid==0
0 is not a valid PID, hence by definition there can't be an process with PID=0 and thus PID=0 is a perfectly well defined return for indicating child status.
if i continue to fork on every son, each of them will have 0 as pid
No process ever has PID=0. All PIDs are greater than zero! A zero is just the return value received by the newly forked process to indicate that it's the child. The actual PID a child process got is queried using the getpid function from the child process. However the parent process can't perform such a query, since in the time between fork and a assumed query function call, the child may already have terminated (race condition). So you want fork to return the PID to the parent directly.
BTW: The terminology is parent and child not father and son (processes are things not people, despite what the TRON movies depict).
Regarding your code snippet: A switch statement is the wrong choice here. You want to use an if statement.
fork() splits up the current process into a father and a child. The child will have a new PID, the father retains the old PID. In both processes fork() returns after the splitting. In the father the return value will be the PID of the child (to make it known), and in the child the return value will be 0.
1) The lowest possible process ID is 1, this is the ID of the init process from which all other processes are forked. Therefore, it is not possible for a child or for your parent process to "already have ID 0". Your child's process ID is necessarily greater than 1. Thus, the problem that you are afraid of cannot happen.
2) The confusion that you state is the reason why fork (which returns twice, once for the parent and once for the newly created child!) has a somewhat "weird" return value which can have so many different values:
it can be -1, then something went wrong, and no child was created.
it can be a positive value, then you are in the parent process, and the value is the child's process ID. It's as if you called any other "normal" function that just returned normally.
it can be 0, then your code knows it is now running in the child process.
You must examine the return value (if()) so you know what process you are in. Then no such thing as you decribe can happen (or, should happen, this presumes your code does not have any bugs).
EDIT:
The code can be rewritten slightly so it gets rid of the && pid!=0 inside the loop and thus looks a bit less scary overall:
int main()
{
int pid, i;
pid_t cons_pid[C];
for(int i=0; i<P; ++i)
{
pid=fork();
if(pid == -1) exit(1); /* fork error */
if(pid == 0) { producer(); return 0; }
}
for(i=0; i<C; ++i)
{
pid = fork();
if(pid == -1) /* fork error */
{ /* should do a kill_producers(); here */ exit(2); }
else if(pid == 0) /* consumer */
{ consumer(); return 0; }
else /* master process, remember all consumer pids */
{ cons_pid[j] = pid; }
}
/* ... */
return 0;
}

how to create two processes from a single Parent

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;
}

Resources