进程终止
进程的退出有三种场景:
- 代码运行完毕,结果正确
- 代码运行完毕,结果不正确
- 代码异常终止
进程退出方法
- 从main返回
- 调用exit函数
- 调用_exit函数
- ctrl + c :x信号终止
其中前三种为正常退出,而第四种是异常退出。在终端可以使用命令 “echo $? ”查看进程退出码
接下来我们来看进程推出的函数有哪些
_exit函数
#include <unistd.h>
void _exit(int status);//status定义了进程的终止状态,父进程通过wait来获取该值
功能: 函数_exit()“立即”终止调用进程。 任何属于该进程打的开文件描述符都将被关闭; 该进程的任何子进程都由进程1,init继承,并且给该进程的父进程发送SIGCHLD信号。
注意的是:虽然status是int,但是只有低8位才被夫进程使用,所以当exit(-1)时,在终端执行$?会发现结果是
255。
exit函数
#include <stdlib.h>
void exit(int value);
exit最后也会调用_exit函数,但在调用_exit函数之前,还做了其他工作:
- 执行用户通过aexit或on_exit定义的清理函数。
- 关闭所有打开的流,所有的缓存数据均被写入。
- 调用_exit函数
我们举个例子:
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("hello");
_exit(0);
}
#include<stdio.h>
//#include<stdlib.h>
int main()
{
printf("hello");
exit(0);
}
对比两个函数,我们可以看出_函数在执行时,什么都没做,就直接退出进程;而exit()函数则是做了一系列的工作之后,才调用_exit函数退出进程。
return 退出
return 的作用只是结束调用 return 的所在函数,只要这个函数不是主函数( main() ),只要主函数没有结束,return 并不能结束进程。
对于在主函数中的(main()),执行return等同于执行exit((n),因为调用main的运行函数时会将main的返回值当作exit的参数。
举个例子:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void func()
{
sleep(3);
printf("hello\n");
return ;
//exit(0);
}
int main()
{
func();
printf("main:hello\n");
while(1);
return 0;
}
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void func()
{
sleep(3);
printf("hello\n");
//return ;
exit(0);
}
int main()
{
func();
printf("main:hello\n");
while(1);
return 0;
}
我们看到结果:func函数调用return之后,进程并不会退出;而调用exit函数之后进程就直接做完该做的工作之后,就直接退出了,后面主函数的语句也不会执行。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
void func()
{
printf("hello\n");
return ;
//exit(0);
}
int main()
{
printf("main:hello\n");
return 0;
func();
}
而在主函数中,执行return,进程就直接退出进程。
总结就是:
return: 只有在main中执行才会退出进程,在main中return跟调用exit效果一样。
exit(): 退出时会逐步释放所有资源。刷新缓冲区,关闭流,关闭文件,做很多操作 在进程的任意位置调用exit都会退出进程。
_exit(): 粗暴的退出进程,什么都不做直释放资源。
退出码:
perror,strerror用于打印退出码