6

Considering the below code :

int main()
{
  int pid;
  pid=vfork();
  if(pid==0)
     printf("child\n");
  else
     printf("parent\n");
  return 0;
  }

In case of vfork() the adress space used by parent process and child process is same, so single copy of variable pid should be there. Now i cant understand how this pid variable can have two values returned by vfork() i.e. zero for child and non zero for parent ?

In case of fork() the adress space also gets copied and there are two copy of pid variable in each child and parent, so I can understand in this case two different copies can have different values returned by fork() but can't understand in case of vfork() how pid have two values returned by vfork()?

L.ppt
  • 524
  • 6
  • 21
  • 2
    That's lethal - you can `exec()` or `_exit()` in the [`vfork()`](http://pubs.opengroup.org/onlinepubs/009695399/toc.htm)'d child, but that's just about it. Pretty much anything else leads to undefined behaviour. Recommendation: don't use [`vfork()`](http://pubs.opengroup.org/onlinepubs/007908799/xsh/vfork.html); indeed, I wouldn't even bother to learn how to use it safely. It's like `gets()`, a function that it is best to pretend doesn't exist. – Jonathan Leffler Feb 19 '12 at 09:08
  • 1
    @JonathanLeffler: `vfork()` is quite useful for MMU-less systems. – ninjalj Feb 19 '12 at 09:26
  • Yes sir, I agree with u we should not use it, but I was using vfork to solve one problem of creating process tree and communication between processes of different levels of tree, in that case vfork was useful taking some global variable. I'll keep ur advice. – L.ppt Feb 19 '12 at 09:28
  • @L.ppt: ummm. no, that's a bad use of vfork(). Better use some real IPC (shared memory, sockets, pipes, ...), or, if you really really know what you are doing, threads. – ninjalj Feb 19 '12 at 09:41
  • @ninjalj : hmm I'll try same problem using pipes with fork system call. – L.ppt Feb 19 '12 at 10:54
  • @ninjali: `vfork()` is only useful if you are about to execute something else with no I/O redirection or any other changes and no intention of reporting errors on failure to execute except via the exit status. For my work, the inability to report errors would be crucial, and the restrictions are so severe that it makes more sense to use `fork()`. I don't get to work on MMU-less POSIX systems, and haven't done so in æons. For most people, most of the time, my advice is valid. As with any sweeping rule, there is a well-informed (usually tiny) minority who can break it with impunity; go for it! – Jonathan Leffler Feb 19 '12 at 15:50
  • `vfork` is very useful because it can be the only way to create a child process if your process's private writable core is extremely large. Calling `fork`, even if you `exec` right afterwards, will momentarily double the required commit charge, which could cause allocations in other programs to fail - or more likely `fork` itself will just fail with out-of-memory. `vfork` on the other hand contributes at most a few pages to the commit charge. Of course nowadays there's `posix_spawn` which should use `vfork` behind the scenes to achieve the same results... – R.. GitHub STOP HELPING ICE Feb 19 '12 at 16:36
  • 1
    I'll translate R..'s comment: `vfork()` is useful for spawning processes from Java (where else can you find such large address space wastage?), and indeed Java 1.7 seems to have added support for `vfork()` and `posix_spawn()`. – ninjalj Feb 20 '12 at 20:03

1 Answers1

6

There aren't 2 copies. When you cal vfork the parent freezes while the child does its thing (until it calls _exit(2) or execve(2)). So at any single moment, there's only a single pid variable.

As a side note, what you are doing is unsafe. The standard spells it clearly:

The vfork() function shall be equivalent to fork(), except that the behavior is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit() or one of the exec family of functions.

As a second side note, vfork has been removed from SUSv4 - there's really no point in using it.

cnicutar
  • 178,505
  • 25
  • 365
  • 392
  • It means that while usinng vfork the created process can modify the the value of **pid_t** variable type so when child exits and parent resumes how or by whom the previous value of **pid_t** variable is restored?? ? – L.ppt Feb 19 '12 at 09:20
  • 2
    @L.ppt When the parent continuse `pid_t` will store the PID of the child. – cnicutar Feb 19 '12 at 09:23
  • 2
    @L.ppt: the compiler treats specially a `pid_t` variable returned from `vfork()`. It's always on a register, and doesn't spill to memory. – ninjalj Feb 19 '12 at 09:28
  • 1
    I don't see how special treatment is necessary. The return in the parent happens **after** the child is done using the parent's memory, so the new return value will be seen. The only thing that must be saved in a register across `vfork` is the return address, since the child will potentially clobber the return address if it's just saved on the stack. – R.. GitHub STOP HELPING ICE Feb 19 '12 at 16:42
  • 1
    @R..: that makes sense. It seems I was reading too much into _"modifies any data other than a variable of type pid_t"_ . So `vfork()` needs the libc-level support you mentioned (saving/restoring the return address in a register), and possibly disallowing some compiler optimizations on functions that call `vfork()` (GCC seems to disallow tail call optimization, global common subexpresion elimination and jump bypassing for functions that call `vfork()` or `setjmp()`). – ninjalj Feb 20 '12 at 19:59