[comp.unix.questions] vfork

chris@mimsy.UUCP (Chris Torek) (06/24/87)

In article <3714@spool.WISC.EDU> lm@cottage.WISC.EDU (Larry McVoy) writes:
>... I'll admit that taking advantage of the semantics of a doomed
>system call is ugly.  But suppose I were to phrase it like this:
>I wasn't taking advantage of vfork, I just had a need for shared
>memory.  Then it's probably ok, right? 

Vfork() is no good for shared memory, since the parent is not run
until the child throws away its own memory via exec() or _exit().
That is, the memory is not *shared*, it is *given away* to the
child until the child no longer needs it.  Without any memory, the
parent process cannot do anything.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

stan@Dixie.Com (Stan Brown) (03/19/91)

	A quick question.  I have run into a couple of packages that
	use a routine called vfork().  My libraries/system cals don't
	include this.

	Could someone tell me how this is different from fork()
	Also any ideas on how to implemet it using fork() (or
	otherwise) would be appreicated.

	Thanks


-- 
Stan Brown	P. c. Design 	404-363-2303	Ataant Ga.
(emory|gatech|uunet) rsiatl!sdba!stan				"vi forever"

hunt@dg-rtp.rtp.dg.com (Greg Hunt) (03/20/91)

In article <8372@rsiatl.Dixie.Com>, stan@Dixie.Com (Stan Brown) writes:
> 
> 	A quick question.  I have run into a couple of packages that
> 	use a routine called vfork().  My libraries/system cals don't
> 	include this.
> 
> 	Could someone tell me how this is different from fork()
> 	Also any ideas on how to implemet it using fork() (or
> 	otherwise) would be appreicated.

The vfork(2) system call does the same thing as the fork(2) system call
except that the child process shares the same address space as the
parent process, instead of having a complete copy of the parent's
address space made for it during the fork.  It uses the same mechanism
as fork(2) to indicate which process is the child (the call returns
zero) and which process is the parent (the call returns the PID of the
child).

This is a more efficient way of forking processes that are simply going
to immediately do an exec(2) of some sort to load and execute a
different executable.  Avoiding the copying of the parent's address
space can save a fair bit of time.

Using vfork(2), however, has some gotchas.  Since the child is sharing
the parent's address space, the child must be extremely careful about
modifiying anything in the address space, since those changes will
affect the parent process when it regains control after the child has
executed an exec(2) of some sort, exit'ed, or terminated abnormally.
This means it can't return from the routine that it's in, and it must
be extremely careful about changing global and local variables, etc.

You should be able to replace the vfork(2) calls with fork(2) calls,
but you need to see what, if any, changes the child is making to the
parent's address space before it does its exec(2) call.  If the child
isn't changing anything, then replacing the vfork(2) calls with fork(2)
calls should work without problems.  If however, the child is changing
parts of the parent's address space, then you'll have to figure out
some other way for the child to communicate those changes to the
parent, since with the fork(2) the child won't be sharing the address
space with the parent.  Maybe you can figure out a way to make the
changes in other local variables before the fork(2), and then have the
parent copy those new local variables into the real local or global
variables that the child wanted to alter.

Hope this helps.  Good luck!

-- 
Greg Hunt                        Internet: hunt@dg-rtp.rtp.dg.com
DG/UX Kernel Development         UUCP:     {world}!mcnc!rti!dg-rtp!hunt
Data General Corporation
Research Triangle Park, NC, USA  These opinions are mine, not DG's.

jb107@prism.gatech.EDU (Jim Burns) (03/20/91)

in article <1991Mar19.181626.28739@dg-rtp.dg.com>, hunt@dg-rtp.rtp.dg.com (Greg Hunt) says:

> The vfork(2) system call does the same thing as the fork(2) system call
> except that the child process shares the same address space as the
> parent process, instead of having a complete copy of the parent's
> address space made for it during the fork.  It uses the same mechanism
> as fork(2) to indicate which process is the child (the call returns
> zero) and which process is the parent (the call returns the PID of the
> child).

The HP-UX man pages state that a particular implementation may make no
distinction between fork(2) and vfork(2), and programs should not depend
on vfork(2)'s distinctions. How true is this generally? If a vendor
provides vfork(2), can it be expected to be different from fork(2), in the
main?
-- 
BURNS,JIM (returned student & GT Research Institute staff member)
Georgia Institute of Technology, Georgia Tech Station 30178,
Atlanta Georgia, 30332            | Internet: jb107@prism.gatech.edu
uucp:	  ...!{decvax,hplabs,ncar,purdue,rutgers}!gatech!prism!jb107

gwyn@smoke.brl.mil (Doug Gwyn) (03/21/91)

