成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

如何在Linux下捕捉信號

系統 Linux 系統運維
捕捉信號是指如果信號的處理動作是用戶自定義函數,在信號遞達時就調用這個自定義函數。進程收到一個信號后不會被立即處理,而是在恰當時機進行處理!即內核態返回用戶態之前 !但是由于信號處理函數的代碼在用戶空間,所以這增加了內核處理信號捕捉的復雜度。

信號由三種處理方式:

  1. 忽略
  2. 執行該信號的默認處理動作
  3. 捕捉信號

如果信號的處理動作是用戶自定義函數,在信號遞達時就調用這個自定義函數,這稱為捕捉信號。

進程收到一個信號后不會被立即處理,而是在恰當時機進行處理!即內核態返回用戶態之前 !

但是由于信號處理函數的代碼在用戶空間,所以這增加了內核處理信號捕捉的復雜度。

內核實現信號捕捉的步驟:

  1. 用戶為某信號注冊一個信號處理函數sighandler。
  2. 當前正在執行主程序,這時候因為中斷、異常或系統調用進入內核態。
  3. 在處理完異常要返回用戶態的主程序之前,檢查到有信號未處理,并發現該信號需要按照用戶自定義的函數來處理。
  4. 內核決定返回用戶態執行sighandler函數,而不是恢復main函數的上下文繼續執行!(sighandler和main函數使用的是不同的堆棧空間,它們之間不存在調用和被調用的關系,是兩個獨立的控制流程)
  5. sighandler函數返回后,執行特殊的系統調用sigreturn從用戶態回到內核態
  6. 檢查是否還有其它信號需要遞達,如果沒有 則返回用戶態并恢復主程序的上下文信息繼續執行。

signal

給某一個進程的某一個信號(標號為signum)注冊一個相應的處理函數,即對該信號的默認處理動作進行修改,修改為handler函數指向的方式;

  1. #include <signal.h> 
  2. typedef void (*sighandler_t)(int); 
  3. sighandler_t signal(int signum, sighandler_t handler);<br>//即:<br>void (*signal(int, void(*)(int)))(int); 

signal函數接受兩個參數:一個整型的信號編號,以及一個指向用戶定義的信號處理函數的指針。

此外,signal函數的返回值是一個指向調用用戶定義信號處理函數的指針。

sigaction

sigaction函數可以讀取和修改與指定信號相關聯的處理動作。

  1. #include <signal.h> 
  2. int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); 
  3. struct sigaction 
  4.                void     (*sa_handler)(int);          //信號處理方式 
  5.                void     (*sa_sigaction)(int, siginfo_t *, void *);  //實時信號的處理方式  暫不討論 
  6.                sigset_t   sa_mask;   //額外屏蔽的信號 
  7.                int        sa_flags; 
  8.                void     (*sa_restorer)(void);     
  9. }; 

signum是指定信號的編號。

處理方式:

若act指針非空,則根據act結構體中的信號處理函數來修改該信號的處理動作。

若oact指針非 空,則通過oact傳出該信號原來的處理動作。

現將原來的處理動作備份到oact里,然后根據act修改該信號的處理動作。

(注:后兩個參數都是輸入輸出型參數!)

將sa_handler三種可選方式:

  1. 賦值為常數SIG_IGN傳給sigaction表示忽略信號;
  2. 賦值為常數SIG_DFL表示執行系統默認動作;
  3. 賦值為一個函數指針表示用自定義函數捕捉信號,或者說向內核注冊一個信號處理函 數,該函數返回值為void,可以帶一個int參數,通過參數可以得知當前信號的編號,這樣就可以用同一個函數處理多種信號。

(注:這是一個回調函數,不是被main函數調用,而是被系統所調用)

當某個信號的處理函數被調用時,內核自動將當前信號加入進程的信號屏蔽字,當信號處理函數返回時自動恢復原來的信號屏蔽字,這樣就保證了在處理某個信號時,如果這種信號再次產生,那么 它會被阻塞到當前處理結束為止。

pause

pause函數使調用進程掛起直到有信號遞達!

  1. #include <unistd.h> 
  2. int pause(void); 

處理方式:

如果信號的處理動作是終止進程,則進程終止,pause函數沒有機會返回;

如果信號的處理動作是忽略,則進程繼續處于掛起狀態,pause不返回;

如果信號的處理動作是捕捉,則調用了信號處理函數之后pause返回-1,errno設置為EINTR。

所以pause只有出錯的返回值(類似exec函數家族)。錯誤碼EINTR表示“被信號中斷”。

