Home
| Calendar
| Mail Lists
| List Archives
| Desktop SIG
| Hardware Hacking SIG
Wiki | Flickr | PicasaWeb | Video | Maps & Directions | Installfests | Keysignings Linux Cafe | Meeting Notes | Blog | Linux Links | Bling | About BLU |
Nathan Meyers wrote: | On Sat, Feb 22, 2003 at 04:49:42AM +0000, John Chambers wrote: | > Which reminds me of a question I've never really seen | > answered: How exactly do kernel threads differ from the | > result of a vfork() call? | | In intent, if nothing else. Threads are intended to allow for multiple | threads of execution in the same process space; vfork is intended to | spawn a child whose only purpose is to immediately exec() a different | executable. One description I found somewhere - I'm not sure how accurate | - is that the parent blocks until the new child exec()s a new executable. On the projects where I used vfork(), I never saw this. It would have been a showstopper, of course, and reported as a fatal bug. I do recall warnings in man pages about the dangers of the child process changing memory before the exec; this implies (but doesn't prove) that the parent is running. But it's moot now that vfork is widely implemented as fork, so it can't be used if you want portability. | There's a lot of context management needed to make threads work | properly. Given its limited functionality, vfork() doesn't have to | provide such management - that's more than a documentation difference :-). While this is true for a lot of programs, it isn't true for all. And in any case, system calls are rarely actually needed for much of this. The work can be done in user space (though some sync primitives will require some judicious use of machine language to get atomicity). One example I saw but didn't implement myself: I worked for a while (at Prime, R.I.P.) on a Sys/V unix system that had hundreds of processors. There was a lot of software that had been modified to take advantage of this. This included a version of make that would run subprocesses in parallel when they didn't have common dependencies. This was really slick. On a box with about 200 385 processors, a system build took about 2 minutes. I talked to some of the implementers on one occasion, and found out that modifying make this way wasn't all that difficult. What they said they did was to take advantage of vfork to get multi-tasking withing a single program. The top-level make built the tree of dependencies, which was then a nearly-static global structure. It then called vfork to fire up 2nd-level makes on subtrees that were independent. The only local storage these needed was the command buffer and a few pointers, which could easily be allocated on the stack. Each make could read the entire dependency tree, but only modified its own subtree. A store of an int or a pointer was atomic, so no synchronization was necessary. The 2nd-level makes could also start their own 3rd-level makes, and so on. Each make had to wait on its own children, of course, which again made sync functions other than wait() unnecessary. But note that blocking the parent of a vfork() shoots down this approach, since the parent needs to create multiple children before waiting on all of them. Granted, some multi-threaded programs need interaction between threads, which implies tools to keep them from shooting each other in the foot. But there are also applications where none of this is needed. Some tasks can be divided cleanly into subtasks, in which case a single global memory area is the simple, elegant solution. Such tasks can be handled simply and efficiently by the original vfork(), if it just does the minimal work of creating a new process with its own stack and the parent's data area, and doesn't try to play any other tricky games.
BLU is a member of BostonUserGroups | |
We also thank MIT for the use of their facilities. |