In article <8372@rsiatl.Dixie.Com> stan@Dixie.Com (Stan Brown) writes:
>	Could someone tell me how this is different from fork()

Just replace it with fork().  If that doesn't work, the application
is going to need some serious redesign anyway.

rmk@rmkhome.UUCP (Rick Kelly) (03/22/91)

In article <8372@rsiatl.Dixie.Com> stan@Dixie.Com (Stan Brown) writes:

>	A quick question.  I have run into a couple of packages that
>	use a routine called vfork().  My libraries/system cals don't
>	include this.

>	Could someone tell me how this is different from fork()
>	Also any ideas on how to implemet it using fork() (or
>	otherwise) would be appreicated.


In many cases you can probably get the packages to work by changing vfork
to fork.



Rick Kelly	rmk@rmkhome.UUCP	frog!rmkhome!rmk	rmk@frog.UUCP

ralfi@pemcom.pem-stuttgart.de (Ralf U. Holighaus) (03/22/91)

gwyn@smoke.brl.mil (Doug Gwyn) writes:

>In article <8372@rsiatl.Dixie.Com> stan@Dixie.Com (Stan Brown) writes:
>>	Could someone tell me how this is different from fork()

>Just replace it with fork().  If that doesn't work, the application
>is going to need some serious redesign anyway.

That is PARTLY right. vfork differs from fork in a way that it doesn't
copy the complete process data range, so the child of a vfork can ONLY
do an exec, execlp etc. 

Actually with vfork, the sun process shares text and data with the father
process, so the only thing possible after a vfork is either an exit by
the father or an exec by the son. Any other use will cause garbage, be-
cause neither of the two processes has a data rang for it's own.

Regards 

Ralf.
-- 
  PEM Programmentwicklungsgesellschaft    |         Ralf U. Holighaus
        fuer Microcomputer mbH            |         Technical Support
PO-Box 810165 D-7000 Stuttgart 80 Germany | holighaus@pemstgt.PEM-Stuttgart.de
VOICE: x49-711-713045 FAX: x49-711-713047 |       ..!unido!pemcom!ralfi 

pfalstad@phoenix.Princeton.EDU (Paul Falstad) (03/23/91)

ralfi@pemcom.pem-stuttgart.de (Ralf U. Holighaus) wrote:
>gwyn@smoke.brl.mil (Doug Gwyn) writes:
>>In article <8372@rsiatl.Dixie.Com> stan@Dixie.Com (Stan Brown) writes:
>>>   Could someone tell me how this is different from fork()
>>Just replace it with fork().  If that doesn't work, the application
>>is going to need some serious redesign anyway.

Sums it up quite nicely...

>Actually with vfork, the sun process shares text and data with the father
>process, so the only thing possible after a vfork is either an exit by
>the father or an exec by the son. Any other use will cause garbage, be-
>cause neither of the two processes has a data rang for it's own.

Not true.  The parent cannot exit because it's not running; it waits for the
child to exit or exec first.  The child can do whatever it wants to the
parent's data segment before it exit()s or exec()s (except destroy the
parent's stack frame) without causing garbage.  You could even use this call
for a horribly unportable shared memory hack if you wanted.

--
Paul Falstad, pfalstad@phoenix.princeton.edu PLink:HYPNOS GEnie:P.FALSTAD
     To boost the economy, I'd tax all foreigners living abroad.
          Well, at least it's *FRESH* puke!  -Basil Fawlty

torek@elf.ee.lbl.gov (Chris Torek) (03/23/91)

In article <7449@idunno.Princeton.EDU> pfalstad@phoenix.Princeton.EDU
(Paul Falstad) writes:
>The [vfork] parent cannot exit because it's not running; it waits for the
>child to exit or exec first.  The child can do whatever it wants to the
>parent's data segment before it exit()s or exec()s (except destroy the
>parent's stack frame) without causing garbage.  You could even use this call
>for a horribly unportable shared memory hack if you wanted.

Vfork is not really useful for shared memory because (as noted above)
the parent process does not run.  But another statement above, that
children of vfork cannot `destroy the parent's stack frame', is not
correct for (some/many/most?) existing implementations, as even the
stack is shared.

This causes no little concern in the vfork library stub routine, which
must return *before* it makes the system call!  On a Vax, the trick is
(after rewriting Ovfork.s completely, as the old one was too gross):

ENTRY(vfork)
	movl	16(fp),r2	# save return address before we smash it
	movab	here,16(fp)
	ret
here:
	chmk	$SYS_vfork
	bcs	err		# if failed, set errno and return -1
	mnegl	r1,r1		# r1 = 0xffffffff if child, 0 if parent
	bicl2	r1,r0		# r0 &= ~r1, i.e., 0 if child, else unchanged
	jmp	(r2)

err:
	movl	r0,_errno
	mnegl	$1,r0
	jmp	(r2)

The mnegl/bicl2 trick is my fault (it shaves one instruction off the
more straightforward `tstl r1; beql parent; clrl r0; parent:' sequence,
and it avoids branches).
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

