I'm new to c language and Linux. I have a problem related to fork(),getpid()and exec()function.
I wrote a c program using fork() call the code of my program is following"
code:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
void fun()
{
printf("\n this is trial for child process");
}
int main (int argc, char const *argv[])
{
int i,status,pid,t;
if(pid=fork()<0)
{
printf("\nfailed to create the process\n");
}
if(pid=fork()==0)
{
printf("\n the child process is created");
fun();
exit(1);
}
while(wait(&status)!=pid);
return 0;
}
The out put of this program is following:
the child process is created
this is trial for child process
the child process is created
this is trial for child process
Now my questions are as follows:
Why the output of program showing same thing twice? The output supposed to be "child process is created this is trial for child process"
Why the output is not according to code ?
Can we have a program which has 4 processes and all the processes perform different task for example one process print "my name". One process print "my age", the other process print "my address ?
How to make multiple process in main function ?
How to control the execution of multiple process ?
what does the exec() function do? Can anyone please explain me the working of exec(), fork(), getpid() with a source code?
Please help this novice fellow.
Your code calls fork() multiple times:
if(pid=fork()<0) /* calls fork() */
{
...
}
if(pid=fork()==0) /* also calls fork() */
{
...
}
Each successful fork() creates a new child process. To make matters worse, the second fork() is called by both the parent and the first child.
If you're trying to create a single child process, you should call fork() just once:
pid_t pid; /* note the correct return type of fork() */
...
pid = fork();
if (pid < 0)
{
...
}
else if (pid == 0)
{
...
}
If you want to create multiple child processes, you can have the parent process call fork() in a loop.
As to questions like "what does exec do?", my advice is to learn how to use man and then come back with specific questions if there's something in the manpages that remains unclear.
In this code you are creating Three process not including your main process.
pid=fork()
is itself a statement , which forks a new process even though it is inside an if statement condition. After the first fork() call the remaining codes will be executed twice. so next fork call will be called twice. You have already created a new process.
fork returns zero to itself and its
process id to its parent
That is consider a process A forks B (not from your code)
pid = fork();
printf("pid is : %d",pid);
printf statement executes twice(one for A and one for B). For A it prints(A is parent)
pid is : 512 //some integer value
process id
and B prints
pid is : 0
So in your question
if(pid=fork()==0)
{
printf("\n the child process is created");
fun();
exit(1);
}
this is the second fork which is already executing twice. So each of this execution creates a new child process. For both childs pid value is 0. So your print statement executes, which is what you see in the output. But for both parents a pid value will be there and your if condition fails, so it wont print. These two childs are your second and third processes..So in short you create 3 processes along with the main process
The output is generated twice because you are forking twice:
if(pid=fork()<0) // Fork #1
{
printf("\nfailed to create the process\n");
}
if(pid=fork()==0) // Fork #2
Related
The task is as follows
Write a program that would run another process in memory and leave it running in an infinite loop. When the program is restarted, it must remove the previously started process from memory (you can use kill).
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <spawn.h>
#include <sys/wait.h>
int main(void){
int pid = getpid(); // we find out the PID of the current process and store it in a variable
FILE *file = fopen("example.txt", "r"); // getting information from a file about a child process
int filePid = 0;
fscanf(file, "%d", filePid);
fclose(file);
switch (filePid){
case -1:{ // if there is no child process, then run it and write the PID to a file
filePid = fork();
file = fopen("example.txt", "w");
fprintf(file, "%d", filePid);
fclose(file);
break;
}
case 0:{ // if this process is a child, then we go into an infinite loop
for(;;){
sleep(7); // waiting for seven seconds so that the system is not heavily loaded
}
break;
}
default:{ // if this program is started again with a child process, then we send a signal to the child process
kill(filePid, SIGKILL); // we send a signal to the child process so that it ends, and after that we write the information to the file
file = fopen("example.txt", "w"); // we write information to the file that the child process is missing
fprintf(file, "%d", -1);
fclose(file);
}
}
return EXIT_SUCCESS;
}
/Yes, I have to do it through the qnx operating system./
the errors are as follows..I'm a little confused with getpid, because I haven't used the pid variable anywhere.
and another mistake.
I will be grateful for your help.since I'm a little confused...
UPD:
I can't get the value 0
UPD: how could it execute both cases, i mean "if" and "else" blocks at the same time?
how could it execute both cases, i mean "if" and "else" blocks at the same time?
You have to have a clear understanding of how fork works, when you use fork two identical processes are created parent and child and they run simultaneously, when you say filePid = fork() and if the operation is successful then the parent process will hold the process id of the child process and child process will hold 0. So here in parent process filePid == child process ID and in child process filePid == 0.
See man fork
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
So whatever you put in the if (filePid == 0) block will be executed by the child process and whatever you put in the else block will be executed by the parent process simultaneously.
This will be helpful if you want to know more about fork.
fork() system call creates a child process and return its pid so once child is created you have two process running same instruction after fork() one is checking pid is greater which means its parent which gets child pid and in child context OS will set the pid value to 0 so it will enter condition block intended for child
[SOLVED]
So for this practice exercise I was assigned we are practicing process control. I'm simply wondering why it seems that my child process will never execute (when child_pid == 0). Any help on this issue would be greatly appreciated!
Also, safe_fork() is a function our instructor wrote in order to avoid students opening too many processes.
#include "safe-fork.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
int main(void) {
pid_t child_pid;
int pipefd[2];
int pipe_result;
int count;
pipe_result = pipe(pipefd);
if (pipe_result == -1) {
perror("pipe failure");
exit(1);
}
child_pid = safe_fork();
/*Parent Process*/
if (child_pid > 0) {
dup2(pipefd[0], STDIN_FILENO);
scanf("%d", &count);
if (count > 200) {
printf("Long enough!\n");
exit(0);
}
else {
printf("Too short!\n");
exit(1);
}
}
/* Child Process */
else {
dup2(pipefd[1], STDOUT_FILENO);
execl("/usr/bin/wc", "-w");
}
return 0;
}
Here is a suggestion, check for child_pid == 0 explicitly cause it could also be the case that your safe_fork() function failed, also check for those errors i.e child_pid < 0.
Add debug printf statements to check control flow if you already haven't and finally check if the execl call failed.
Also please have a look at this tutorial for creating pipes in C and using them to communicate between a parent and a child process. As I feel there are some issues with how you are handling those file descriptors. A possible reason that you can't see any output is that wc might still waiting for some input.
And another thing you might need to wait for the child process to complete/do something useful or actually be run before checking for its output. Check the other issues first before you worry about this.
Hope this Helps :)
Yes, But no. First you should carefully understand the meaning of fork().
fork(): creates a child process and it returns into TWO PROCESSES, with different return value in each. In parent, it always returns the number that OS has assigned for the newly created child's process id. At the same it returns in newly created child also, as child process will start executing the code copied from parent just after the fork() statement. In child fork always returns zero. So normally after a fork() system call, people check for returned value by fork to differentiate child process and parent process.
particularly in this case after a fork(), there will be two processes with same code and same program states(except both will have different value assigned in child_pid variable). In parent its a non zero value (which is corresponding to child's pid) and in child, its the value zero as the fork returns zero in child.
Now both processes will execute
if (child_pid > 0)
which is true only for parent so parent process will flow into 'if block' and is false for child so it will directly jump to else part and will execute the else block.
What if child_process id is zero?
OS will always assign a non zero value for a child so that fork() will work. And if you have somehow got child process id as zero then parent will fail to enter in 'if block' and will execute else block which is the same as child.
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main ()
{
int i = 3;
int pid;
while(i > 0) {
pid = fork();
if(pid > 0) {
exit(0);
} else {
i--;
}
}
}
How many process are created on that program??? I am still confused with the fork() system calls, can anybody help me to explain this?
What does fork() do?
fork() is an interesting call. You can think of it as cloning the state of your program into two exact copies -- the only difference between them will be the return value of fork(). The process that did the fork() receives the process id (pid) of the new process, while the new process receives 0.
With that in mind:
How many processes are created?
Each time you fork, you create a new process and exit the parent. You do this three times, therefore -- three processes are created by forking. This doesn't include the one that you started by starting the process, of course. :)
during start of you program, system creates 1 process (+1)
i=3, program creates new process (+1), parent exits, child continue
i=2, program creates new process (+1), parent exits, child continue
i=1, program creates new process (+1), parent exits, child continue
i=0, program exit
so, totally - 4 processes, 3 created by program, 1 by system
I have read that system function make use of execl, fork and wait functions internally. So, I tried to simulate working of system without using it. But I am not able to achieve the same working.
When we call a program using system function the code below(after) system() function call also executes. So to simulate system function i wrote this code below:
int main()
{
printf("In controller Start: %d\n\n",getpid());
system("./prog1");
printf("Forking New Process %d\n\n",fork());
printf("Process Id: %d\n\n",getpid());
execl("./infinite",0);
printf("In controller End\n\n");
return 0;
}
In the above code after running "infinite" program the last line does not get printed.
i.e. printf("In controller End\n\n");
What to do in order to print the last line and also execute the "infinite" program without using system function.
It would be great if someone can explain the step by step working of system function like which function is called by system first and so on.
Why execution is not continuing to last line like it must have did if we made a simple function call other than execl.
Foot notes:-
infinite: is a binary file created using C code.
The last line doesn't get printed because it is never executed. The execl function never returns if everything went okay, instead it replaces your program with the one in the call.
I highly recommend you read the manual pages for fork and execl.
In short, fork splits the current process into two, and returns differently depending on if it returns to the parent or the child process. In the child process you then does your exec call, while the parent process continues to do what it wants. The parent must however wait on the child process to finish, or the child process will become what is called a "zombie" process.
In your code, both the parent and the child processes calls exec.
this is basis of fork
/*previous code*/
if((cpid=fork())<0){
printf("\n\tFORK ERROR");
exit(1);
}
if(cpid==0){ /*SON*/
/*CODE FOR SON-your `execl("./infinite",0);` goes here*/
}else{ /*FATHER*/
/*CODE FOR FATHER-your `printf("In controller End\n\n");` */
}
dont forget that when making a fork memory and variables are copied to the SON pid
In your example you do the same thing in both the parent and the child process. You have to check the return value of fork, which indicates if you are in the parent or the child, and then exec in the child, while you wait in your main process.
When you call fork(), both the parent and child process continue executing the same code from that point, but the return value of fork() is different for each. Generally you would do some conditional logic based on that return value.
I would imagine that system() does something like this:
int childpid = fork();
if (childpid) {
/* This is the parent */
wait( childpid );
} else {
/* This is the child */
execl( program_name );
}
Since execl() replaces the current executable with a new one, the child will run that executable then end. The parent will wait for the child to complete then continue.
You are not performing any kind of conditional statement based on the return value of fork. If you don't make sure that one process does the exec and one does something else then both will do the same thing.
You usually want to check against 0 and then execute the program you want to run. 0 signals that everything went ok and you are in the child process.
int main()
{
int pid;
printf("In controller Start: %d\n\n",getpid());
system("./prog1");
pid = fork();
printf("Forking New Process %d\n\n",pid);
printf("Process Id: %d\n\n",getpid());
if (pid == 0) { /* Son process : execute the command */
execl("./infinite",0);
} else { /* Original process : keep working */
printf("In controller End\n\n");
return 0;
}
}
Consider the code:
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>
/* main --- do the work */
int main(int argc, char **argv)
{
pid_t child;
if ((child = fork()) < 0) {
fprintf(stderr, "%s: fork of child failed: %s\n",
argv[0], strerror(errno));
exit(1);
} else if (child == 0) {
// do something in child
}
} else {
// do something in parent
}
}
My question is from where does in the code the child process starts executing, i.e. which line is executed first??
If it executes the whole code, it will also create its own child process and thing will go on happening continuously which does not happen for sure!!!
If it starts after the fork() command, how does it goes in if statement at first??
It starts the execution of the child in the return of the fork function. Not in the start of the code. The fork returns the pid of the child in the parent process, and return 0 in the child process.
When you execute a fork() the thread is duplicated into memory.
So what effectively happens is that you will have two threads that executes the snippet you posted but their fork() return values will be different.
For the child thread fork() will return 0, so the other branch of the if won't be executed, same thing happens for the father thread.
When fork() is called the operating system assigns a new address space to the new thread that is going to spawn, then starts it, they will both share the same code segment but since the return value will be different they'll execute different parts of the code (if correctly split, like in your example)
The child starts by executing the next instruction (not line) after fork. So in your case it is the assignment of the fork's return value to the child variable.
Well, if i understand your question correctly, i can say to you that your code will run as a process already.When you run a code,it is already a process , so that this process goes if statement anyway. After fork(), you will have another process(child process).
In Unix, a process can create another process, that's why that happens.
Code execution in a child process starts from the next instruction following the fork() system call.
fork() system call just creates a seperate address space for the child process therefore it is a cloned copy of the parent process and the child process has all the memory elements of it's parent's process.
Thus, after spawning a child process through fork(), both processes (the parent process and the child process) resumes the execution right from the next instruction following the fork() system call.