舉個栗子

  1. 定義一個鬧鐘,約定times秒后,內核向該進程發送一個SIGALRM信號;
  2. 調用pause函數將進程掛起,內核切換到別的進程運行;
  3. times秒后,內核向該進程發送SIGALRM信號,發現其處理動作是一個自定義函數,于是切回用戶態執行該自定義處理函數;
  4. 進入sig_alrm函數時SIGALRM信號被自動屏蔽,從sig_alrm函數返回時SIGALRM信號自動解除屏蔽。然后自動執行特殊的系統調用sigreturn再次進入內核,之后再返回用戶態繼續執行進程的主控制流程(main函數調用的mytest函數)。
  5. pause函數返回-1,然后調用alarm(0)取消鬧鐘,調用sigaction恢復SIGALRM信號以前的處理 動作。
  1. /************************************************************************* 
  2.  > File Name: Pause.c 
  3.  > Author:Lynn-Zhang 
  4.  > Mail: iynu17@yeah.net 
  5.  > Created Time: Sun 14 Aug 2016 12:27:03 PM CST 
  6.  ************************************************************************/ 
  7.   
  8. #include<stdio.h> 
  9. #include<signal.h> 
  10. #include<unistd.h> 
  11. void sig_alarm(int signum) 
  12.     printf("I am a custom handler!\n"); 
  13. void mysleep(unsigned int times) 
  14.     //注冊兩個信號處理動作 
  15.     struct sigaction new,old; 
  16.     new.sa_handler=sig_alarm; //信號處理函數 
  17.     sigemptyset(&new.sa_mask);//不屏蔽任何信號屏蔽字 
  18.     new.sa_flags=0; 
  19.       
  20.     //對SIGALRM 信號的默認處理動作修改為自定義處理動作 
  21.     sigaction(SIGALRM,&new,&old); 
  22.     alarm(times); 
  23.     pause(); //掛起等待 
  24.     alarm(1); 
  25.     sleep(2); 
  26.     alarm(0); //取消鬧鐘 
  27.     //恢復SIGALRM 信號到默認處理動作 
  28.     sigaction(SIGALRM,&old,NULL); 
  29.     alarm(1); 
  30.     sleep(2); 
  31. int main() 
  32.     while(1) 
  33.     { 
  34.         mysleep(2); 
  35.         printf("many seconds passed\n"); 
  36.         printf("###################\n"); 
  37.     } 
  38.     return 0; 

定義一個鬧鐘并掛起等待,收到信號后執行自定義處理動作,在沒有恢復默認處理動作前,收到SIGALRM信號都會按照其自定義處理函數來處理。恢復自定義處理動作之后收到SIGALRM信號則執行其默認處理動作即終止進程!

責任編輯:武曉燕 來源: 博客園
相關推薦

2020-10-18 07:13:44

Linux系統編程信號捕捉

2009-02-18 17:31:48

2014-12-23 09:37:09

Linuxrsync

2017-01-05 12:21:00

LinuxPyCharm安裝

2011-03-09 15:54:34

LAMP

2018-02-01 04:52:08

信號布線高速信號

2014-05-30 10:50:51

iOS捕捉簽名

2023-02-27 17:36:33

LinuxSIGINT信號

2019-02-28 09:13:21

Linux用法交互模式

2019-03-28 08:00:00

Linux磁盤IO監控存儲設備

2015-11-24 13:27:35

Linuxcool-retro-復古終端

2023-09-24 19:29:44

LinuxWebP圖像

2017-05-08 18:10:54

2017-08-07 16:41:39

LinuxOpenCV

2014-03-20 10:31:02

Linuxbin

2010-08-25 13:46:28

入侵檢測IDS

2009-02-16 20:16:52

Linux網卡硬件查看

2022-03-09 14:43:38

LinuxDLNA

2009-07-17 14:26:40

在Linux下配置Jy

2010-01-26 11:06:50

C++開發
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 一级片子| 国产高清视频 | 欧美aaa一级片 | 国内精品一区二区 | 国产精品自拍av | 91n成人 | 草比av| 日韩成人在线一区 | 日韩精品1区2区3区 成人黄页在线观看 | 国产伦精品 | 欧美精品在欧美一区二区 | 国产精品免费一区二区三区四区 | 久久成人午夜 | 日韩久久精品 | 国产欧美精品 | 一区二区三区观看视频 | 久久91| 日韩在线精品 | 国产乱码精品一区二区三区忘忧草 | 亚洲一区二区不卡在线观看 | 国产一区二区三区在线 | 天天摸天天干 | 精品一区二区三区四区视频 | 亚洲精品日本 | 黄网免费看 | 中文字幕亚洲欧美 | 精品精品 | 欧美精品一区免费 | 日韩日韩日韩日韩日韩日韩日韩 | 欧美日韩电影免费观看 | 孕妇一级毛片 | 亚洲国产欧美国产综合一区 | 亚洲精品视频观看 | 精品一区二区三区91 | 欧美啪啪 | 亚洲日本一区二区 | 黄在线免费观看 | 天天天天天操 | 99精品欧美一区二区三区综合在线 | 91免费看片 | 亚洲黄色一级毛片 |