UNIX再学习 -- 发送信号
生活随笔
收集整理的這篇文章主要介紹了
UNIX再学习 -- 发送信号
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、發送信號的方式
發送信號的方式有幾種:
1、由鍵盤觸發的信號(只能發送一些比較特殊的信號)
SIGINT (2):ctrl+c ?中斷符
SIGQUIT (3):ctrl+\ ?退出符
SIGTSTP (20):ctrl+z ?停止符
2、由錯誤和異常引發的信號
SIGILL (4) ? ?進程試圖執行非法指令
SIGBUS (7) ? ?硬件或對齊錯誤
SIGFPE (8) ? ?算術異常
SIGSEGV (11) ? ?無法內存訪問
SIGPIPE (13) ? ?向無讀取進程的管道寫入
SIGSTKFLT (16) ? ?協處理器棧錯誤
SIGXFSZ (25) ? ?文件資源超限
SIGPWR (30) ? ?斷電
SIGSYS (31) ? ?進程試圖執行無效系統調用
3、用專門的系統命令發送信號
kill [-信號] PIDs 若不指明具體的信號,缺省發送 SIGTERM (15) 信號。 該信號允許用戶優雅地終止進程。進程可以選擇捕獲該信號,并在臨終之前完成必要的清理和善后工作。但如果捕獲了該信號,卻死賴著不走,則有流氓進程之嫌。 若要指明具體信號,可以使用信號編號,也可以使用信號名稱,而且信號名稱中的“SIG”前綴可以省略不寫。例如: kill -9 1234 kill -SIGKILL 1234 kill -KILL 1234 kill -9 -1 (終止所有進程)接收信號的進程可以是一個、多個或所有的(PIDs 取 -1)。拆機用戶可以發送任何進程,而普通用戶只能發送自己的進程。二、發送信號的系統函數
1、函數 kill
#include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); 返回值:成功(至少發出去一個信號)返回 0,失敗返回 -1(1)函數功能
向指定進程或進程組發送信號(2)參數解析
kill 的 pid 參數有以下 4 種不同的情況。 pid > 0 ? ? 將該信號發送給進程 ID 為 pid 的進程 pid == 0 ?將該信號發送給與發送進程屬于同一進程組的所有進程(這些進程的進程組 ID 等于發送進程的進程組 ID),而且發送進程具有權限向這些進程發送信號。這里用的術語“所有進程”不包括實現定義的系統進程集。對于大多數 UNIX 系統,系統進程集包括內核進程和 init (pid 為 1)。 pid < 0 ? ? 將信號發送給其進程組 ID 等于 pid 絕對值,而且發送進程具有權限向其發送信號的所有進程。如前所述,所有進程并不包括系統進程集中的進程。 pid == -1 將該信號發送給發送進程有權限向它們發送信號的所有進程。若茜所述,所有進程不包括系統進程集中的進程。? 參數 sig 為信號編號,取 0 可用于檢查 pid 進程是否存在,如果不存在 kill 函數返回 -1,且 errno 為 ESRCH。(3)示例說明
//示例一 //使用kill函數發送信號 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <sys/types.h>void fa(int signo) {printf("捕獲到了信號%d\n",signo); }int main(void) {//使用fork函數創建子進程pid_t pid = fork();if(-1 == pid){perror("fork"),exit(1);}if(0 == pid) //子進程{printf("pid = %d\n",getpid());//設置對信號50進行自定義處理signal(50,fa);while(1);}sleep(1);//判斷子進程是否存在if(0 == kill(pid,0)){printf("父進程發送信號50\n");kill(pid,50);}return 0; } 輸出結果: pid = 4569 父進程發送信號50 捕獲到了信號50 //示例二 殺死進程 #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include <sys/types.h>int main(void) {pid_t pid;if((pid=fork())<0){perror("fork");}else if(pid==0){printf("這是子進程,pid=%d,",getpid());printf("父進程的pid=%d\n",getppid());printf("按回車鍵,終止父進程\n");getchar();kill(getppid(), SIGTERM);}else{printf("這是父進程,pid=%d\n",getpid());while (1)pause();}return 0; } 輸出結果: 這是父進程,pid=4705 這是子進程,pid=4706,父進程的pid=4705 按回車鍵,終止父進程已終止(4)示例解析
示例一,發送信號 50 給子進程。如果 kill 第二個參數 sig 取 0,可判斷子進程是否存在。 示例二,發送 SIGTERM 給指定父進程。殺死特定進程。2、函數 raise
#include <signal.h> int raise(int sig); 返回值:成功返回 0,失敗返回非 0(1)函數功能
向調用進程自己發送信號(2)參數解析
sig 為信號編號(3)函數解析
raise 函數實際上是給調用進程或者線程發送信號。 對于單線程應用來說,它相當于 kill (getpid (), sig); 對于多線程應用來說,它相當于 pthread_kill (pthread_self (), sig); 若所發信號被捕獲,raise 函數會在信號處理函數返回后返回。(4)示例說明
//示例一 //使用raise函數發送信號 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h>void fa(int signo) {printf("捕獲到了信號%d\n",signo); }int main(void) {//設置信號2進行自定義處理signal(2,fa);int res = sleep(10);if(0 == res){printf("總算美美地睡了個好覺\n");}else{printf("睡眠被打斷,還有%d秒沒有來得及睡\n",res);}//使用raise函數發送信號2raise(2);while(1);return 0; } 輸出結果: 總算美美地睡了個好覺 捕獲到了信號2 //示例二 進程自殺 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h>int main (void) {printf ("按回車鍵,終止進程\n");getchar ();raise (SIGTERM);while (1)pause ();return 0; } 輸出結果: 按回車鍵,終止進程已終止(5)示例解析
示例一,如果不使用 ctrl+c,而是等待 10 秒,raise 函數會發送信號 2。 示例二,raise 發送信號 SIGTERM,終止進程。總結
以上是生活随笔為你收集整理的UNIX再学习 -- 发送信号的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UNIX再学习 -- 可重入函数和 SI
- 下一篇: JMS学习八(ActiveMQ消息持久化