[comp.arch] UNIX fork

srg@quick.COM (Spencer Garrett) (09/28/87)

In article <7672@felix.UUCP>, preston@felix.UUCP (Preston Bannister) writes:
} In article <838@usfvax2.UUCP> chips@usfvax2.UUCP (Chip Salzenberg) writes:
} 
} >There is one thing about UNIX fork()-exec() that you've overlooked --
} >after the fork(), the child process can set up the environment of the
} >soon-to-be-exec'ed process by modifying its own environment.
} >(Can you say `pipes, I/O redirection and current directory'?
} >I knew you could.)
} 
} What I should have said :-) was that the
} code executed between the fork() and exec() call typically does not
} need the full semantics of fork().

Indeed it does not.  That's why Berkeley has vfork().  A vfork call
"borrows" the parent's memory instead of copying it.  The parent is
kept in suspended animation while the child modifies the new environment.
When the child exec's (or exit's) the memory is given back to the
parent instead of being freed.

kent@tifsie.UUCP (Russell Kent) (09/30/87)

in article <125@quick.COM>, srg@quick.COM (Spencer Garrett) says:
> Xref: tifsil comp.arch:734 comp.unix.wizards:1187 comp.os.minix:494
> 
> In article <7672@felix.UUCP>, preston@felix.UUCP (Preston Bannister) writes:
> } What I should have said :-) was that the
> } code executed between the fork() and exec() call typically does not
> } need the full semantics of fork().
> 
> Indeed it does not.  That's why Berkeley has vfork().  A vfork call
> "borrows" the parent's memory instead of copying it.

This (perhaps unfortunately) includes the information about open FILEs and
file descriptors, which precludes the redirection of the child's streams
without a good deal of work by the parent to recover.  Preston's objections
to the fork()/exec() concepts are valid; they glob together concepts
which should have been kept separate.  Unfortunately, the inertia of all
those programs running already will probably preclude us from re-defining
the process startup primitives.  An alternative solution to the problem
of poor performance during the fork() is to use a copy-on-write algorithm
which gradually duplicates the parent's address space as the parent or child
attempts to change values.  (Can you say real MMU? :-)

-- 
Russell Kent			Phone: +1 214 995 3501
Texas Instruments - MS 3635	Net mail:
P.O. Box 655012			...!{ihnp4,uiucdcs}!convex!smu!tifsie!kent	
Dallas, TX 75265		...!ut-sally!im4u!ti-csl!tifsie!kent

chris@mimsy.UUCP (10/04/87)

In some article (the quoting was improper, and I have forgotten who)
someone writes:
>>... That's why Berkeley has vfork().  A vfork call
>>"borrows" the parent's memory instead of copying it.

In article <246@tifsie.UUCP> kent@tifsie.UUCP (Russell Kent) replies:
>This (perhaps unfortunately) includes the information about open FILEs and
>file descriptors, which precludes the redirection of the child's streams
>without a good deal of work by the parent to recover.

Not so.  Were this the case, vfork() would be nearly useless.
Vfork borrows the parent's *memory*; this does not include its
kernel space information, such as file descriptors.  (`FILE *'s
are indeed borrowed; the child is simply not supposed to muck about
with them.)

>... An alternative solution to the problem of poor performance during
>the fork() is to use a copy-on-write algorithm which gradually duplicates
>the parent's address space as the parent or child attempts to change
>values.

The standard objection to this is that the parent is likely
immediately to change some values, and that it may be cheaper to
duplicate the entire process once than to do it piecemeal.  A
standard solution is for the child to `borrow' the parent's memory
(read only) until it exec()s or some short time has passed, after
which the parent is allowed to continue regardless.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

richard@aiva.ed.ac.uk (Richard Tobin) (10/16/87)

In article <8904@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>Vfork borrows the parent's *memory*; this does not include its
>kernel space information, such as file descriptors.  (`FILE *'s
>are indeed borrowed; the child is simply not supposed to muck about
>with them.)

Indeed, it would usually be pointless to muck about with them, because
they're going to disappear when the child execs another program.  The
things that are shared between the parent and child are just the things
that don't survive an exec.
-- 
Richard Tobin,                         JANET: R.Tobin@uk.ac.ed             
AI Applications Institute,             ARPA:  R.Tobin%uk.ac.ed@nss.cs.ucl.ac.uk
Edinburgh University.                  UUCP:  ...!ukc!ed.ac.uk!R.Tobin

mouse@mcgill-vision.UUCP (der Mouse) (11/18/87)

In article <179@aiva.ed.ac.uk>, richard@aiva.ed.ac.uk (Richard Tobin) writes:
> In article <8904@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes:
>> Vfork borrows the parent's *memory*; this does not include its
>> kernel space information, such as file descriptors.

True, though file descriptors are a bad example - the child gets clones
of the parent's file descriptors with vfork() just as it does with
fork().

> Indeed, it would usually be pointless to muck about with [the
> parent's stdio streams], because they're going to disappear when the
> child execs another program.  The things that are shared between the
> parent and child are just the things that don't survive an exec.

In fact, this is the whole point of vfork() - share the things that can
be given back on exec().

However, it is not quite "pointless" to mess with stdio streams.
Consider the following program:

main()
{
 printf("xxx");
 if (vfork() == 0)
  { printf("yyy");
    exec(....);
    _exit(1);
  }
 printf("zzz\n");
}

(note the lack of fflush()es).  This will print xxxyyyzzz\n, for the
printf in the child is merely buffered - and the buffer is shared.  If
we add fflush(stdout); after printf("yyy"); then we get xxxyyyzzz\n as
before, though for different reasons: the child's fflush empties the
stdio buffer, which remains emptied when the parent gets the memory
back.

Of course, it *is* a bad idea for the child to mess around with
anything the parent owns (such as is done in the above code), because
code depending on the sharing semantics will break when someone finally
fixes fork() to do a proper copy-on-write fork, and thus eliminates the
need for vfork() and makes it equivalent to fork().

					der Mouse

				(mouse@mcgill-vision.uucp)

mash@mips.UUCP (John Mashey) (11/24/87)

In article <909@mcgill-vision.UUCP> mouse@mcgill-vision.UUCP (der Mouse) writes:
...
>code depending on the sharing semantics will break when someone finally
>fixes fork() to do a proper copy-on-write fork, 

Many UNIXes, including SVR3 already do copy-on-write forks.
-- 
-john mashey	DISCLAIMER: <generic disclaimer, I speak for me only, etc>
UUCP: 	{ames,decwrl,prls,pyramid}!mips!mash  OR  mash@mips.com
DDD:  	408-991-0253 or 408-720-1700, x253
USPS: 	MIPS Computer Systems, 930 E. Arques, Sunnyvale, CA 94086

berke@acf8.UUCP (Wayne Berke) (11/27/87)

> main()
> {
>  printf("xxx");
>  if (vfork() == 0)
>   { printf("yyy");
>     exec(....);
>     _exit(1);
>   }
>  printf("zzz\n");
> }
> 
> (note the lack of fflush()es).  This will print xxxyyyzzz\n, for the

It could also print "xxxzzz\nyyy".  You're dealing with a parallel program
here!

Wayne Berke (berke@nyu.edu)

berke@acf8.UUCP (Wayne Berke) (11/28/87)

Re: my earlier posting.

Woops.  I didn't know that vfork caused an implicit wait() in the parent.
Thus the original program was NOT parallel.  My thanks to those who
corrected me.

Wayne Berke