c程序启动终止过程及exit(),_exit(),atexit()函数区别
- c语言启动与终止过程
- main()函数不一定是程序的入口,在内核中可以使用链接器设置程序的开始地方。当内核使用一个exec函数执行c程序的时候,在main函数之前要先调用一个特殊的启动例程,可执行程序将此例程指定为程序的起始地址。启动例程从内核获取命令行参数和环境变量,然后为调用main函数做好准备。
2.exit(),_exit(),_Exit()函数的区别
- exit(),_exit(),_Exit()函数的区别是是否立即进入内核。_exit()和_Exit()函数都是在调用后立即进入内核,而不会执行一些清理处理,但是exit()函数会执行一些清理处理,这也是atexit()函数存在的原因,因为exit()函数需要执行一系列的操作,而这些终止处理函数实际上就是完成各种所谓的清除操作的实际执行体。
3.atexit()函数
- atexit()函数是一个特殊的函数,他是在正常程序退出时调用的函数,称之为登记函数(函数原型:int atexit()void (*)(void)))
- 一个进程可以登记32个函数,这些函数由exit自动调用,这些函数称为终止处理函数,atexit()函数可以登记这些函数。exit()调用终止处理函数的顺序和atexit登记的顺序相反(参数压栈造成的,参数的压栈是先进后出),如果一个函数被多次登记,也会被多次调用。
- atexit()函数的调用顺序和退出顺序
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 void func1() 5 { 6 printf("The process is done...\n"); 7 } 8 void func2() 9 { 10 printf("Clean up the processing\n"); 11 } 12 void func3() 13 { 14 printf("Exit sucessful..\n"); 15 } 16 int main() 17 { 18 atexit(func1); 19 atexit(func2); 20 atexit(func3); 21 exit(0); 22 23 }
- 输出结果是atexit()函数的调用顺序与登记顺序相反
4.atexit()函数的用途
- atexit()函数可以按照你给予的顺序摧毁全局变量,比如有个log类,在其他的全局类中也有可能调用到log类写日志。所以log类最后被析构。假定没有定义析构顺序,那么程序在退出前有可能首先析构log类,那么其他的全局变量在此时将无法正确写日志。
- 将数据写回文件,删除临时文件等
- 即注册程序正常终止时要被调用的函数,并且函数的调用顺序与注册顺序相反。