All process terminations are handled by the do_exit( ) function, which removes most references to the terminating process from kernel data structures. The do_exit( ) function executes the following actions:
1. Sets the pf_exiting flag in the flag field of the process descriptor to indicate that the process is being eliminated.
2. Removes, if necessary, the process descriptor from an IPC semaphore queue via the sem_exit( ) function (see Chapter 19) or from a dynamic timer queue via the del_timer_sync( ) function (see Chapter 6).
3. Examines the process's data structures related to paging, filesystem, open file descriptors, and signal handling, respectively, with the _ _exit_mm( ), _ _exit_files( ), _ _exit_fs( ), and exit_sighand( ) functions. These functions also remove each of these data structures if no other process are sharing them.
4. Decrements the resource counters of the modules used by the process.
5. Sets the exit_code field of the process descriptor to the process termination code. This value is either the _exit( ) system call parameter (normal termination), or an error code supplied by the kernel (abnormal termination).
6. Invokes the exit_notify( ) function to update the parenthood relationships of both the parent process and the child processes. All child processes created by the terminating process become children of another process in the same thread group, if any, or of the init process. Moreover, exit_notify( ) sets the state field of the process descriptor to task_zombie. We shall see what happens to zombie processes
7. Invokes the schedule( ) function (see Chapter 11) to select a new process to run. Since a process in a task_zombie state is ignored by the scheduler, the process stops executing right after the switch_to macro in schedule( ) is invoked.
Was this article helpful?