1. 从main函数开始
在学习C语言的时候,我们知道C程序总是从main函数开始执行的,main函数原型为:
int main(int argc , char *argv[ ]);
当内核执行C程序时,在调用main函数前先调用一个特殊的启动例程,这个启动例程就是可执行程序文件的起始位置,并为main函数执行前配置好运行环境。
2. 进程的终止
进程的终止分为两种:正常终止和异常终止。
正常终止有以下几种情况:
1.从main函数中return
2.调用exit(C标准函数)
3.调用_exit和Exit函数(系统调用)
4.最后一个线程从其启动例程返回
5.最后一个线程调用了pthread_exit
异常终止也有以下几种情况:
1.调用了abort函数
2.接收到一个信号终止
3.最后一个线程对取消请求做出响应
进程运行成功通常返回0,否则返回非0。以上这些进程终止情况了解即可,因为有些进程终止情况在后面还会详细介绍,到时候再回过头来看也不迟。
3. 从main函数来看进程终止
一般来说,main函数在return 0时表示进程状态正常终止,return -1则表示某种失败,当然main函数返回什么值,这个值代表什么错误是可以由程序员自己指定的,并不一定非要返回特定的值。
int main(void)
{
return 0; //进程退出状态为0
//return -1; //-1代表某种失败
}
main(void)
{
return; //进程退出状态为未定义
}
如果main函数不写返回值,在编译时会有警告,因为与main函数的返回值要求不符,该进程的退出状态则是未定义。其实这对程序并没有什么影响,不过是在编译时报警告而已,但是作为一个程序员要有严谨的态度,所以在写程序时,严格按照标准写法。
4. 退出函数
exit和_exit两个函数用于正常终止一个进程,其用法是一样的,参数status是一个传出参数,表示程序的退出状态,status为0表示进程正常终止,不为0则表示进程异常终止。从这两个函数各自所包含的头文件来看,我们可以知道exit是库函数,_exit是系统调用。
#include <stdlib.h>
void exit(int status);
#include <unistd.h>
void _exit(int status);
main函数返回一个整型值与调用exit是等价的,也就是说return (0)等于exit(0)。但是_exit会立即进入内核,而exit会先做一些清理工作再进入内核,由于历史原因,exit函数会在调用_exit之前执行各种动作,例如:
1.调用fclose函数刷新缓冲区,把数据刷到磁盘文件中
2.调用终止函数,例如通过atexit()注册的函数
3.使用由参数status提供的值执行_exit()系统调用
所以程序一般不会直接调用_exit(),更多的是调用库函数exit(),因为_exit函数是一个系统调用,exit函数的底层就是_exit函数实现的。即便是exit函数通常只在各种出错的情况下使用,比如使用open函数打开一个文件失败,这种情况就可以调用exit函数退出。
需要注意的是:如果进程异常退出的话,是不会刷新缓冲区的,因为进程异常退出是不会调用exit函数的。