unix fork() understanding - linux

int main(){
fork();
}
I know this is a newbie question, but my understanding is that the parent process now will fork a new child process exactly as the parent one, which means that the child should also fork a child process and so on... In reality, this only generates one child process. I cant understand what code will the child be executing?

The child process begins executing at the exact point where the last one left off - after the fork statement. If you wanted to fork forever, you'd have to put it in a while loop.

As everybody mentioned, the child also starts executing after fork() has finished. Thus, it doesn't call fork again.
You could see it clearly in the very common usage like this:
int main()
{
if (fork())
{
// you are in parent. The return value of fork was the pid of the child
// here you can do stuff and perhaps eventually `wait` on the child
}
else
{
// you are in the child. The return value of fork was 0
// you may often see here an `exec*` command
}
}

You missed a semi-colon.
But the child (and also the parent) is continuing just after the fork happenned. From the point of view of application programming, fork (like all system calls) is "atomic".
The only difference between the two processes (which after the fork have conceptually separate memory spaces) is the result of the fork.

If the child went on to call fork, the child would have two forks (the one that created it and the one that it then made) while the parent would only have one (the one that gave it a child). The nature of fork is that one process calls it and two processes return from it.

Related

Linux pipe example . ipc pipe creation

I was looking through the pipe(2) syscall example in linux, I got this from tldp: http://tldp.org/LDP/lpg/node11.html#SECTION00722000000000000000
When we need to close the input of child process we close fd(1) of child - fine, but we should also close the output of the parent i.e. close fd(0) of parent, why should we use else statement here, in this case the parent's fd(0) will close only when the fork fails, am I correct?
I feel there should not be else statement and both the input of child and output of parent should be closed for communication from child to parent correct?
You shouldn't talk about child input and parent output, that looks like you are referring to stdin and stdout, which is not necessarily the same as the pipe's read and write channels.
For communication from child to parent, the child needs to close the pipe's read channel (fd[0] in your example), and the parent needs to close the pipe's write channel (fd[1]).
Your confusion seems to be more about forking than about pipes.
The else is needed, because we need to execute different code in the parent and in the child. It is very common to use if / else after forking to differentiate the code that executes in each process. Remember that fork(2) returns twice: in the parent, and in the newborn child. It returns the child's pid in the parent, and 0 in the child, so we use that to tell them apart.
In the example you posted, if fork(2) fails, the first if is entered and the process exits. Otherwise, a pair of if / else is used to execute different code in each process.

How to make sure my child executes first and then parent?

Here below i have a simple code snippet of application which takes request from several clients and invokes mathematical operations through exec and waits for result from invoked processes to return those results to the respective clients through pipes
case '+':
fret=fork();
if(fret==-1)
perror(" error in forking at add\n");
else if(fret==0)
{//child
sprintf(s_rp,"%d",p_op[0]);
sprintf(s_wp,"%d",p_op[1]);
argm[0]="add";
if((ret= execve(argm[0],argm,argp))== -1)
{
printf("exeve of add failed \n");
exit(1);
}
}
else
{//parent
write(p_op[1],&request,sizeof(request));
if((ret=waitpid(fret,&x,0))==-1)
perror("Error with wait at +\n");
read(p_op[0],&result,sizeof(result));
write(fd_res,&result,sizeof(result));
}
break;
Here i am facing a simple issue of parent being executing first fastly,which makes the waitpid() to fail,generally waitpid() waits for the child to exit but in my case the child is not even created when parent encounters waitpid() fails
My question is instead of using a sleep() (which has solved my problem but making the program run slow !! ) or any IPC How can i make sure the fork to execute my child first than my parent
when i thought of this, some approaches reeled in my mind, like making use of signals to block parent or semaphores to achieve atomicity is there any simple approach that makes sure my child will execute first and then my parent start execution
The waitpid function will BLOCK until the specified process ends. Although some other reasons such as EINTR can cause waitpid to return -1, it is very easy to solve that by placing the waitpid call into a loop. For example, if waitpid call returned -1 and errno == EINTR, then just continue the loop. See http://linux.die.net/man/3/waitpid about the return value.
Your waitpid call will NEVER be executed before the child process is created! Obviously, the waitpid function is called after the fork syscall, and the return value of the fork syscall is not -1. So, at that time, the fork call has already returned which means that the child process would already exist.

DIFFERENT TASKS ASSIGNED TO DIFFERENT INSTANCES OF FORK() OF A PROCESS IN C

Can I assign different task to different instances of fork() of a process in C ?
like for example:
program.c has been forked 3 times
int main()
{
pid_t pid;
pid = fork();
pid = fork();
pid = fork();
}
now to every instance of fork() I want to do different thing, Can I do this? with forks ? or any other method if favorable? :)
PS: I am testing Real Time Linux and want to check the performance of the Context Switching through forks through Time Constraint.
You can use posix process..
posix_spawn( &Pid,ProgramPath.c_str(), & FileActions,& SpawnAttr,argv,envp);
Check its documentation here.
You always have to test the result of fork(2) (in particular, to handle error cases), and do different things for 0 result (successful in child process), positive result (successful in parent process), negative result (failure, so use perror). So according to that result you can do different things. Often you end up invoking execve(2) for the child process (when fork gives 0), and you usually setup things (e.g. for IPC thru pipe(7)-s) before calling fork.
So to assign a different task after a fork just execute different code according to result of fork
You should read Advanced Linux Programming. It has several chapters explaining all that (so I won't take the time to explain it here).
You could be interested in pthreads (implemented using clone(2) and futex(7), which you should not use directly unless you are implementing your thread library, which is not reasonable).
Try also to strace(1) several programs (including some shell and some basic commands). It will tell which syscalls(2) they are calling. See also intro(2).

How to use vfork to create multiple process?

This is program for vfork(). This program creates multiple parent and child processes and return -1 at the end (mean OS cannot create another process). Why such behaviour happens?
#include<stdio.h>
void main()
{
int pid;
pid=vfork();
printf("pid=%d\n",pid);
if(pid==0)
{
printf("hello\n");
}
}
(1) This creates a single child.
(2) With vfork the child shares memory with the parent until either exec or _exit are called. You call neither.
(3) The parent's execution is suspended until the child calls exec or _exit.
So basically your example is FUBAR. The point of vfork (if there really is one these days) is to provide a fast fork mechanism that will immediately exec another program. The need for this has been vastly diminished with the copy-on-write behavior of regular fork.

Fork()-ing a new process

Fork()-ing a process will end up calling do_fork() inside kernel, making an exact copy of itself. When I read through books, it says that child of fork will call exec to create the new process.
example:
ls command on a shell, will create this way.
sh(Parent)
|
sh(Child)
|
ls(New Process)
But, I am not able to understand how & where the exec*() is called?
Because, All I can see is the shell(child) is what created in fork.
But, when and where will the new process be created/executed?
You have to exec() if you actually want a new program running in one of the processes (usually the child but not absolutely necessary). In your specific case where the shell executes ls, the shell first forks, then the child process execs. But it's important to realise that this is two distinct operations.
All fork() does is give you two (nearly) identical processes and you can then use the return code from fork() to decide if you're the parent (you get the positive PID of the child, or -1 if the fork() failed) or child (you get 0).
See this answer for a description on how fork() and exec() work together (under your control) and how they can be used without each other.
Similar to do_fork(), the exec stuff all boils down to calls to do_execve, located in exec.c.

Resources