按照ISO C的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用,通常这32个函数被称为终止处理程序,并调用atexit函数来登记这些函数。

  我们通常认为C语言的起始函数是main函数,实质上一个程序的启动函数并不一定是main函数,这个可以采用链接器来设置,但是gcc中默认main就是C语言的入口函数,在main函数启动之前,内核会调用一个特殊的启动例程,这个启动例程从内核中取得命令行参数值和环境变量值,为调用main函数做好准备,因此对应程序而言main函数并不是起始,但是对应C 语言而言,main函数就是入口地址,其他的链接器帮助我们完成,实际上mian函数的执行是使用了exec函数,这是一个函数族,这也是内核执行一个程序的唯一方法,这在进程控制部分将进行分析。

记得在面试题中有一道关于在main函数退出之后,是否还可以执行程序的问题,这时候就要使用到前面提到的atexit函数。

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

  其中,atexit的参数是一个函数地址,当调用此函数时无须传递任何参数,该函数也不能返回值,atexit函数称为终止处理程序注册程序,注册完成以后,当函数终止是exit()函数会主动的调用前面注册的各个函数,但是exit函数调用这些函数的顺序于这些函数登记的顺序是相反的,我认为这实质上是参数压栈造成的,参数由于压栈顺序而先入后出。同时如果一个函数被多次登记,那么该函数也将多次的执行。

  我们知道exit是在main函数调用结束以后调用,因此这些函数的执行肯定在main函数之后,这也是上面面试题的解决方法。即采用atexit函数登记相关的执行函数即可。

  在exit函数的介绍中我们知道,exit()和_exit()以及_Exit()函数的本质区别是是否立即进入内核,_exit()以及_Exit()函数都是在调用后立即进入内核,而不会执行一些清理处理,但是exit()则会执行一些清理处理,这也是为什么会存在atexit()函数的原因,因为exit()函数需要执行清理处理,需要执行一系列的操作,这些终止处理函数实际上就是完成各种所谓的清除操作的实际执行体。atexit函数的定义也给了程序员一种运用exit执行一些清除操作的方法,比如有一些程序需要额外的操作,具体的清除操作可以采用这种方法对特殊操作进行清除等。

 # include <stdio.h>
# include <stdlib.h> void f1(void){
printf("the first exit handier\n");
} void f2(void){
printf("the second exit handier\n");
} int main(void)
{
if( != atexit(f1)){
perror("fail to set exit handier");
exit();
}
if( != atexit(f1)){
perror("fail to set exit handier");
exit();
}
if( != atexit(f2)){
perror("dail to set exit handier");
exit();
}
return ;
}

具体的执行结果如下所示:

the second exit handier
the first exit handier
the first exit handier

  根据exit的执行过此可知,exit首先会调用各个终止处理程序,然后按需多次调用fclose(),关闭所有打开流,也就是说exit函数会执行一个标准I/O库的清理关闭操作:对所有打开的流调用fclose(),这样就会造成所有缓冲的输出数据都被冲洗即写入文件中。

  内核使程序执行的唯一方法是调用一个exec函数,进程自愿终止哦的唯一方法是显式或者隐式调用(通过exit函数)_exit()或者_Exit()函数。因此exit函数中实质是对_exit()或者_Exit()函数的封装。exit会先执行自定义的终止处理函数,然后执行I/O库函数清理函数fclose(),这也是为什么可以在终止处理函数中可以继续运用printf之类函数的原因,因为I/O库函数的流对象还没有被清除,当然可以继续运用。执行完了所有的fclose()以后,可以执行真正意义上的终止函数_exit()或者_Exit()函数。

参考:http://blog.chinaunix.net/uid-20937170-id-3447901.html

