4 ms·
Learn and use fork(), vfork(), wait() and exec() system calls on Linux
- dogecoinbase 7y agoDon't forget unfork()! https://github.com/whitequark/unfork https://github.com/whitequark/unfork
- joosters 7y agoFollowing is the c-programming example which explains how fork system call works. shashi@linuxtechi ~}$ vim 1_fork.c #include<stdio.h> #include<unistd.h> Int main(void) { printf("Before fork\n"); fork(); printf("after fork\n"); } shashi@linuxtechi ~}$ shashi@linuxtechi ~}$ cc 1_fork.c shashi@linuxtechi ~}$ ./a.out Before fork After fork shashi@linuxtechi ~}$ How exactly is that demonstrating how fork() works? The article is completely missing any explanation - like why 'After fork' was only printed once and not twice as would be initially expected (It's unclear to me: while stdio buffering can cause strangeness if you don't flush buffers before a fork(), surely in this case both processes will exit cleanly and should flush their post-fork outputs?)
- DSMan195276 7y agoIt should print `after fork` two times, they just wrote it wrong. They clearly wrote the whole thing manually, since they used `vim` and not `cat` to display the contents of the file, and they show it printing `After fork` and not `after fork`. I think they just forgot to put the line twice. The fact that they have `Int` and not `int` means their example doesn't actually compile, so I don't think they tested this one.
- tyingq 7y agoSure but doesn't address the article mentions of vfork, wait, waitpid, kill, etc. Or other unmentioned stuff, like variations of kill/killpid().
- moltensodium 7y agoThis example is wrong, it should print "after fork" twice as both processes would run that.
- cfors 7y agoAs another resource, I just finished up the chapters of The Linux Application Programming Interface [0] that described this. Highly recommend this book, its filled with fun tidbits of Linux-lore. [0] https://www.amazon.com/Linux-Programming-Interface-System-Handbook/dp/1593272200 https://www.amazon.com/Linux-Programming-Interface-System-Ha...
- dullgiulio 7y agoAll these systemcalls (except wait(2)) are just facade for clone(2), which has a whole bunch of options. Basically everything from threads to program invocation is just this one powerful systemcall.
- matheusmoreira 7y agoClone is a great system call, it allows the programmer to specify which resources are shared with the new task. The problem with clone is the C standard library maintains global and thread-local state. For example, using clone is not supported by glibc: > If you use clone() you're on your own. https://sourceware.org/bugzilla/show_bug.cgi?id=10311 https://sourceware.org/bugzilla/show_bug.cgi?id=10311 Sometimes it feels like the standard library is holding C back. I wonder how many great Linux-specific features go unused because of it.
- dooglius 7y agoThis looks like more of a case of glibc not working well with one particular combination of options. I don't think libc really holds anyone back considering it does still expose a syscall wrapper.
- dooglius 7y agoNot a very good article IMHO. In addition to not explaining things well, it doesn't discuss posix_spawn or clone which are much preferable and more extensible ways to launch processes.
- inetknght 7y ago> posix_spawn or clone which are much preferable and more extensible ways to launch processes. My understanding is that `fork()` is a nice wrapper around `posix_spawn` and, in particular, `clone()`. And in some ways you're right: as an experienced developer I can really appreciate the extensibility of using `clone()` instead of `fork()`. Unfortunately if I were to use `clone()` _ever_ then I would be immediately chastized by the architecture lead. He's not a C dude. I don't think he even understands the concept of programs sharing an address space (he's also anti-thread). All of it stems from "make programs simple" in an effort to minimize maintenance costs down the road. And in many ways he's right too. `clone()` is anything but simple despite being more extensible and `posix_spawn()` is just a more complex `fork()` in that regard.
- gpderetta 7y ago> My understanding is that `fork()` is a nice wrapper around `posix_spawn` . Not really, you can't implement fork on top of POSIX spawn, but you can do the reverse. On linux they are both implemented on top of a lower lower level primitive (clone).
- dooglius 7y agoposix_spawn is a wrapper around fork/do some setup/exec which is the most common way fork is used. Also, fork is normally implemented as a wrapper around clone FWIW. > I don't think he even understands the concept of programs sharing an address space (he's also anti-thread). Personally, I find it easier to reason about than both the parent and the child having the same return stack but YMMV.
- unilynx 7y agovfork is perfectly predictable as long as you follow the basic rule: only invoke async-signal-safe functions until you call exec. they're explicitly listed but basically boil down to: any functions that more-or-less map directly to a system call, and nothing that could possibly modify process memory or attempt to take a lock (including memory allocation) it's meant for cases where you want to avoid a bit of the fork overhead or if you need to spawn a subprocess from an existing memory-heavy process without getting a KILL from the kernel if overcommit is disabled (as the fork COW doubles your claim on memory even if you don't actually trigger a copy)
- matheusmoreira 7y agoIn general signal safety is lost because the C standard library maintains global and thread-local data. For example, the various I/O functions make use of global buffers. Using the read and write system calls directly is safe: when interrupted, they either report their progress or return EINTR.
- gpderetta 7y ago> vfork is perfectly predictable as long as you follow the basic rule: only invoke async-signal-safe functions until you call exec. Unsurprisingly, that's also true for plain fork in a multithreaded program.
- dooglius 7y agoI disagree, anything not written in inline assembly can potentially lead to the compiler modifying the stack which violates the assumption.
- Animats 7y agoThe fork/exec approach to process launch is a kludge from early PDP-11 UNIX. It's done that way because it had to work when you didn't have enough memory for both program images. Fork originally worked by swapping the process out to disk, then updating the process table so that the in-memory copy and the swapped out copy became separate processes. Most of the troublesome semantics of "fork" come from that history.
- eyberg 7y agoI agree with the authors of https://www.microsoft.com/en-us/research/uploads/prod/2019/04/fork-hotos19.pdf https://www.microsoft.com/en-us/research/uploads/prod/2019/0... that we should not be teaching fork and friends to people anymore except out of historical context. Yes, there is large swaths of software that make extensive use of it but that software should be re-written in my most humble opinion.