在C语言中,常见的进程退出方式包括使用 exit()
函数和从 main()
函数返回。下面是这两种方式的示例
- 使用
exit()
函数:#include <stdlib.h> int main() { // 程序逻辑... exit(0); // 正常退出进程,参数为退出状态码 }
exit()
函数将进程终止,并返回一个指定的退出状态码给操作系统。通常,非零的退出状态码表示进程异常终止,而0表示进程正常终止。 - 从
main()
函数返回:当main()
函数结束时,进程会自动退出,并将返回值作为退出状态码传递给操作系统。int main() { // 程序逻辑... return 0; // 正常退出进程,返回值为退出状态码 }
当 main()
函数结束时,进程会自动退出,并将返回值作为退出状态码传递给操作系统。
3._exit()
和 _Exit()
_exit()
和 _Exit()
是C语言中用于立即终止进程的函数。它们与 exit()
函数有一些区别:
-
_exit()
函数:- 函数原型:
void _exit(int status)
- 头文件:
<unistd.h>
- 功能:立即终止进程,不执行任何清理操作,包括不刷新缓冲区、不关闭文件描述符等。
- 参数
status
是退出状态码,通常非零值表示进程异常终止。 - 不会调用退出处理程序(
atexit()
注册的函数)。
- 函数原型:
-
_Exit()
函数:- 函数原型:
void _Exit(int status)
- 头文件:
<stdlib.h>
- 功能:立即终止进程,不执行任何清理操作,包括不刷新缓冲区、不关闭文件描述符等。
- 参数
status
是退出状态码,通常非零值表示进程异常终止。 - 不会调用退出处理程序(
atexit()
注册的函数)。
- 函数原型:
这两个函数通常用于在发生严重错误或异常情况下立即退出进程,而不需要执行任何后续的清理工作。与 exit()
不同,它们不会调用已注册的退出处理程序和标准I/O库的清理操作。因此,在使用这两个函数时,需要确保已经处理好可能的资源释放和关闭操作。
我们来举例说明下:exit 与 _exit 和_Exit区别
#include <stdio.h>
#include <stdlib.h>
void cleanup() {
printf("Exit handler called\n");
}
int main() {
atexit(cleanup);
printf("Main function\n");
exit(0);
}
运行结果:
Main function
Exit handler called
在这个例子中,我们在main()
函数中使用atexit()
注册了一个名为cleanup()
的退出处理程序。当调用exit(0)
终止进程时,退出处理程序cleanup()
被调用,并打印出"Exit handler called"。
现在,如果我们将exit(0)
替换为_exit(0)
,例如:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void cleanup() {
printf("Exit handler called\n");
}
int main() {
atexit(cleanup);
printf("Main function\n");
_exit(0);
}
运行结果:
Main function
在这个例子中,当我们使用_exit(0)
立即终止进程时,不会调用已注册的退出处理程序cleanup()
,因此不会打印"Exit handler called"。
再举一个一个例子:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void cleanup() {
printf("Exit handler called in child process\n");
}
int main() {
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(EXIT_FAILURE);
} else if (pid == 0) { // 子进程
atexit(cleanup);
printf("Child process\n");
exit(EXIT_SUCCESS);
} else { // 父进程
wait(NULL); // 父进程等待子进程终止
printf("Parent process\n");
// 注册的退出处理程序不适用于父进程
}
return 0;
}
运行结果:
Child process
Exit handler called in child process
Parent process
在这个例子中,子进程在调用 exit()
之前注册了一个退出处理函数 cleanup()
。当子进程终止时,cleanup()
函数会被调用,并输出 "Exit handler called in child process"。
值得注意的是,父进程不会执行子进程中通过 atexit()
注册的退出处理函数。atexit()
函数在每个进程中都是独立的,子进程的退出处理函数不会传递到父进程。
20230814