Why do we need Zombies in UN*X?

A zombie seems like a waste of space. It's a process that' finished executing, but nobody cares enough about it to wait(2) for it! Why bother keeping a slot in the process table for it? Just so that ps can show it, unkillable, complete with that annoying "Z" code, mocking your feeble efforts to free a process?

A zombie is a process that's called exit(). It's given the operating system a return value. It's now the OS' job to ensure this exit code reaches the "caller" -- aka the parent process. The parent process is expected to call one of the wait*() system calls to get this code and "reap" the zombie; until it does so, the zombie stays. A well-written application will do this, possibly using SIGCHLD.

If the parent process never wait()s, the zombie stays forever. If the parent terminates, the zombie is passed on according to the usual UN*X process rules. Eventually it can reach init, which is always wait()ing. Note, however, that a zombie is a process in a very special state. It can only cease to exist. It is never eligible for CPU time (or memory). The only resource it uses up is a process table slot.