[git commit] update FAQ

Denys Vlasenko vda.linux at googlemail.com
Fri Jun 12 13:23:12 UTC 2009


commit: http://git.busybox.net/busybox-website/commit/?id=8182b74b5b58aa915bedb667fddcb9c9b4d3046a
branch: http://git.busybox.net/busybox-website/commit/?id=refs/heads/master


Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 FAQ.html |   64 ++++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 34 insertions(+), 30 deletions(-)

diff --git a/FAQ.html b/FAQ.html
index 7ed1394..7aca694 100644
--- a/FAQ.html
+++ b/FAQ.html
@@ -296,7 +296,7 @@ within each applet.  More build coverage testing.</p></li>
 	does not include the features i want?</a></h2>
 
 <p>
-	we maintain such a <a href="tinyutils.html">list</a> on this site!
+	We maintain such a <a href="tinyutils.html">list</a> on this site!
 </p>
 
 <hr />
@@ -871,18 +871,26 @@ second argument to pw_encrypt(text,buffer).</p>
 
 <p>On systems that haven't got a Memory Management Unit, fork() is unreasonably
 expensive to implement (and sometimes even impossible), so a less capable
-function called vfork() is used instead.  (Using vfork() on a system with an
-MMU is like pounding a nail with a wrench.  Not the best tool for the job, but
-it works.)</p>
+function called vfork() is used instead.</p>
 
 <p>Busybox hides the difference between fork() and vfork() in
-libbb/bb_fork_exec.c.  If you ever want to fork and exec, use bb_fork_exec()
-(which returns a pid and takes the same arguments as execve(), although in
-this case envp can be NULL) and don't worry about it.  This description is
-here in case you want to know why that does what it does.</p>
-
-<p>Implementing fork() depends on having a Memory Management Unit.  With an
-MMU then you can simply set up a second set of page tables and share the
+libbb.  If you ever want to fork and exec, use [x]spawn(argv)
+(which returns a pid) + waid4pid(pid) (which returns exitcode),
+or even spawn_and_wait(argv).</p>
+
+<p>Making program to daemonize is trickier. Usually, it's done by
+forking, and exiting <b>in parent</b>, leaving child to continue to run.
+This is not possible with vfork, because with vfork, while child
+is running, parent does not return from vfork, and therefore it can't exit.
+It can be worked around by execing the same program with same parameters
+after vfork in child. This unblocks parent, which can then exit.
+bb_daemonize_or_rexec(flags, argv) hides all NOMMU machinery
+of this process. Consult comments in libbb.h for details.</p>
+
+<p>This description is here in case you want to know gory details.</p>
+
+<p>Implementing fork() depends on having a Memory Management Unit.  With
+a MMU you can simply set up a second set of page tables and share the
 physical memory via copy-on-write.  So a fork() followed quickly by exec()
 only copies a few pages of the parent's memory, just the ones it changes
 before freeing them.</p>
@@ -905,7 +913,7 @@ redirect them to the new locations is not an easy problem.)</p>
 
 <p>So with a primitive or missing MMU, fork() is just not a good idea.</p>
 
-<p>In theory, vfork() is just a fork() that writeably shares the heap and stack
+<p>In theory, vfork() is just a fork() that writeably shares process memory
 rather than copying it (so what one process writes the other one sees).  In
 practice, vfork() has to suspend the parent process until the child does exec,
 at which point the parent wakes up and resumes by returning from the call to
@@ -921,40 +929,36 @@ itself: both assignments write into the same memory location.</p>
 the parent does a setjmp and then continues on (pretending to be the child)
 until the exec() comes around, then the _exec_ does the actual fork, and the
 parent does a longjmp back to the original vfork call and continues on from
-there.  (It thus becomes obvious why the child can't return, or modify
-local variables it doesn't want the parent to see changed when it resumes.)
+there.  (It thus becomes obvious why the child should not return (this would
+destroy data on stack needed by parent), or modify any memory variables
+it doesn't want the parent to see changed when it resumes.)
 
 <p>Note a common mistake: the need for vfork doesn't mean you can't have two
 processes running at the same time.  It means you can't have two processes
 sharing the same memory without stomping all over each other.  As soon as
 the child calls exec(), the parent resumes.</p>
 
-<p>If the child's attempt to call exec() fails, the child should call _exit()
-rather than a normal exit().  This avoids any atexit() code that might confuse
-the parent.  (The parent should never call _exit(), only a vforked child that
-failed to exec.)</p>
-
-<p>(Now in theory, a nommu system could just copy the _stack_ when it forks
-(which presumably is much shorter than the heap), and leave the heap shared.
-Even with no MMU at all
-In practice, you've just wound up in a multi-threaded situation and you can't
-do a malloc() or free() on your heap without freeing the other process' memory
-(and if you don't have the proper locking for being threaded, corrupting the
-heap if both of you try to do it at the same time and wind up stomping on
-each other while traversing the free memory lists).  The thing about vfork is
-that it's a big red flag warning "there be dragons here" rather than
-something subtle and thus even more dangerous.)</p>
+<p>If the child's attempt to call exec() fails, the child usually calls
+_exit() rather than a normal exit().  This avoids any atexit() code that
+might confuse the parent. In most circumstances, fflush(stdout) and _exit()
+is good enough.</p>
+
+<p>Another thing to keep in mind is that if vforked child allocates any memory
+and does not free it before exec or exit, parent will also have this memory
+allocated. Unless child takes care to record the address of these memory areas
+and parent frees them, they will be leaked. This should be avoided
+if parent process is long lived. The prime example is the shell.</p>
 
 <hr />
 <h2><a name="tips_sort_read">Short reads and writes</a></h2>
 
-<p>Busybox has special functions, bb_full_read() and bb_full_write(), to
+<p>Busybox has special functions, full_read() and full_write(), to
 check that all the data we asked for got read or written.  Is this a real
 world consideration?  Try the following:</p>
 
 <pre>while true; do echo hello; sleep 1; done | tee out.txt</pre>
 
-<p>If tee is implemented with bb_full_read(), tee doesn't display output
+<p>If tee is implemented with full_read(), tee doesn't display output
 in real time but blocks until its entire input buffer (generally a couple
 kilobytes) is read, then displays it all at once.  In that case, we _want_
 the short read, for user interface reasons.  (Note that read() should never
-- 
1.6.0.6


More information about the busybox-cvs mailing list