C++ - C++ signal的使用1. 頭文件 #include <signal.h> 2. 功能 設置某一信號的對應動作 3. 函數(shù)原型 void (*signal(int signum,void(* handler)(int)))(int); 分解來看: typedef void (*sig_t) (int); sig_t signal(int sig, sig_t func); 第一個參數(shù)是目標信號,。func參數(shù)是一個指針,,指向某個處理該信號的函數(shù),。這個處理信號函數(shù)帶有一個int型參數(shù),,并應返回void,。 func參數(shù)也可以設定為下面的一些值: SIG_IGN: 如果func參數(shù)被設置為SIG_IGN,,該信號將被忽略。 SIG_DFL: 如果func參數(shù)被設置為SIG_DFL,,該信號會按照確定行為處理,。 4. sig信號的可能類型 1) #define SIGHUP 1 /* hangup */ SIGHUP是Unix系統(tǒng)管理員很常用的一個信號。許多后臺服務進程在接受到該信號后將會重新讀取它們的配置文件,。然而,,該信號的實際功能是通知進程它的控制終端被斷開。缺省行為是終止進程,。 2) #define SIGINT 2 /* interrupt */ 對于Unix使用者來說,,SIGINT是另外一個常用的信號。許多shell的CTRL-C組合使得這個信號被大家所熟知,。該信號的正式名字是中斷信號,。缺省行為是終止進程。 3) #define SIGQUIT 3 /* quit */ SIGQUIT信號被用于接收shell的CTRL-/組合,。另外,,它還用于告知進程退出。這是一個常用信號,,用來通知應用程序從容的(譯注:即在結束前執(zhí)行一些退出動作)關閉。缺省行為是終止進程,,并且創(chuàng)建一個核心轉儲,。 4) #define SIGILL 4 /* illegal instr. (not reset when caught) */ 如果正在執(zhí)行的進程中包含非法指令,操作系統(tǒng)將向該進程發(fā)送SIGILL信號,。如果你的程序使用了線程,,或者pointe functions,,那么可能的話可以嘗試捕獲該信號來協(xié)助調試。([color=Red]注意:原文這句為:“If your program makes use of use of threads, or pointer functions, try to catch this signal if possible for aid in debugging.”,。中間的兩個use of use of,,不知是原書排版的瑕疵還是我確實沒有明白其意義;另外,,偶經(jīng)常聽說functions pointer,,對于pointer functions,google了一下,,應該是fortran里面的東西,,不管怎樣,還真不知道,,確切含義還請知道的兄弟斧正,。[/color])缺省行為是終止進程,并且創(chuàng)建一個核心轉儲,。 5) #define SIGTRAP 5 /* trace trap (not reset when caught) */ SIGTRAP這個信號是由POSIX標準定義的,,用于調試目的。當被調試進程接收到該信號時,,就意味著它到達了某一個調試斷點,。一旦這個信號被交付,被調試的進程就會停止,,并且它的父進程將接到通知,。缺省行為是終止進程,并且創(chuàng)建一個核心轉儲,。 6) #define SIGABRT 6 /* abort() */ SIGABRT提供了一種在異常終止(abort)一個進程的同時創(chuàng)建一個核心轉儲的方法,。然而如果該信號被捕獲,并且信號處理句柄沒有返回,,那么進程不會終止,。缺省行為是終止進程,并且創(chuàng)建一個核心轉儲,。 7) #define SIGFPE 8 /* floating point exception */ 當進程發(fā)生一個浮點錯誤時,,SIGFPE信號被發(fā)送給該進程。對于那些處理復雜數(shù)學運算的程序,,一般會建議你捕獲該信號,。缺省行為是終止進程,并且創(chuàng)建一個核心轉儲,。 8) #define SIGKILL 9 /* kill (cannot be caught or ignored) */ SIGKILL是這些信號中最難對付的一個,。正如你在它旁邊的注釋中看到的那樣,這個信號不能被捕獲或忽略。一旦該信號被交付給一個進程,,那么這個進程就會終止。然而,,會有一些極少數(shù)情況SIGKILL不會終止進程,。這些罕見的情形在處理一個“非中斷操作”(比如磁盤I/O)的時候發(fā)生。雖然這樣的情形極少發(fā)生,,然而一旦發(fā)生的話,,會造成進程死鎖。唯一結束進程的辦法就只有重新啟動了,。缺省行為是終止進程,。 9) #define SIGBUS 10 /* bus error */ 如同它的名字暗示的那樣,CPU檢測到數(shù)據(jù)總線上的錯誤時將產生SIGBUS信號,。當程序嘗試去訪問一個沒有正確對齊的內存地址時就會產生該信號,。缺省行為是終止進程,并且創(chuàng)建一個核心轉儲,。 10) #define SIGSEGV 11 /* segmentation violation */ SIGSEGV是另一個C/C++程序員很熟悉的信號,。當程序沒有權利訪問一個受保護的內存地址時,或者訪問無效的虛擬內存地址(臟指針,,dirty pointers,,譯注:由于沒有和后備存儲器中內容進行同步而造成。關于野指針,,可以參見http://en./wiki/Wild_pointer 的解釋,。)時,會產生這個信號,。缺省行為是終止進程,,并且創(chuàng)建一個核心轉儲。 11) #define SIGSYS 12 /* non-existent system call invoked */ SIGSYS信號會在進程執(zhí)行一個不存在的系統(tǒng)調用時被交付,。操作系統(tǒng)會交付該信號,,并且進程會被終止。缺省行為是終止進程,,并且創(chuàng)建一個核心轉儲,。 12) #define SIGPIPE 13 /* write on a pipe with no one to read it */ 管道的作用就像電話一樣,允許進程之間的通信,。如果進程嘗試對管道執(zhí)行寫操作,,然而管道的另一邊卻沒有回應者時,操作系統(tǒng)會將SIGPIPE信號交付給這個討厭的進程(這里就是那個打算寫入的進程),。缺省行為是終止進程,。 13) #define SIGALRM 14 /* alarm clock */ 在進程的計時器到期的時候,SIGALRM信號會被交付(delivered)給進程。這些計時器由本章后面將會提及 的setitimer和alarm調用設置,。缺省行為是終止進程,。 14) #define SIGTERM 15 /* software termination signal from kill */ SIGTERM信號被發(fā)送給進程,通知該進程是時候終止了,,并且在終止之前做一些清理活動,。SIGTERM信號是Unix的kill命令發(fā)送的缺省信號,同時也是操作系統(tǒng)關閉時向進程發(fā)送的缺省信號,。缺省行為是終止進程,。 15) #define SIGURG 16 /* urgent condition on IO channel */ 在進程已打開的套接字上發(fā)生某些情況時,SIGURG將被發(fā)送給該進程,。如果進程不捕獲這個信號的話,,那么將被丟棄。缺省行為是丟棄這個信號,。 16) #define SIGSTOP 17 /* sendable stop signal not from tty */ 本信號不能被捕獲或忽略,。一旦進程接收到SIGSTOP信號,它會立即停止(stop),,直到接收到另一個SIGCONT 信號為止,。缺省行為是停止進程,直到接收到一個SIGCONT信號為止,。 17) #define SIGTSTP 18 /* stop signal from tty */ SIGSTP與SIGSTOP類似,,它們的區(qū)別在于SIGSTP信號可以被捕獲或忽略。當shell從鍵盤接收到CTRL-Z的時候就會交付(deliver)這個信號給進程,。缺省行為是停止進程,,直到接收到一個SIGCONT信號為止。 18) #define SIGCONT 19 /* continue a stopped process */ SIGCONT也是一個有意思的信號,。如前所述,,當進程停止的時候,這個信號用來告訴進程恢復運行,。該信號的有趣的地方在于:它不能被忽略或阻塞,,但可以被捕獲。這樣做很有意義:因為進程大概不愿意忽略或阻塞SIGCONT信號,,否則,,如果進程接收到SIGSTOP或SIGSTP的時候該怎么辦?缺省行為是丟棄該信號,。 19) #define SIGCHLD 20 /* to parent on child stop or exit */ SIGCHLD是由Berkeley Unix引入的,,并且比SRV 4 Unix上的實現(xiàn)有更好的接口。(如果信號是一個沒有追溯能力的過程(not a retroactive process),,那么BSD的SIGCHID信號實現(xiàn)會比較好,。在system V Unix的實現(xiàn)中,,如果進程要求捕獲該信號,操作系統(tǒng)會檢查是否存在有任何未完成的子進程(這些子進程是已經(jīng)退出exit)的子進程,,并且在等待調用wait的父進程收集它們的狀態(tài)),。如果子進程退出的時候附帶有一些終止信息(terminating information),那么信號處理句柄就會被調用,。所以,,僅僅要求捕獲這個信號會導致信號處理句柄被調用(譯注:即是上面說的“信號的追溯能力”),而這是卻一種相當混亂的狀況,。)一旦一個進程的子進程狀態(tài)發(fā)生改變,SIGCHLD信號就會被發(fā)送給該進程,。就像我在前面章節(jié)提到的,,父進程雖然可以fork出子進程,但沒有必要等待子進程退出,。一般來說這是不太好的,,因為這樣的話,一旦進程退出就可能會變成一個僵尸進程,??墒侨绻高M程捕獲SIGCHLD信號的話,它就可以使用wait系列調用中的某一個去收集子進程狀態(tài),,或者判斷發(fā)生了什么事情,。當發(fā)送SIGSTOP,SIGSTP或SIGCONF信號給子進程時,SIGCHLD信號也會被發(fā)送給父進程,。缺省行為是丟棄該信號,。 20) #define SIGTTIN 21 /* to readers pgrp upon background tty read */ 當一個后臺進程嘗試進行一個讀操作時,SIGTTIN信號被發(fā)送給該進程,。進程將會阻塞直到接收到SIGCONT信號為止,。缺省行為是停止進程,直到接收到SIGCONT信號,。 21) #define SIGTTOU 22 /* like TTIN if (tp->t_local<OSTOP) */ SIGTTOU信號與SIGTTIN很相似,,不同之處在于SIGTTOU信號是由于后臺進程嘗試對一個設置了TOSTOP屬性的tty執(zhí)行寫操作時才會產生。然而,,如果tty沒有設置這個屬性,,SIGTTOU就不會被發(fā)送。缺省行為是停止進程,,直到接收到SIGCONT信號,。 22) #define SIGIO 23 /* input/output possible signal */ 如果進程在一個文件描述符上有I/O操作的話,SIGIO信號將被發(fā)送給這個進程,。進程可以通過fcntl調用來設置,。缺省行為是丟棄該信號,。 23) #define SIGXCPU 24 /* exceeded CPU time limit */ 如果一旦進程超出了它可以使用的CPU限制(CPU limit),SIGXCPU信號就被發(fā)送給它,。這個限制可以使用隨后討論的setrlimit設置,。缺省行為是終止進程。 24) #define SIGXFSZ 25 /* exceeded file size limit */ 如果一旦進程超出了它可以使用的文件大小限制,,SIGXFSZ信號就被發(fā)送給它,。稍后我們會繼續(xù)討論這個信號。缺省行為是終止進程,。 25) #define SIGVTALRM 26 /* virtual time alarm */ 如果一旦進程超過了它設定的虛擬計時器計數(shù)時,,SIGVTALRM信號就被發(fā)送給它。缺省行為是終止進程,。 26) #define SIGPROF 27 /* profiling time alarm */ 當設置了計時器時,,SIGPROF是另一個將會發(fā)送給進程的信號。缺省行為是終止進程,。 27) #define SIGWINCH 28 /* window size changes */ 當進程調整了終端的行或列時(比如增大你的xterm的尺寸),,SIGWINCH信號被發(fā)送給該進程。缺省行為是丟棄該信號,。 28) #define SIGUSR1 29 /* user defined signal 1 */ 29) #define SIGUSR2 30 /* user defined signal 2 */ SIGUSR1和SIGUSR2這兩個信號被設計為用戶指定,。它們可以被設定來完成你的任何需要。換句話說,,操作系統(tǒng)沒有任何行為與這兩個信號關聯(lián),。缺省行為是終止進程。(譯注:按原文的意思翻譯出來似乎這兩句話有點矛盾,。) 5. 例子 5.1. Linux下的Ctrl+C在Windows下的實現(xiàn)一 Linux下通常的做法: signal(SIGINT, sigfunc); // 設置信號 void sigfunc(int signo) { ... //處理信號相關的操作 } 以下是Linux下的Ctrl+C在Windows下的實現(xiàn) #include <stdio.h> #include <windows.h> static is_loop = 1; // 捕獲控制臺 Ctrl+C 事件的函數(shù) BOOL CtrlHandler( DWORD fdwCtrlType ) { switch (fdwCtrlType) { /* Handle the CTRL-C signal. */ case CTRL_C_EVENT: printf("CTRL_C_EVENT \n"); break; case CTRL_CLOSE_EVENT: printf("CTRL_CLOSE_EVENT \n"); break; case CTRL_BREAK_EVENT: printf("CTRL_BREAK_EVENT \n"); break; case CTRL_LOGOFF_EVENT: printf("CTRL_LOGOFF_EVENT \n"); break; case CTRL_SHUTDOWN_EVENT: printf("CTRL_SHUTDOWN_EVENT \n"); break; default: return FALSE; } is_loop = 0; return (TRUE); } int main(int argc, char *argv[]) { printf("Set Console Ctrl Handler\n"); SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE); while (is_loop); return 0; } 5.2.Linux下的Ctrl+C在Windows下的實現(xiàn)二 #include <stdio.h> #include <windows.h> #define CONTRL_C_HANDLE() signal(3, exit) int main(int argc, char *argv[]) { printf("Set Console Ctrl Handler\n"); CONTRL_C_HANDLE(); while (1); system("PAUSE"); return 0; } |
|
來自: 昵稱14604338 > 《待分類1》