基於命令列程式如何判斷自己被終止

來源:互聯網
上載者:User

基於命令列的程式在當今各個作業系統上都應用得非常廣泛,但是這些程式沒有GUI,所以使用者要終止它們時通常都是按"Ctrl+C"或用系統命令直接結束進程,這樣可能會造成資料丟失或者一些特殊資源沒有釋放,因此須要編寫一段代碼在程式被終止前作一些自己的結束工作。
ANSI C已經提供了一個標準函數signal來捕獲命令列的中斷訊號。
這是該函數在Linux下GCC中的原形:

typedef 
void
 (
*
sighandler_t)(
int
);
sighandler_t signal(
int
 signum, sighandler_t handler);

這是該函數在Microsoft C中的原形:

void
 (__cdecl 
*
signal(
int
 sig, 
void
 (__cdecl 
*
func ) (
int
 [, 
int
 ] ))) (
int
);

以上兩個函式宣告表面上看是乎不同,其實是一樣的。

下面介紹該函數的用法。
第一個參數signum為要捕獲的訊號值,ANSI C定義了以下訊號值。

SIGABRT

程式調用了abort函數

SIGFPE

浮點數錯誤

SIGILL

違例的調用

SIGINT

使用者按了CTRL+C

SIGSEGV

違例的記憶體訪問

SIGTERM

使用者調用了exit函數

第二個參數handler是一個指向捕獲訊號回呼函數的指標,如果產生了signum指定的訊號將執行handler指向的回呼函數。
如果singal函數執行成功則返回一個指向上次指定的訊號捕獲函數的指標,如果執行失敗則返回SIG_ERR。
通常要判斷程式被終止只須要捕獲SIGABRT、SIGINT和SIGTERM這三個訊號就行了。

現在來看一個例子:

#include 
<
stdio.h
>

#include 
<
singal.h
>


int
 end 
=
 
0
;


/**

 * 中斷訊號處理函數。
 
*/


void
 signal_handler( 
int
 sig )
{
    
switch
( sig )
    {
    
case
 SIGINT:
    
case
 SIGABRT:
    
case
 SIGTERM:
        end 
=
 
1

//
 標記為結束


        
break
;
    
default
:
        
//
 其它訊號的處理


        
break
;
    }
}


int
 main( 
int
 argc, 
char
 
*
argv[] )
{
    
if
( signal(SIGINT,signal_handler) 
==
 SIG_ERR ) 
return
 
-
1

//
 設定處理函數失敗


    
    
while

!
end ) 
//
 等待結束


    {
#ifdef WIN32
        _sleep( 
1000
 );
#
else

        sleep( 
1
 );
#endif
        printf( 
"
wait...
"
 );
    }
    
    printf( 
"
end.
"
 );
    
    
return
 
0
;
}

將以上代碼編譯為可執行程式,運行起來然後按Ctrl+C看看有什麼效果吧。

但是要注意的是在Windows下命令列也是一個視窗,如果使用者直接把命令列視窗關閉的話是不會觸發中斷訊號的,所以Windows API提供了一個函數SetConsoleCtrlHandler用來接收Windows控制訊號。
這是該函數的原形:

BOOL WINAPI SetConsoleCtrlHandler( PHANDLER_ROUTINE HandlerRoutine, BOOL Add );

參數HandlerRoutine為接收控制訊號的回呼函數。參數Add決定是添加還是刪除回呼函數,這一點和signal函數是不同的,通過SetConsoleCtrlHandler可以添加多個接收控制訊號的回呼函數。
接收控制訊號的回呼函數原形:

BOOL WINAPI HandlerRoutine( DWORD dwCtrlType );

參數dwCtrlType為控制訊號的類型,是下列值之一。

CTRL_C_EVENT 使用者按了Ctrl+C。
CTRL_BREAK_EVENT 使用者按了CTRL+BREAK。
CTRL_CLOSE_EVENT 控制台視窗被關閉。
CTRL_LOGOFF_EVENT 目前使用者登出。
CTRL_SHUTDOWN_EVENT

系統關閉。

如果回呼函數返回非0值,系統將不再處理這個控制訊號。如果回呼函數返回0,系統就將控制訊號交給下一個回呼函數處理。

SetConsoleCtrlHandler函數和signal的用法大致相同,這裡就不多說了。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.