The difference between exit () and _exit () function (in Linux system)

Source: Internet
Author: User
Tags glob signal handler terminates

Note: Exit () is exited, the parameters passed in is the program exit status code, 0 for normal exit, the other means the abnormal exit, generally used-1 or 1, standard C has exit_success and exit_failure two macros, with exit (exit_success) , readability is better. As a system call, _exit and exit are twins, and we can find the answer from the Linux source:

#define __NR__EXIT __nr_exit/* Excerpt from file include/asm-i386/unistd.h line No. 334 */

"__nr_" is the prefix for each system call in the Linux source, note that there are 2 underscores before the first exit, and only 1 underline before the second exit.

At this point, a person who understands C and has a clear mind will say that there is no difference between _exit and exit, but we also want to talk about the difference between the two, which is mainly reflected in their definition of the function library. The prototypes of _exit in the Linux libraries are:

#i nclude void _exit (int status); Compared to exit, the exit () function is defined in Stdlib.h, and _exit () is defined in Unistd.h, and Stdlib.h seems to be a bit more advanced than unistd.h, so what is the difference between them?

The _exit () function is the simplest: it directly stops the process, clears the memory space it uses, and destroys its various data structures in the kernel; the exit () function makes some packaging on these bases and adds a number of operations before the exit is performed, and for this reason, Some people think that exit is not a purely system call.

The most important difference between the exit () function and the _exit () function is that the exit () function checks the opening of the file before calling the exit system, and writes the contents of the file buffer back to the file, which is "cleanup I/O buffering." Exit () before ending the process that called it, take the following steps:

1. Call the function (Exit Function) registered by Atexit () and invoke all functions registered by it in the reverse order of atexit registration, which allows us to specify that we perform our own cleanup actions when the program terminates. For example, save the program state information to a file, unlock the lock on the shared database, and so on.

2.cleanup (); Closes all open streams, which will cause all buffered output to be written, deleting all temporary files created with the Tmpfile function.

3. Finally call the _exit () function to terminate the process. _exit do 3 Things (man):

1,any Open file descriptors belonging to the process is closed

2,any children of the process is inherited by process 1, Init

3,the process's parent is sent a SIGCHLD signal exit after the cleanup is performed, the call to _exit is terminated.

In addition, another explanation: Simply put, the exit function terminates the calling process. Before exiting the program, all files are closed, the buffered output refreshes the definition, and all flushed "exit functions" (defined by atexit) are called.

_exit: This function is defined by POSIX and does not run exit handler and signal handler and does not flush the standard I/O stream in Unix systems. Simply put, _exit terminates the calling process, but does not close the file, does not clear the output cache, and does not call the egress function. Common: Regardless of how the process terminates, the kernel closes all file descriptors opened by the process, releasing the memory! used by the process

A more detailed description:

Calling exit () the exit () function causes normal program termination.

The exit () function performs the following functions:

1. All functions registered by the standard C atexit () function is called in the reverse order of registration. If any of these functions calls exit (), the results is not portable.

2. All open output streams is flushed (data written out) and the streams is closed.

3. All files created by tmpfile () is deleted.

4. The _exit () function is called. Calling _exit () the _exit () function performs operating system-specific program termination functions.

These include:1. All open file descriptors and directory streams is closed.

2. If The parent process is executing a wait () or waitpid (), the parent wakes up and status is made available.

3. If the parent is not executing a wait () or waitpid (), the status was saved for return to the parent on a subsequent wait () or Waitpid ().

4. Children of the terminated process is assigned a new parent process ID. Note:the termination of a parent does not directly terminate its children.

5. If the implementation supports the SIGCHLD signal, a SIGCHLD is sent to the parent.

6. Several Job control signals is sent. Why use the _exit function in a fork sub-process branch without using the Exit function? There are quite a few differences between ' exit ' and ' _exit ' () ' fork ' () ', especially ' vfork ' () ' when it becomes prominent.

The basic difference between ' exit () ' and ' _exit () ' Is that the previous call implements the cleanup work (clean-up) associated with invoking the user state structure (User-mode constructs) in the library, And the user-defined cleaner is called (the custom cleaner is defined by the Atexit function, can be defined multiple times, and executed in reverse order), and the _exit function only enforces kernel cleanup for the process.