torek@elf.ee.lbl.gov (Chris Torek) (03/24/91)

In article <11366@dog.ee.lbl.gov> I wrote:
>[quoting Paul Falstad] ... But another statement above, that
>children of vfork cannot `destroy the parent's stack frame', is not
>correct for (some/many/most?) existing implementations, as even the
>stack is shared.

... which is of course what Paul wrote in the first place.

Just to be absolutely clear on the point:  The child of a vfork must
not return from the function that called vfork, as this could destroy
the (shared) stack frame, causing the parent process to misbehave later.
In some implementations this restriction is relaxed to `if the child
returns, it must not call any other functions'.

These `features' of vfork are subject to change without notice.
-- 
In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427)
Berkeley, CA		Domain:	torek@ee.lbl.gov

ralfi@pemcom.pem-stuttgart.de (Ralf U. Holighaus) (03/26/91)

pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes:

>>Actually with vfork, the sun process shares text and data with the father
>>process, so the only thing possible after a vfork is either an exit by
>>the father or an exec by the son. Any other use will cause garbage, be-
>>cause neither of the two processes has a data rang for it's own.

>Not true.  The parent cannot exit because it's not running; it waits for the
>child to exit or exec first.  The child can do whatever it wants to the
>parent's data segment before it exit()s or exec()s (except destroy the
>parent's stack frame) without causing garbage.  You could even use this call
>for a horribly unportable shared memory hack if you wanted.


     VFORK(2)			   HP-UX		      VFORK(2)




     NAME
	  vfork	- spawn	new process in a virtual memory	efficient way

     SYNOPSIS
	  int vfork()

     REMARKS
	  Vfork	is provided as a higher	performance version of fork on
	  those	systems	which choose to	provide	it and for which there
	  is a performance advantage.

	  Vfork	differs	from fork only in that the child  process  may
	  share	 code  and  data  with	the  calling  process  (parent
	  process).  This speeds the cloning activity significantly at
	  a  risk  to  the integrity of	the parent process if vfork is
	  misused.

	  The use of vfork for any purpose except as a prelude	to  an
	  immediate  exec or exit is not supported.  Any program which
	  relies upon the differences between fork and	vfork  is  not
	  portable across HP-UX	systems.

	  All implementations of HP-UX must provide the	 entry	vfork,
	  but  it  is  permissible for them to treat it	identically to
	  fork.	 Some implementations may not  choose  to  distinguish
	  the two because their	implementation of fork is as efficient
	  as possible, and others may not  wish	 to  carry  the	 added
	  overhead of two similar calls.

     DESCRIPTION
	  Vfork	can be used to	create	new  processes	without	 fully
	  copying  the	address	space of the old process.  If a	forked
	  process is simply going to do	an  exec(2),  the  data	 space
	  copied  from the parent to the child by fork(2) is not used.
	  This is particularly inefficient  in	a  paged  environment.
	  Vfork	 is  useful  in	this case.  Depending upon the size of
	  the  parent's	 data  space,  it  can	give   a   significant
	  performance improvement over fork.

	  Vfork	differs	from  fork  in	that  the  child  borrows  the
	  parent's  memory  and	thread of control until	a call to exec
	  or an	exit (either by	a call to exit(2) or abnormally.)  The
	  parent  process  is  suspended  while	the child is using its
	  resources.

	  Vfork	can normally be	used just like fork. It	does not work,
	  however, to return while running in the child's context from
	  the procedure	which called vfork since the  eventual	return



     Hewlett-Packard Company	   - 1 -   Version B.1,	  Mar 10, 1989






     VFORK(2)			   HP-UX		      VFORK(2)




	  from	vfork  would then return to a no longer	existent stack
	  frame.  Be careful, also, to call exit rather than exit  if
	  you  cannot  exec,  since exit will flush and	close standard
	  I/O channels,	and  thereby  mess  up	the  parent  process's
	  standard  I/O	 data structures.  (Even with fork it is wrong
	  to call exit since  buffered	data  would  then  be  flushed
	  twice.)

	  The [vfork,exec] window begins at the	vfork  call  and  ends
	  when the child completes its exec call.

     RETURN VALUE
	  Upon successful completion, vfork returns a value  of	 0  to
	  the  child  process  and returns the process ID of the child
	  process to the parent	process.  Otherwise, a value of	-1  is
	  returned  to	the  parent,  no child process is created, and
	  errno	is set to indicate the error.

     ERRORS
	  Vfork	will fail and no child process will be created if  one
	  or more of the following are true:

	  [EAGAIN]	 The system-wide limit on the total number  of
			 processes under execution would be exceeded.

	  [EAGAIN]	 The system-imposed limit on the total	number
			 of processes under execution by a single user
			 would be exceeded.

     DEPENDENCIES
	  Series 300, 800
	       A call to signal(2) in the [vfork,exec] window which is
	       used  to	 catch	a  signal  can	affect handling	of the
	       signal by the parent.  This is not true if  the	signal
	       is set SIGDFL or SIGIGN, or if	sigvector(2) is	used.

	  Series 500
	       Shared  memory  segments	  generated   with   the   EMS
	       intrinsics will be inherited over vfork.	Private	memory
	       segments	will not be copied over	vfork.

	       Vfork will also fail in the following cases:

	       [ENOMEM]	      There is not enough physical  memory  to
			      create the new process.

	       [EAGAIN]	      The  child  process  attempts  to	 do  a
			      second  vfork  or	 a  fork  while	in the
			      [vfork,exec] window.

	       The parent and child processes  share  the  same	 stack



     Hewlett-Packard Company	   - 2 -   Version B.1,	  Mar 10, 1989






     VFORK(2)			   HP-UX		      VFORK(2)




	       space  within  the [vfork,exec] window.	If the size of
	       the stack has been changed within this  window  by  the
	       child  process  (return from or call to a function, for
	       example), it  is	 likely	 that  the  parent  and	 child
	       processes will be killed	with signal SIGSEGV.

	  Series 500, 800
	       Process times for the parent and	child processes	within
	       the [vfork,exec]	window may be inaccurate.

	  Series 800
	       The parent and child processes  share  the  same	 stack
	       space  within  the [vfork,exec] window.	If the size of
	       the stack has been changed within this  window  by  the
	       child  process  (return from or call to a function, for
	       example), it  is	 likely	 that  the  parent  and	 child
	       processes will be killed	with signal SIGSEGV or SIGBUS.

     AUTHOR
	  Vfork	 was  developed	 by  the  University  of   California,
	  Berkeley.

     SEE ALSO
	  exec(2), exit(2), fork(2), wait(2).

-- 
  PEM Programmentwicklungsgesellschaft    |         Ralf U. Holighaus
        fuer Microcomputer mbH            |         Technical Support
PO-Box 810165 D-7000 Stuttgart 80 Germany | holighaus@pemstgt.PEM-Stuttgart.de
VOICE: x49-711-713045 FAX: x49-711-713047 |       ..!unido!pemcom!ralfi 

mouse@thunder.mcrcim.mcgill.edu (der Mouse) (03/26/91)

In article <7449@idunno.Princeton.EDU>, pfalstad@phoenix.Princeton.EDU (Paul Falstad) writes:
> [various stuff about vfork()]

> You could even use this call for a horribly unportable shared memory
> hack if you wanted.

I did, once.  The child signaled failure to exec() by setting a
variable before exiting.

I think the program has by now died the death it deserved, thankfully.

					der Mouse

			old: mcgill-vision!mouse
			new: mouse@larry.mcrcim.mcgill.edu

guy@auspex.auspex.com (Guy Harris) (03/27/91)

>That is PARTLY right. vfork differs from fork in a way that it doesn't
>copy the complete process data range, so the child of a vfork can ONLY
>do an exec, execlp etc. 

That's precisely what Doug was referring to; either the application
*doesn't* depend on the fact that, in most if not all current
implementations, "vfork()" causes the parent and child to temporarily
share an address space, in which case the original poster can just
replace the "vfork()" calls with "fork()", or it *does* depend on that,
in which case it will probably require a fair bit of rewhacking in order
to work....

(And if it does depend on that, the author of the application is hereby
asked "Didn't your 'vfork()' manual page tell you not to do that? 
Berkeley's version of the 'vfork()' manual page sure as hell tells you
not to....")

sef@kithrup.COM (Sean Eric Fagan) (03/28/91)

In article <6834@auspex.auspex.com> guy@auspex.auspex.com (Guy Harris) writes:
>That's precisely what Doug was referring to; either the application
>*doesn't* depend on the fact that, in most if not all current
>implementations, "vfork()" causes the parent and child to temporarily
>share an address space, in which case the original poster can just
>replace the "vfork()" calls with "fork()"

Of course, it (the application) may also depend on the fact that the child
is guaranteed to execute *before* the parent (which is an extremely useful
thing, I will admit), in which case you cannot replace it with a fork().

-- 
Sean Eric Fagan  | "I made the universe, but please don't blame me for it;
sef@kithrup.COM  |  I had a bellyache at the time."
-----------------+           -- The Turtle (Stephen King, _It_)
Any opinions expressed are my own, and generally unpopular with others.