System calls are always made by processes to the kernel.
So to answer the specific questions.
- The parent process makes the
wait
call to the kernel.
- The child process makes the
exit
call to the kernel.
The following is a much simplified view of what happens.
When the process calls exit
the kernel stores the argument (the return code
) in the internal process table, destroys all the other resources associated with the process (allocated memory, open file descriptors) and marks the process as a zombie
.
When the parent calls wait
the kernel checks to see if any child is in zombie
state. If so then it gets the stored return code
from the internal process table, releases the slot in the table and returns from the wait
system call passing back the return code
. If the child is not in zombie
state then the kernel blocks the parent process until the child calls exit
.
When any process calls exit
then any remaining child processes are reparented
to the process with PID 1, so all processes except the first always have a parent.
PID 1 starts everything running (network services, listeners on serial lines, the gui login program), and then goes into an infinite loop calling wait
so the kernel process table doesn't fill up with zombies.
There are a lot of things I have simplified, these days you can ask the kernel to reparent to a process other than process number 1 a subreaper, there are lots of forms of the wait
call (wait, waitid, waitpid, wait3, wait4 (man pages), interaction with the ptrace system call, what destroying the allocated resources means etc.