In a sub-process branch created by ' fork () ', it is not normal to use ' exit ' () because it causes the buffer of the standard input output (Stdio:standard input outputs) to be emptied two times, and the temporary file is unexpectedly deleted ( Temporary files are created by the Tmpfile function in the system temp directory, and the file name is randomly generated by the system.

In a C + + program, the situation is worse because the static target (objects) destructor (destructors) can be executed incorrectly. (There are also special cases, such as Daemons, whose parent processes need to call ' _exit () ' rather than child processes; The basic rule for most cases is that ' exit () ' is called only once every time it enters the ' main ' function. In the sub-process branch created by ' vfork () ', the use of ' exit ' () will be more dangerous because it will affect the state of the parent process.

#include;

#include int glob = 6;

/* External variable in initialized data */

int main (void) {

int var; /* Automatic variable on the stack */pid_t pid;

var = 88; printf ("Before vfork\n";

/* We don ' t flush stdio */

if (PID = Vfork ()) < 0)

printf ("Vfork error\n";

else if (PID = = 0) {

/* Child */glob++; /*

Modify Parent ' s variables */

var++; Exit (0); /* Child terminates *///Sub-process preferably with _exit (0) more secure.

}/* Parent */

printf ("pid =%d, Glob =%d, var =%d\n", Getpid (), Glob, Var);

Exit (0);

}

Running on a Linux system, the content output of the parent process printf: PID = 29650, Glob = 7, var = 89 child processes are closed by their own, although they share standard input, standard output, standard error, etc. "Open file", when the child process exit, it is only decrements a reference Count, it is not possible to close the parent process, so the parent process still has output.

On other Unix systems, however, the parent process might not have output because the child process called E X i T, and it flushed off all standard I/O streams, including standard output. Although this is performed by a child process, it is in the address space of the parent process, so all the affected standard I/O file objects are in the parent process. When the parent process calls P R i n t f, the standard output is closed, and P R i n t f returns-1.

In the standard library of Linux, there is a set of functions called "Advanced I/O", which are known as printf (), fopen (), Fread (), fwrite (), which are also known as "Buffered I/O (buffered I/Os)", Its characteristics are corresponding to each open file, there is a buffer in memory, each time you read a file, you will read more than a few records, so that the next time you read a file can be read directly from the memory buffer, each time the file is written, it is only written in memory buffer, etc. to meet a certain number of conditions (reached a certain amount, or encounter certain characters, such as line break and file Terminator EOF), and then write the contents of the buffer once to the file, which greatly increases the speed of file read and write, but also for our programming a little bit of trouble. If there is some data that we think has been written to the file, in fact, because it does not meet certain conditions, they are only in the buffer, then we use the _exit () function to close the process directly, the data in the buffer is lost,

Conversely, if you want to ensure the integrity of the data, you must use the exit () function. the function declaration for exit The stdlib.h header file. The _exit function is declared in the unistd.h header file. The following example compares the differences between the two functions. The printf function is the way to use buffered I/O, which automatically reads the record from the buffer when it encounters a "\ n" line break. Examples are compared by using this property.

EXIT.C Source

#include

#include

int main (void)

{

printf ("Using exit...\n");

printf ("The content in buffer");

Exit (0);

}

Output information: Using exit ... The content in buffer

#include

#include

int main (void) {

printf ("Using exit...\n"); If you do not add "\ n" To this information, this message may not be displayed on the terminal. printf ("The content in buffer");

_exit (0);

}

Then output only: Using exit ... Description: After a process has called exit, the process does not immediately disappear completely, leaving behind a data structure called the zombie process (Zombie). Zombie process is a very special process, it has almost given up all the memory space, no executable code, and can not be scheduled, just keep a position in the process list, record the process's exit status and other information for other processes to collect, in addition, the zombie process no longer occupy any memory space.

#include;

int main () {

printf ("%c", ' C ');

_exit (0);

}

The program does not output "C", stating that _exit () does not have IO flush

The difference between exit () and _exit () function (in Linux system)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.