fork() why not infinite output - c

why does
int main(...) {
fork();
printf("hello again\n");
exit(0);
}
not create an infinte number of processess?
I understood it as follows, the main process creates a childprocess, the child an other child, and so on.

The execution continues after the fork in both the parent and the child, it doesn't restart the program.

The parent process is "cloned" right at the execution point where fork() is called, and both processes proceed from there. The child process doesn't start over by calling main() again.

Related

Why is my parent process not waiting the second time? C/Unix

So, what I am trying to do is create a child process, have it execute execl and run ls. Then after ls is done, create another child process and have it run a cat command on a file. The second wait(pid) does not seem to wait for the second child process to complete before finishing. here is my code and output
#include <fcntl.h>
int main(){
int pid;
printf("In parent process, creating child now...\n");
pid = fork();
if (pid==0){
printf("Now in child process...\n");
execl("/bin/ls","ls","-l",(char*)0);
}
wait(pid);
printf("ls child process complete\n");
printf("in parent process\n");
printf("Creating another child process\n");
pid=fork();
if(pid==0){
execl("/bin/cat","cat","f1",(char*)0);
}
wait(pid);
return 0;
}
Here is my output
In parent process, creating child now...
Now in child process...
"Contents of ls"
ls child process complete
in parent process
creating another child process
[username#host ~]$ "Contents of file" *cursor*
the parent process seems to finish before the second child is complete. There is only 1 child existing at a time. The "Contents of file" are supposed to appear before the [username#host ~]$ prompt. I think i am misplacing a wait or wrong pid assignment or something. Thanks in advance!
The argument to wait() is not a PID. It's a pointer to an int where the exit status will be stored. You're passing an integer where a pointer is needed, which means:
The program might crash or corrupt some unrelated memory location as soon as you call wait. Its behavior after that point is unpredictable.
You need to enable more compiler warnings and pay attention to them.
Although the Cat process may have finished the disk cache may still be holding the results... Instead of waiting for cat to complete wait until the lock on the file is released.

How system function in C works

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

Where does code Execution start in a child process?

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.

something about process schedule by OS?

I write the following codes and run it in my linux.Everytime after fork the terminals print two PID, which shows both processes are scheduled by the OS, and then it is time for "scanf" to execute, both processes are blocked waiting for the input.However every time I put a number, and then I get the same PID printed on the terminal. Does it mean the same process is invoked by the OS when a terminal IO meets, or something else happens?
int main(int argc, char* argv[])
{
int num;
if(fork() >= 0)
{
printf("%x\n",getpid());
while(1)
{
if(scanf("%d",&num) != EOF)
{
printf("%x\n",getpid());
}
}
}
printf("\nit is over:%x\n", getpid());
}
As Hunter McMillen already noted in comments you are grouping the cases for the parent and child. Now both of them are scheduled as noted by different PIDs outputted and both of them are now waiting at scanf. As soon as you enter data, you are seeing only one PID, because the input you entered was part of one process. Other process ( can be parent or child ) is still waiting for you to enter something. Now, even though your terminal is flooded by a single PID, continuously outputted by one process, try entering some data again and press enter. Now you can see both PIDs being printed!
This is because, in the if() statement, fork() creates child process and runs in an infinite loop. There's a concept of parent process, the parent of child process created using fork() system call. The statement after if() ends, belongs to parent process and here, it will execute only after child process ends. That's why you get the same process ID, that is of child process.

Forking in a loop does not work as thought

I want to have the main process to run and create 4 subprocesses. Once they are created I want the main process to wait for them to finish.
This is my whole code:
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int i;
int childID;
int status;
for (i=0;i<4;i++){
childID=fork();
if (childID==0){
printf("[%d] I the child, will sleep\n", (int)getpid());
sleep(1);
}
}
if (!childID){
wait(&status);
printf("[%d] I the parent, have waited for my children!\n", (int)getpid());
}
return 0;
}
What I get instead is this:
..
[8508] I the child, will sleep
[8503] I the parent, have waited for my children!
[8511] I the child, will sleep
[8510] I the child, will sleep
[8509] I the child, will sleep
[8520] I the child, will sleep
[8511] I the parent, have waited for my children!
[8510] I the parent, have waited for my children!
(prompt stuck)
Why does the parent print out multiple times instead of once, in the end?
Is not the parent who writes multiple times, but the first 3 children. When you fork, the children gets an exact copy of the process including its address space, stack, registers, everything. That means that after the first fork both the parent and the new child will go through the for 3 more times creating 3 new childs. You should break out of the for when executing as the children for the desired effect:
if (childID==0){
printf("[%d] I the child, will sleep\n", (int)getpid());
sleep(1);
break;
}
Look at the pids of the prints. 8510 and 8511 are children, not the original parent. When you fork in the loop, the children are also in that loop. Try putting a break; after the sleep(1).
When you run the loop, once you fork, the child sleeps during the first iteration after it is forked off, but then it forks off more processes. Since childID is no longer 0 for those processes, the do not call wait and so they do not reap their children. This means that when all of the wait calls are completed you will still have processes running, so the terminal will hang.

Resources