1. 程式人生 > >ateixt、ptread_exit 、exit和_exit、_Exit引發的思考和總結

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 the buffer?");
 exit(0);
}

輸出結果:

if  i  will  be output ?if  i  will  be in the buffer?

(如圖:為編譯和執行結果)

 
程式二:

#include<unistd.h>
main()
{
 printf(" if  i  will  be output ?");
 printf(" if  i  will  be in the buffer?");
 _exit(0);
}
輸出結果:

(沒有任何輸出)


 對比上面兩個結果,我們可以更好的理解上面提到過的這兩句關鍵的文字
1.exit()函式與_exit()函式最大的區別就在於exit()函式在呼叫exit系統呼叫之前要檢查檔案的開啟情況,把檔案緩衝區中的內容寫回檔案,就是"清理I/O緩衝"。

2.有一些資料,我們認為已經寫入了檔案,實際上因為沒有滿足特定的條件,它們還只是儲存在緩衝區內,這時我們用_exit()函式直接將程序關閉,緩衝區中的資料就會丟失,反之,如果想保證資料的完整性,就一定要使用exit()函式。

附:如果讀者對緩衝機制不太理解可以參見我部落格裡的另一篇博文《UNIX裡關於標準IO的幾種緩衝機制》,它可以幫助你更好的理解本文中關於exit和_exit()的區別。