【Linux】atexit 的验证

来源:互联网 发布:迭代器java 线程安全 编辑:程序博客网 时间:2024/06/04 19:54

在我们进行进程终止的分析前,先引入一下关于 main 函数的知识:

当内核使用一个 exec 函数执行 C 程序时,在调用 main 函数之前先调用一个特殊的启动例程,可执行程序将此例程指定为程序的起始地址。启动例程从内核获取命令行参数和

环境变量,然后为调用 main 函数做好准备。

引入 main 函数的知识是因为我们最常接触的就是 main 函数的返回,以 main 函数的返回 return 进行引入更能容易理解进程终止的概念。

接下来我们介绍下进程终止吧。

进程终止的方式有8种:1. 从 main 函数返回;

                                  2. 调用 exit 函数;
                                  3. 调用 _exit 或 _Exit;
                                  4. 最后一个线程从启动例程返回;
                                  5. 最后一个线程调用 pthread_exit;
                                  6. 调用 abort 函数;
        
                          7. 接到一个信号并终止;                         

                                  8. 最后一个线程对取消请求做出响应。

前5种为正常终止,后三种为异常终止。


下面我们重点介绍下 exit 函数和 atexit 函数。

首先我们了解下基本概念:

一个进程可以登记若干(至少32)个函数,这些函数由 exit 自动调用,这些函数被称为终止处理函数,atexit 函数可以登记这些函数。exit 调用终止处理函数的顺序和 atexit 登记的顺序相反造成顺序相反的原因是参数压栈造成的,参数的压栈是先进后出,和函数的栈帧相同)。如果一个函数被多次登记,也会被多次调用。


1)exit 函数


#include <stdlib.h>void exit( int status );void _Exit( int status );#include <unistd.h>void _exit( int status );


这三个函数用于正常终止一个程序,_exit 和 _Exit 立即进入内核,而 exit 则要先做一些清理工作(调用执行各终止处理程序,关闭所有标准 I/O 流),再进入内核。

三个函数所带的整型参数称为终止状态或退出状态,如果(a)调用这些函数不带参数,(b)main 函数中的 return 语句无返回值,(c)main 函数没有声明返回类型为整型,则进程的终止状态是未定义的。

main 函数返回一个整型值与用该值调用 exit 是等价的。


2)atexit 函数


#include <stdlib.h>int atexit( void (*fun)( void ) );


定义:atexit 函数是在正常程序退出时调用的函数,也称为登记函数。

函数名:atexit 

头文件:#include <stdlib.h>

用 法: void atexit(void (*fun)(void));

功 能:注册终止函数(即 main 执行结束后调用的函数)

存在原因:exit 函数需要做清理工作,需要执行一系列操作,这些终止处理函数实际上就是完成各种所谓的清除操作的实际执行体。

注意:exit 调用这些注册函数的顺序与它们登记时候的顺序相反。同一个函数如若登记多次,则也会被调用多次


下面我们演示一下 atexit  函数的程序示例:



\





编译、链接、运行如下:



我们会发现在主函数中,先打印 finish,而后休眠三秒打印出 fun 函数的内容,并且打印顺序是 fun5---fun4---fun3---fun2---fun1,可以轻易地总结出函数的调用顺序规律:exit 调用终止处理函数的顺序和 atexit 登记的顺序相反,并且同一个函数如若登记多次,则也会被调用多次。



以上就是我关于 atexit 函数的理解,希望可以对你理解它有所帮助。




0 0
原创粉丝点击