7. The difference between exit and _exit
In order to understand the differences between these two system calls, we first discuss the problem of the file memory buffer. In Linux, standard input and output (I/O) functions are processed as files. Corresponds to each open file, there is a corresponding cache in memory, each time the file is read, read more records into the cache, so that the next time the file is read in the cache, but also in the file is written in the corresponding cache, is not directly written to the hard disk file, A certain condition (such as reaching a certain number, encountering a newline character \ n or the end-of-file sign EOF) will actually write the data to the file. The advantage of this is that it speeds up file read and write. But this also poses some problems, such as having some data that we think has been written to the file, but actually does not meet certain conditions and still resides in the memory cache, so if we directly terminate the process with the _exit () function, it will result in data loss. If you change to exit, there will be no data loss problem, which is the difference between them. To explain the problem, it involves the steps of their work.
Exit (): The previous source code analysis shows that when the function is executed, the process checks for file opening, cleans the I/O cache, and if there is data in the cache, writes them to the appropriate file, preventing the loss of file data and then terminating the process.
_exit (): When the function is executed, the standard input output cache is not cleaned up, but the memory space is cleared, and of course the data in the file cache that has not yet been written to the file is destroyed. This shows that using the exit () function is more secure.
In addition, there are different header files for their differences. Exit () in Stdlib.h, _exit () is in unistd.h. In general, exit (0) indicates normal exit, exit (1), Exit (-1) for exception exit, 0, 1,-1 is the return value, the specific meaning can be customized. Also note that return returns the function call and, if the main function is returned, exits the program. Exit is forced to exit the program at the point of invocation, and runs the program at the end.
The following is the complete Linux process run process:
[Plain]View PlainCopy
- Arch/x86/include/asm/unistd_32.h:fork () User space to invoke (e.g. C program)
- --->int $0x80 generates 0x80 soft interrupt
- --->arch/x86/kernel/entry_32.s:entry (system_call) Interrupt handler System_call ()
- ---> Execute save_all macro to save all CPU register values
- --->arch/x86/kernel/syscall_table_32.s:entry (sys_call_table) system calls a multi-path decomposition table
- --->arch/x86/kernel/process_32.c:sys_fork ()
- --->kernel/fork.c:do_fork () copy the original process into another new process
- --->kernel/fork.c:copy_process ()
- --->struct task_struct *p; Defining a new Process descriptor (PCB)
- Legality check of--->clone_flags sign
- --->security_task_create () security check (SELinux mechanism)
- --->kernel/fork.c:dup_task_struct () copy process descriptor
- --->struct thread_info *ti; Defining the thread information structure
- --->alloc_task_struct () allocates memory for the new PCB
- --->kernel/fork.c:arch_dup_task_struct () Copy the PCB of the parent process
- --->atomic_set (&tsk->usage,2) Sets the PCB usage counter to 2, indicating the active state
- --->copy_creds () Copy Permissions and identity information
- ---> Detect whether the total number of processes exceeds max_threads
- ---> Initialize each field in the PCB
- --->sched_fork () Scheduler Related Settings
- ---> Copy process All information Copy_semundo (), Copy_files (),
- --->copy_signal (), copy_mm ()
- --->copy_thread () replication thread
- --->alloc_pid () assigning PID
- ---> Update properties and Count of processes
- --->kernel/sched.c:wake_up_new_task () put the process on the run queue and let the scheduler Dispatch
- --->kernel/sched.c:select_task_rq () Select the best CPU (multiple CPUs in SMP)
- --->p->state = task_running set to task_running status
- --->activate_task ()
- --->enqueue_task () inserts the current process into the runqueue of the corresponding CPU
- ---> Clone_vfork flag: Wait_for_completion () blocks the parent process and waits for the child process to end
- ---> Return the assigned PID
- Kernel/sched.c:schedule () scheduling a newly created process
- Process in operation
- Exit () User space to invoke (e.g. C program)
- --->0x80 interrupt jumps to Include/linux/syscalls.h:sys_exit ()
- --->kernel/exit.c:do_exit () is responsible for the process exit
- --->struct task_struct *tsk = current; Get my PCB
- --->set_fs (user_ds) settings using the file system mode
- --->exit_signals () clears the signal processing function and sets the PF_EXITING flag
- ---> Purge process a series of resources exit_mm (), Exit_files ()
- --->exit_fs (), Exit_thread ()
- --->kernel/exit.c:exit_notify () exit notification
- --->forget_original_parent () adoptive all my sub-processes to the INIT process
- --->kill_orphaned_pgrp () sends a pending signal to processes within the process group Sighup and Sigcont
- --->tsk->exit_signal = SIGCHLD; Send a SIGCHLD signal to my parent process
- --->kernel/exit.c:do_notify_parent () notifies the parent process
- ---> returns DEATH_REAP if the parent process processes the SIGCHLD signal
- ---> If the parent process does not process the SIGCHLD signal, returns the signal value when it is passed in
- --->__wake_up_parent () wakes the parent process
- ---> Notifications return death_reap, set Exit_state to Exit_dead I quit and die.
- ---> Otherwise set me up for Exit_zombie I quit but not dead, become a zombie process
- ---> If I clean up the resources myself for Death_reap:release_task ()
- ---> If I am a zombie, I will adopt the INIT process when my parent process exits, and the Init is responsible for cleanup
- --->exit_io_context () cleanup IO context
- --->preempt_disable () to disable preemption
- --->tsk->state = task_dead; Set me up for process death status
- --->kernel/sched.c:schedule () release my PCB, dispatch another new process
- Cleanup Zombie Process: Wait system call waits for child process to end
- --->0x80 interrupt last reached kernel/exit.c:do_wait ()
- --->do_wait_thread ()
- --->wait_consider_task ()
- ---> If the child process is exit_dead, return the 0,wait call back, and the subprocess cleans itself
- ---> If the child process is Exit_zombie:wait_task_zombie ()
- --->xchg () sets the zombie subprocess to Exit_dead
- --->release_task () cleanup Zombie subprocess
Here is a basic diagram of the execution process:
Figure 1 Execution flow of Linux process management
Linux process Management (3): summary