4 ms·
The concept of Fork was not designed to "spawn new programs", it was created to allow parallelism on a single program with several processes collaborating on th
by TuringTest 9y ago
The concept of Fork was not designed to "spawn new programs", it was created to allow parallelism on a single program with several processes collaborating on the same task. It's even in the name (i.e. you fork the program in two, not spawn a new process).
For this purpose, the choice to start with the same data structures and the same execution point is quite sensible - it's essentially what happens when you create a thread nowadays. So, the hypothetical discussion where someone decided to copy the address space in order to launch new programs, would never have happened.
The day where someone decided to reuse the existing fork code to launch processes for new programs, that one must have been worth to watch.
- majewsky 9y ago> it's essentially what happens when you create a thread nowadays I'm not familiar with the guts of threading libs, but AFAIK the syscall that spawns threads is clone(), which takes a function pointer and a stack pointer, so it very much does not start "with the same data structures and the same execution point".
- mcguire 9y agoClone() came much, much later. In fact, the original thread-creation syscall was vfork() in BSD, IIRC.
- tialaramex 9y agoYou're talking about the C library function clone(). The actual system call "clone" on Linux doesn't care about functions, or stack pointers, it just sets a flag like the system call fork did. Everything else is implemented in the library by checking the return code. This is all fine, there are two scenarios, neither of which is the imagined "race" described above: 1. "Fork-and-exec" Our new execution context will actually run a different program. We immediately do so, the new program doesn't care about most of the state of the old program, it throws that state away, including locks that were held by the old program's allocator. 2. "New Thread" Our new context will share all the state, if another thread has a process-wide lock for some reason, it can and should apply to us too. If it took a thread-specific lock, we're not that thread, so we already don't care.
- majewsky 9y ago> You're talking about the C library function clone(). Huh? I saw that the manpage for clone() is in section 2, which AFAIK means it's kernel API, whereas C library functions are usually in section 3. Am I mistaken? Even syscalls(2) refers to clone(2) in its list of syscalls.
- tialaramex 9y agoYeah, no. You are correct that the manual section 2 is "for" system calls, but in practice today these are just the lowest level of the C library, and not the actual system calls. My copy of the clone(2) manual page hints at this by commenting /* For the prototype of the raw system call, see NOTES */ and more explicitly in its body text by saying "The main text describes the wrapper function; the differences for the raw system call are described toward the end of this page." Other modern stuff is the same way, the section 2 documentation is describing what an ordinary C programmer needs to know, but if you're say, implementing the C standard library or writing a compiler for a language that runs on the bare metal you need to read the kernel documentation which is not provided as manual pages.
- chrisseaton 9y ago> The concept of Fork was not designed to "spawn new programs" I thought the fork syscall was the only way to spawn new programs in earlier versions of Unix, and that the spawn syscall only came later. Is that not right? If there was no other syscall, fork must have been designed for this purpose.
- jrochkind1 9y agoThat's false teleology. Not everything we end up with was intentionally designed to end there. Maybe it did not occur to the designers that you would want to create new processes for anything but parallelism; or that if someone did, they would invent a new mechanism for that, instead of deciding it was convenient to re-use and extend the fork mechanism.
- chrisseaton 9y ago> Maybe it did not occur to the designers that you would want to create new processes for anything but parallelism Parallelism? In the original unix? You're talking absolute nonsense. These were single socket, single core systems. How on earth do you think it was designed for parallelism? But we don't even need to debate this - read the 1971 manual. https://www.bell-labs.com/usr/dmr/www/pdfs/man21.pdf https://www.bell-labs.com/usr/dmr/www/pdfs/man21.pdf "fork is the only way new processes are created" exec is also in there, and refers to fork and describes how to use them to run programs.
- dgsb 9y agoParallelism is probably not the correct word, but multi-tasking on I/O seems to have appear early, don't you think ?
- chrisseaton 9y agoYes multi-tasking, or concurrency, but not parallelism!
- jsnell 9y agoThere is no way parallelism was the reason for fork. It was a PDP-7, so there was no parallelism in the first place. And even worse, I believe only one user-mode process was in memory at a time; any process switch meant swapping out the current process and swapping in a new one. There was also no form of interprocess communication other than the filesystem, nor any synchronization other than waiting for a specific process to exit. So having multiple processes work on the same problem would mostly have been very awkward.
- mcguire 9y ago"There was also no form of interprocess communication other than the filesystem..." Until Doug McIlroy invented pipes. And the modern Unix shell pipeline style of creating complex programs.
- kindfellow92 9y ago> The concept of Fork was not designed to "spawn new programs", it was created to allow parallelism on a single program with several processes collaborating on the same task. It's even in the name (i.e. you fork the program in two, not spawn a new process). I really doubt this. Is there an instance of a program with 1st edition lineage that use processes to achieve concurrency? There were pipes, sure, but that could be achieved with a spawn-like call. I don’t see processes being used for concurrency in UNIX history until BSD sockets and forking servers emerged.
- mcguire 9y agoWell, yes, fork()/exec() and spawn-like things are capable of doing the same things, more or less. On the other hand, shell pipelines were used for concurrency before BSD added networking code. And I have doubts that shell pipelines would have developed without the fork()/exec() model---see the author's Windows NT (and earlier) with really, seriously broken shell models.
- fiddlerwoaroof 9y agospawn() is relatively new and does what used to be done with fork()/exec().
- cryptonector 9y agoWhatever the original purpose, the purposes it actually served were: a) spawning new processes (fork() then exec()) with the spawn code implemented in user-land, thus enabling agile shell development, and b) parallelism. I would argue that (a) was easily the most important aspect of fork(). One can always get (b) by spawning more instances of the same program and passing them whatever state is to be shared. But (a) needs a decent API and to be kernel-side if one has no fork(). Yes, posix_spawn() is better, but fork() enabled Unix to kick the can of standardizing a spawn API that doesn't suck until enough experience was had with it to make such a thing.