#include #include #include #include int main(int argc, char const *argv[]) { // create copy of process if (fork() == 0) { // if this is the child (fork returns 0 to child) printf("hello from child (%d)\n", getpid()); // call `execv` to replace all of this process's state with a new program char * args[] = {"/usr/bin/pwd"}; execv(args[0], args); // exec doesn't usually return (unless there's an error) } else { // this branch represents the parent's continuing execution printf("hello from parent (%d)\n", getpid()); // fork again to make a second child if (fork() == 0) { printf("hello from second child.\n"); exit(0); // exit never returns } int child_status; // wait on one of the children to complete wait(&child_status); printf("child has terminated with status: %d\n", child_status); // wait for the second child wait(&child_status); printf("other child has terminated with status: %d\n", child_status); } // only printed by parent because both children exec/exit before getting to this code printf("bye\n"); return 0; } /* # Demo ## Compile > gcc -g -o testfork testfork.c ## Run within gdb > gdb testfork gdb> break main gdb> run # executes first fork, creating child which then execs and becomes `pwd` gdb> next ## At this point, pstree shows the new pwd child: bash(63240)---gdb(103877)---testfork(103887)-+-pwd(103893) # executes second fork, creating second child gdb> next ## see pstree at this point to see both children, un-reaped: bash(63240)---gdb(103877)---testfork(103887)-+-pwd(103893) `-testfork(103904) # execute the first wait gdb> next ## pstree at this point should have reaped one of the children (could be either) bash(63240)---gdb(103877)---testfork(103887)-+-testfork(103904) ######################################### # In other window: ## List all executing processes > ps aux ## Show all processes (with their pids) as a tree with `systemd` at the root ## In the output, look for the `bash` process that forked this `pstree` command... > pstree -p ## Run pstree filtering to just the terminal which is running these 2 bash shells ## and re-run every second so we can see a "live" view of the process tree > watch -n 1 pstree -p 61040 ## At the point where we've forked both children but haven't executed the wait yet, ## it should look something like this: tmux(61040)-+-bash(63240)---gdb(103877)---testfork(103887)-+-pwd(103893) | `-testfork(103904) `-bash(102610)---watch(103762)---watch(103929)---pstree(103930) */