About the vfork () system call?

#include <stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
   pid_t child_pid = vfork();

   if(child_pid < 0)
   {
       printf("vfork() error\n");
       exit(-1);
   }
   if(child_pid != 0)
   {
       printf("Hey I am parent %d\nMy child is %d\n",getpid(),child_pid);
       wait(NULL);
   }

   else
   {
       printf("Hey I am child %d\nMy parent is %d\n",getpid(),getppid());
       execl("/bin/echo","echo","hello",NULL);
       exit(0);
   }
   return 0;
}

      

output:

 Hey I am child 4
 My parent is 3
 Hey I am parent 3
 My child is 4
 hello

      

My question is, why is "hello" printed after the parent process has executed? I started learning vfork (). Can anyone help me with this?

+3


source to share


2 answers


After the parent process is executed, it goes into wait(NULL);

, which blocks the parent process until the child process calls execl()

or exit

.

Therefore, the child process, when the parent is blocked, calls execl()

and therefore hello

prints at the end of the output.

#include <stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
pid_t child_pid = vfork();

if(child_pid < 0)
{
   printf("vfork() error\n");
   exit(-1);
}
if(child_pid != 0)
{
   printf("Hey I am parent %d\nMy child is %d\n",getpid(),child_pid);
   wait(NULL);
 }

 else
 {
   printf("Hey I am child %d\nMy parent is %d\n",getpid(),getppid());
   execl("/bin/echo","echo","hello",NULL);
   exit(0);
  }
 return 0;
  }

      



If you delete execl()

, the child process will jump to exit(0)

and hello

won't be printed.

Also, once executed, execl()

it creates a new process, so any code you write after execl()

will not be executed. According to the man page: -

The exec () family of functions replaces the current process image with a new process image. The functions described in this man page are interfaces to execve (2). (For more information on replacing the current process image, see the execve (2) man page.)

+2


source


First advice: don't use vfork()

. In a modern system, the benefits of using vfork()

over are fork()

tiny. The code you show will never be able to work fine with vfork()

, because it causes undefined behavior:

POSIX.1:

The function vfork()

has the same effect as fork()

, except that the behavior is undefined if the process created         vfork()

changes any data other than the type variable pid_t

       used to store the return value from vfork()

or returned from the function in which it was called vfork()

, or calls any other function before a successful call _exit()

or one of the exec()

       function family .

So, by calling printf()

in your child code, your code is already undefined. Note that even the call exit()

will result in undefined behavior, only _exit()

allowed.


I assume you try this on Linux, which defines the behavior a vfork()

little more and in a way that explains what you are seeing:

From linux man vfork()

page
:



vfork()

differs from fork(2)

that the calling thread is suspended until the child exits (usually by calling _exit(2)

, or abnormally after delivery of a fatal signal) or it calls         execve(2)

. Up to this point, the child shares all memory with its parent, including the stack.

So, on Linux, you can be sure that the child created with vfork()

is executed first and only on your call execl()

(which is called execve()

inside) the parent process is allowed to continue. This is the reason why you see parenting output after your child's output. As soon as the parent calls wait()

, he waits for the child to finish - at which point the child is replaced by echo

.

Relying on this behavior, your program is not portable across different implementations vfork()

. The call printf()

is good because Linux suspends the parent process, and the call is wrong , exit()

it doesn't matter here: anything after the call exec*()

is not available anyway (those functions never return, they replace the running program)!

It vfork()

was removed from POSIX in POSIX.1-2008 due to its strange semantics and enormous risk of errors . A safe and modern POSIX replacement for the typical usecase vfork()

followed by a exec*()

is posix_spawn()

.


All in all, you really shouldn't be using vfork()

. Use instead fork()

. Remove the unreachable call exit()

and your program looks fine.

+2


source







All Articles