atexit函数和exit函数的理解的更多相关文章

  1. Linux C _exit函数与exit函数的联系与区别

    一.联系 1.功能上,_exit和exit函数都是让进程正常退出,即关闭进程所打开的文件描述符,释放已占用内存和其他资源. 二.区别 1._exit函数在头文件unistd.h中声明,而exit在头文 ...

  2. absort函数和exit函数

    1. exit()函数会结束并退出程序. 1. abosrt()函数会触发程序的异常,然后程序后面的语句就不会执行了.用来提示错误.会出现:  

  3. 回收进程用户空间资源 exit()函数 _exit()函数 atexit()函数 on_exit()函数

    摘要:本文主要讲述进程的终止方式,以及怎样使用exit()函数来终止进程.回收进程用户空间资源:分析了exit()函数与_exit()函数,returnkeyword的差异.同一时候具体解读了怎样使用 ...

  4. linux fork函数与vfork函数,exit,_exit区别

    man vfork: NAME vfork - create a child process and block parent SYNOPSIS #include <sys/types.h> ...

  5. 进程控制之exit函数

    进程有下面5种正常终止方式: (1)在main函数内执行return语句.这等效于调用exit. (2)调用exit函数.此函数有ISO C定义,其操作包括调用各终止处理程序(终止处理程序在调用ate ...

  6. C语言中exit函数的使用

      exit() 结束当前进程/当前程序/,在整个程序中,只要调用 exit ,就结束 return() 是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如果不是,那就是退回上一 ...

  7. (转)C语言中Exit函数的使用

    C语言中Exit函数的使用 exit() 结束当前进程/当前程序/,在整个程序中,只要调用 exit ,就结束return() 是当前函数返回,当然如果是在主函数main, 自然也就结束当前进程了,如 ...

  8. 【Linux编程】进程终止和exit函数

    内核要运行一个应用程序,唯一的途径是通过系统调用.exec函数.exec又会调用启动程序,启动程序(一般是汇编语言)以类似以下的方式调用main函数: void exit(main(argc, arg ...

  9. c++ exit() 函数

    函数用法 编辑 函数名: exit() 所在头文件:stdlib.h(如果是”VC6.0“的话头文件为:windows.h) 功 能: 关闭所有文件,终止正在执行的进程. exit(0)表示正常退出, ...

随机推荐

  1. 你应该知道的Linux历史

    说道linux的历史不得不说的就是unix,我们的linux就是类unix系统: 1969年第一台unix系统 贝尔实验室 1970年C语言诞生,对unix内核重新编写 system V(AT& ...

  2. HDU 1541 Stars (线段树)

     Problem Description Astronomers often examine star maps where stars are represented by points on ...

  3. OpenGL ES 3.0之顶点缓冲

    所谓顶点缓冲就是直接将顶点数据存储在gpu的一段缓冲区,不需要从cpu拷贝到gpu.提高了程序的运行效率. 操作步骤 1.创建顶点缓冲对象 GLuint vertexBufferID; 2.分配空间 ...

  4. 解决CentOS下无法发送邮件的问题

    最近有个项目从虚拟主机迁到云主机上,换了个环境,原来用于找回密码的发送邮件功能竟然用不了了!反应极慢,导致tenginx报504网关超时错误. 5.5 or 7.0, sockets 初次百度,看了别 ...

  5. Android 模仿微信启动动画

    本文内容 环境 项目结构 演示微信启动动画 本文演示微信启动动画.请点击此处下载,自行调试. 顺便抱怨一下,实践性(与研究性质的相对)技术博的"七宗罪": 第一宗罪,错字连篇,逻辑 ...

  6. 微服务架构实践 - 你只懂docker与spring boot就够了吗?

    微服务架构实践 - 你只懂docker与spring boot就够了吗? 作者 浮云发发 已关注 2017.02.27 02:50* 字数 2613 阅读 2583评论 6喜欢 35赞赏 2 微服务并 ...

  7. centos下mysql自动备份

    #!/bin/bashdb_user="root"db_passwd="123456"db_name="test_db"#进入备份目录将之前 ...

  8. 牛客网-《剑指offer》-用两个栈实现队列

    题目:http://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6 C++ class Solution { public: vo ...

  9. POSTGRESQL 查看数据库 数据表大小

    1.查看数据库大小: select pg_database_size('log_analysis'); select pg_database_size('log_analysis'); pg_data ...

  10. VB 求余求整

    可以直接用函数来实现: 1.用CInt()函数的范围在-32,768 至 32,767,对于小数部分四舍五入 . 2.用Int()函数和Fix()函数都会删除参数的小数部份而返回剩下的整数, 不同之处 ...