`
java-mans
  • 浏览: 11439768 次
文章分类
社区版块
存档分类
最新评论

ateixt、ptread_exit 、exit和_exit、_Exit引发的思考和总结

 
阅读更多

编写背后:视频采集应用程序的main函数中atexit(&free_dev)的调用

基础理解:

函数名: atexit

  头文件:#include<stdlib.h>

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

  用 法: int atexit(void (*func)(void));

  注意:按照ISO C的规定,一个进程可以登记多达32个函数,这些函数将由exit自动调用。atexit()注册的函数类型应为不接受任何参数的void函数,exit调用这些注册函数的顺序与它们登记时候的顺序相反。同一个函数如若登记多次,则也会被调用多次。

  程序例:

   #include <stdio.h> 
  #include <stdlib.h> 

  void exit_fn1(void) 

  { 

  printf("Exit function #1 called\n"); 

  } 

  void exit_fn2(void) 

  { 

  printf("Exit function #2 called\n"); 

  } 

  int main(void) 

  { 

  /* post exit function #1 */ 

  atexit(exit_fn1); 

  /* post exit function #2 */ 

  atexit(exit_fn2); 

  return 0; 

  } 

 输出:

  Exit function #2 called

  Exit function #1 called

  进程的终止方式:

  有8种方式使进程终止,其中前5种为正常终止,它们是

  1:从 main 返回

  2:调用 exit

  3:调用 _exit 或 _Exit

  4:最后一个线程从其启动例程返回

  5:最后一个线程调用 pthread_exit

  异常终止有3种,它们是

  6:调用 abort

  7:接到一个信号并终止

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

  #include <stdlib.h?

  void exit (int status);

  void _Exit (int status);

  #include <unistd.h>

  void _exit (status);

  其中调用 _exit,_Exit 都不会调用终止程序

  异常终止也不会。

对比+例程---加深理解

对比atexit 、 exit、 _exit、 ptread_exit

关于atexit()函数:

main 函数执行完后,如果需要再执行一段代码的话可以调用atexit()注册一个函数:例如:

#include<stdio.h>
#include<stdlib.h>
  
  void fumc1()
  {printf("next\n");}


   void fumc2()
   {printf("executed");}
  

   void fumc3()
   {printf("is");}
 

   void fumc4()
   {printf("this");}
 
 void main()
 {
     char str[]="0123456789";
     atexit(fumc1);
     atexit(fumc2);
     atexit(fumc3);
     atexit(fumc4);
     printf("%d\n",sizeof(str));

      printf("main execued to the end. \n");
   }


执行结果:
main execued to the end.
11
thisisexecutednext


本来到该结束程序printf("main execued to the end. \n");
但是还打印thisisexecutednext
说明:mian程序结束后,还运行atexit函数

关于exit、 _exit、 ptread_exit的区分:

(1)终止”进程” 调用:exit和_exit

注意:如果进程中任何一个线程中调用exit或_exit,那么整个进程都会终止。(会导致线程退出)

(2)终止“线程”调用:ptread_exit

而“线程”的正常退出方式3种:

A线程从启动例程中返回(return())

B线程可以被另一个进程终止

C线程自己调用pthread_exit函数

关于exit、 _exit 的区分

_exit()函数:的作用最为简单:直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;

exit() 函数:则在这些基础上作了一些包装,在执行退出之前加了若干道工序,也是因为这个原因,有些人认为exit已经不能算是纯粹的系统调用。

exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是"清理I/O缓冲"。

在Linux的标准函数库中,有一套称作"高级I/O"的函数,我们熟知的printf()、fopen()、fread()、fwrite()都在此 列,它们也被称作"缓冲I/O(buffered I/O)",其特征是对应每一个打开的文件,在内存中都有一片缓冲区,每次读文件时,会多读出若干条记录,这样下次读文件时就可以直接从内存的缓冲区中读取,每次写文件的时候,也仅仅是写入内存中的缓冲区,等满足了一定的条件达到一定数量,或遇到特定字符,如换行符和文件结束符EOF),再将缓冲区中的 内容一次性写入文件,这样就大大增加了文件读写的速度,但也为我们编程带来了一点点麻烦。如果有一些数据,我们认为已经写入了文件,实际上因为没有满足特定的条件,它们还只是保存在缓冲区内,这时我们用_exit()函数直接将进程关闭,缓冲区中的数据就会丢失,反之,如果想保证数据的完整性,就一定要使用exit()函数。

下面我们来看两小段程序并对比起输出结果:

程序一:

#i nclude<stdlib.h>
main()
{
printf("if i will be output ?");
printf(" if i will be in thebuffer?");
exit(0);
}

输出结果:

if i will be output ?if i will be in thebuffer?

(如图:为编译和执行结果)


程序二:

#include<unistd.h>
main()
{
printf("if i will be output ?");
printf(" if i will be in thebuffer?");
_exit(0);
}
输出结果:

(没有任何输出)


对比上面两个结果,我们可以更好的理解上面提到过的这两句关键的文字
1.exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是"清理I/O缓冲"。

2.有一些数据,我们认为已经写入了文件,实际上因为没有满足特定的条件,它们还只是保存在缓冲区内,这时我们用_exit()函数直接将进程关闭,缓冲区中的数据就会丢失,反之,如果想保证数据的完整性,就一定要使用exit()函数。

附:如果读者对缓冲机制不太理解可以参见我博客里的另一篇博文《UNIX里关于标准IO的几种缓冲机制》,它可以帮助你更好的理解本文中关于exit和_exit()的区别。



分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics