I'm working on some stuff using fork() in C. This is my first contact with the concept of forking processes.
Basically, I have something like this:
int pid;
pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed");
exit(-1);
} else if (pid == 0) {
fprintf(stderr, "Inside child %d\n", getpid());
// do some other stuff
exit(0);
} else {
fprintf(stderr, "Inside parent %d\n", getpid());
}
Before, I hadn't put the exit(0) in the child process' code. I was getting seemingly tons of duplicate processes. I added the exit(0) and now I'm only spawning one child. However, I want to know if this is proper practise or just a bandaid. Is this the correct thing to do. How should a child "stop" when its done?
Usually the child either has it's own code with an exit or calls one of the exec functions to replace its process's image with another program. So the exit is okay. But the parent and child could execute at least some of the same code, something like this:
int pid = fork();
if (pid < 0) {
fprintf(stderr, "Fork Failed");
exit(-1);
} else if (pid == 0) {
// child code
} else {
// parent code
}
// shared code
Well if you want that parent process works only after child process finishes then you can use wait function.Here is the example:
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h> //fork() is defined in this header file
#include<sys/wait.h>//wait() is defined in this header file
int main()
{
int pid,a,b;
printf("\nPlease enter two numbers\n");
scanf("%d%d",&a,&b);
pid=fork();
if(pid<0)
{
printf("\nfork failed\n");
exit(1);
}
if(pid==0)
{
//you are in chiled process
//getting child process id
printf("\n[child %d]: sum of %d and %d is %d\n",getpid(),a,b,a+b);
}
else
{
//waiting for child process to finish
wait(NULL);
//getting parent id
printf("\n[parent %d]:difference of %d and %d is %d\n",pa_pid,a,b,a-b);
exit(0);
}
}
Related
I have the following code in my main function
pid_t pid;
pid = fork(); //Two processes are made
if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
{
int status;
if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
{
printf("Exitstatus [");
for (int i = 0; i < noOfTokens; i++)
{
printf("%s ", commands[i]);
}
printf("\b] = %d\n", WEXITSTATUS(status));
}
}
else if (pid == 0) //Child process. Executes commands and prints error if something unexpected happened
{
if (runBGflag==1) insertElement(getpid(),ptr);
execvp(commands[0], commands);
printf ("exec: %s\n", strerror(errno));
exit(1);
}
In a nutshell, a child process is made and if the runBackGround flag is set, the parent process will not wait for the child process to exit, but rather continue running. If a background process is made, the PID of the background process is stored in a list. At a later point, this function is called
void delete_zombies(void)
{
pid_t kidpid;
int status;
char buffer[1337];
while ((kidpid = waitpid(-1, &status, WNOHANG)) > 0)
{
removeElement(kidpid,buffer,1337);
printf("Child %ld terminated\n", kidpid);
printf("its command was %s\n",buffer);
}
}
This function simply checks if any child processes have died and in that case deletes them. It will then search for the childs PID in the list, remove it and print it out.
The problem is, the delete_zombies function will find that a child has died and will then try to remove it from the list, but it only finds an empty list, as if the child process never inserted its PID into the list.
This is really strange, because delete_zombies only finds a dead child process, when there was one created with the background flag set, so we know insertElement must have been called, but strangely when the parent checks in the list nothing is there
Is the cause for that, that child process and parent process have seperate lists, or is the PID maybe wrong?
The problem here is that the child process does not wait for the message to arrive from the function startWorking(), and because of that I am getting a random char as output or sometimes nothing.
I am sending a char array from startWorking() to the pipe and I am making sure only the parent does this job.
One solution would be, sending a signal from startWorking() to the child processor, after writing into the pipe.
But the read() function behavior is waiting for the pipe to receive the message and only then read the message, but somehow it's not doing that, or maybe there is a problem in writing the message.
int main(int argc, char const *argv[])
{
pid_t pid;
pid = fork();
int mypipefd[2];
if (pid > 0)
{
if (pipe(mypipefd) == -1)
{
perror("Pipe failed\n");
exit(EXIT_FAILURE);
}
storeEngine(mypipefd);
}
else if(pid < 0)
{
perror("fork call failed \n");
exit(EXIT_FAILURE);
}
else
{
printf("I am the child \n");
printf("child: %d \n", getpid());
char message[6];
close(mypipefd[1]);
read(mypipefd[0], &message, 6);
close(mypipefd[0]);
printf("child read value:\n ");
printf("%s \n", message);
}
return 0;
}
void startWorking(int *mypipefd)
{
printf("%d \n" ,getpid());
//close(*mypipefd);
write(*(mypipefd+1), "hello", 6);
close(*(mypipefd+1));
}
Notice that if I remove the two slash behind close(*mypipefd) the program will never finish, and it will get stuck there.
Without examining the rest of your code, you need to call pipe() before you call fork() so the pipe can be used by both the parent and the child process. If you call pipe() after you call fork(), the pipe is only usable by that one process.
More like this:
int main(int argc, char const *argv[])
{
int mypipefd[2];
if ( pipe( mypipefd ) == -1 )
{
perror("Pipe failed\n");
exit(EXIT_FAILURE);
}
pid_t pid = fork();
if (pid > 0)
{
storeEngine(mypipefd);
}
.
.
.
No, pipes used to communicate between processes should be created before the fork() (otherwise, you have no easy way to send thru them, since the reading and the writing ends should be used by different processes).
I'm start to studying the fork. while using the fork, I have some problems.
I'm trying to create a single parent process with two child
and two child trying to make each three grandchild.
When I run my code, unlike my expectations, so many child and grandchild come out.
Here my code:
int main()
{
int i, j, rev;
for(i=0;i<2;i++)
{
if((rev=fork())<0) { printf("fork() error\n"); exit(-1); }
else if(rev==0)
{
printf("child %d %d \n",getpid(),getppid());
for(j=0;j<3;j++)
{
if((rev=fork()) <0) { printf("fork() error\n"); exit(-1); }
else if(rev == 0)
{
printf("grandch %d %d \n",getppid(),getpid());
exit(0);
}
}
}
}
printf("parent %d %d \n",getpid(),getppid());
exit(0);
}
How can I correct this code?
One important example before using fork() statements :
//Calculate number of times hello is printed.
#include <stdio.h>
#include <sys/types.h>
int main()
{
fork();
fork();
fork();
printf("hello\n");
return 0;
}
Number of times hello printed is equal to number of process created. Total Number of Processes = 2^n where n is number of fork system calls. So here n = 3, 2^3 = 8.
fork (); // Line 1
fork (); // Line 2
fork (); // Line 3
L1 // There will be 1 child process
/ \ // created by line 1.
L2 L2 // There will be 2 child processes
/ \ / \ // created by line 2
L3 L3 L3 L3 // There will be 4 child processes
// created by line 3
So if you are trying to make two child process and then three grand
child follow something of this sort:
What you should do is something like this for two child processes
if(fork()) # parent
if(fork()) #parent
else # child2
else #child1
After you create process , you should check the return value. If you don't , the second fork() will be executed by both the parent process and the child process, so you have four processes.
If you want to create n child processes , just :
for (i = 0; i < n; ++i) {
pid = fork();
if (pid) { //means pid is non-zero value, i.e, pid>0
continue;
} else if (pid == 0) {
break;
} else {
printf("fork error\n");
exit(1);
}
}
The section of code that runs for the child processes doesn't exit. As a result, they continue on to run more iterations of the outer loop which only the parent process is supposed to run, so they spawn more children.
You need to call exit, or better yet _exit, so that the children don't do that:
int main()
{
int i, j, rev;
for(i=0;i<2;i++)
{
if((rev=fork())<0) { printf("fork() error\n"); exit(-1); }
else if(rev==0)
{
printf("child %d %d \n",getpid(),getppid());
for(j=0;j<3;j++)
{
if((rev=fork()) <0) { printf("fork() error\n"); exit(-1); }
else if(rev == 0)
{
printf("grandch %d %d \n",getpid(),getppid());
_exit(0);
}
}
sleep(1); // stick around so the grandchild can print the parent pid
_exit(0); // exit the child
}
}
printf("parent %d %d \n",getpid(),getppid());
sleep(1); // stick around so the child can print the parent pid
exit(0);
}
//Why not execute all the conditions(parent and child)?
#include<stdio.h>
#include<unistd.h>
int main(){
pid_t pid; //process-id
printf("This is where we start...\n");
pid = fork();
//For the child process
if(pid==0){
printf("This is the child process!\n");
return 1;
}
//This should have been printed
if(pid>0){
printf("This is the parent!\n");
}
//THis may/may not be printed - its ok
if(pid < 0){
printf("Fork failed!");
}
return 0;
}
It was excepted that after returning from the child, the parent should have been executed but this is what i get:
$ This is the child process!
What am i missing? why not child as well as the parent block printed?
The program is completely fine. When a fork is performed, a new child process is created. The child process created is independent of the parent and it is completely possible that the parent does not wait for the child to complete its execution.
If you want that the parent execution resumes once the child is complete, you should use the wait() function, that makes sure that a forked child is executed before parent continues.
Try updating your code as follows:
#include<stdio.h>
#include<unistd.h>
#include <sys/wait.h> //Add this header
int main()
{
pid_t pid; //process-id
int status; //A variable to get the status of the child, i.e. if error or success
printf("This is where we start...\n");
pid = fork();
if(pid==0){
printf("This is the child process!\n");
return 1;
}
if(pid>0){
wait(&status); //Function to wait for child
printf("This is the parent!\n");
}
if(pid < 0){
printf("Fork failed!");
}
return 0;
}
For more information check out this link: Forking a Process and Parent-Child execution - Linux : C Programming
I'm writing a C program that creates a child process. After creating the child process, the parent process should ouput two messages: "I am the parent" then it should print "The parent is done". Same for child process "I am child" and "The child is done". However I want to make sure, the second message of the child is always done before the second message of the parent. How can I achieve to print "The child is done" and "The parent is done" rather than printing their pid?
#include <unistd.h>
#include <stdio.h>
main()
{
int pid, stat_loc;
printf("\nmy pid = %d\n", getpid());
pid = fork();
if (pid == -1)
perror("error in fork");
else if (pid ==0 )
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
}
else
{
printf("\nI am the parent process, my pid = %d\n\n", getpid());
sleep(2);
}
printf("\nThe %d is done\n\n", getpid());
}
You could have a flag variable, that is set in the parent, but then the child clears it. Then simply check for that for the last output.
Something like
int is_parent = 1; // Important to create and initialize before the fork
pid = fork();
if (pid == -1) { ... }
if (pid == 0)
{
printf("\nI am the child process, my pid = %d\n\n", getpid());
in_parent = 0; // We're not in the parent anymore
}
else { ... }
printf("\nThe %s is done\n\n", is_parent ? "parent" : child");
Call wait(2) in the parent process for the child to complete.
else
{
wait(0);
printf("\nI am the parent process, my pid = %d\n\n", getpid());
}
You should check if wait() succeeds and main()'s return type should be int.