自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

如何在Linux下捕捉信號(hào)

系統(tǒng) Linux 系統(tǒng)運(yùn)維
捕捉信號(hào)是指如果信號(hào)的處理動(dòng)作是用戶自定義函數(shù),在信號(hào)遞達(dá)時(shí)就調(diào)用這個(gè)自定義函數(shù)。進(jìn)程收到一個(gè)信號(hào)后不會(huì)被立即處理,而是在恰當(dāng)時(shí)機(jī)進(jìn)行處理!即內(nèi)核態(tài)返回用戶態(tài)之前 !但是由于信號(hào)處理函數(shù)的代碼在用戶空間,所以這增加了內(nèi)核處理信號(hào)捕捉的復(fù)雜度。

信號(hào)由三種處理方式:

  1. 忽略
  2. 執(zhí)行該信號(hào)的默認(rèn)處理動(dòng)作
  3. 捕捉信號(hào)

如果信號(hào)的處理動(dòng)作是用戶自定義函數(shù),在信號(hào)遞達(dá)時(shí)就調(diào)用這個(gè)自定義函數(shù),這稱為捕捉信號(hào)。

進(jìn)程收到一個(gè)信號(hào)后不會(huì)被立即處理,而是在恰當(dāng)時(shí)機(jī)進(jìn)行處理!即內(nèi)核態(tài)返回用戶態(tài)之前 !

但是由于信號(hào)處理函數(shù)的代碼在用戶空間,所以這增加了內(nèi)核處理信號(hào)捕捉的復(fù)雜度。

內(nèi)核實(shí)現(xiàn)信號(hào)捕捉的步驟:

  1. 用戶為某信號(hào)注冊(cè)一個(gè)信號(hào)處理函數(shù)sighandler。
  2. 當(dāng)前正在執(zhí)行主程序,這時(shí)候因?yàn)橹袛?、異常或系統(tǒng)調(diào)用進(jìn)入內(nèi)核態(tài)。
  3. 在處理完異常要返回用戶態(tài)的主程序之前,檢查到有信號(hào)未處理,并發(fā)現(xiàn)該信號(hào)需要按照用戶自定義的函數(shù)來處理。
  4. 內(nèi)核決定返回用戶態(tài)執(zhí)行sighandler函數(shù),而不是恢復(fù)main函數(shù)的上下文繼續(xù)執(zhí)行!(sighandler和main函數(shù)使用的是不同的堆棧空間,它們之間不存在調(diào)用和被調(diào)用的關(guān)系,是兩個(gè)獨(dú)立的控制流程)
  5. sighandler函數(shù)返回后,執(zhí)行特殊的系統(tǒng)調(diào)用sigreturn從用戶態(tài)回到內(nèi)核態(tài)
  6. 檢查是否還有其它信號(hào)需要遞達(dá),如果沒有 則返回用戶態(tài)并恢復(fù)主程序的上下文信息繼續(xù)執(zhí)行。

signal

給某一個(gè)進(jìn)程的某一個(gè)信號(hào)(標(biāo)號(hào)為signum)注冊(cè)一個(gè)相應(yīng)的處理函數(shù),即對(duì)該信號(hào)的默認(rèn)處理動(dòng)作進(jìn)行修改,修改為handler函數(shù)指向的方式;

  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函數(shù)接受兩個(gè)參數(shù):一個(gè)整型的信號(hào)編號(hào),以及一個(gè)指向用戶定義的信號(hào)處理函數(shù)的指針。

此外,signal函數(shù)的返回值是一個(gè)指向調(diào)用用戶定義信號(hào)處理函數(shù)的指針。

sigaction

sigaction函數(shù)可以讀取和修改與指定信號(hào)相關(guān)聯(lián)的處理動(dòng)作。

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

signum是指定信號(hào)的編號(hào)。

處理方式:

若act指針非空,則根據(jù)act結(jié)構(gòu)體中的信號(hào)處理函數(shù)來修改該信號(hào)的處理動(dòng)作。

若oact指針非 空,則通過oact傳出該信號(hào)原來的處理動(dòng)作。

現(xiàn)將原來的處理動(dòng)作備份到oact里,然后根據(jù)act修改該信號(hào)的處理動(dòng)作。

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

將sa_handler三種可選方式:

  1. 賦值為常數(shù)SIG_IGN傳給sigaction表示忽略信號(hào);
  2. 賦值為常數(shù)SIG_DFL表示執(zhí)行系統(tǒng)默認(rèn)動(dòng)作;
  3. 賦值為一個(gè)函數(shù)指針表示用自定義函數(shù)捕捉信號(hào),或者說向內(nèi)核注冊(cè)一個(gè)信號(hào)處理函 數(shù),該函數(shù)返回值為void,可以帶一個(gè)int參數(shù),通過參數(shù)可以得知當(dāng)前信號(hào)的編號(hào),這樣就可以用同一個(gè)函數(shù)處理多種信號(hào)。

(注:這是一個(gè)回調(diào)函數(shù),不是被main函數(shù)調(diào)用,而是被系統(tǒng)所調(diào)用)

當(dāng)某個(gè)信號(hào)的處理函數(shù)被調(diào)用時(shí),內(nèi)核自動(dòng)將當(dāng)前信號(hào)加入進(jìn)程的信號(hào)屏蔽字,當(dāng)信號(hào)處理函數(shù)返回時(shí)自動(dòng)恢復(fù)原來的信號(hào)屏蔽字,這樣就保證了在處理某個(gè)信號(hào)時(shí),如果這種信號(hào)再次產(chǎn)生,那么 它會(huì)被阻塞到當(dāng)前處理結(jié)束為止。

pause

pause函數(shù)使調(diào)用進(jìn)程掛起直到有信號(hào)遞達(dá)!

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

處理方式:

如果信號(hào)的處理動(dòng)作是終止進(jìn)程,則進(jìn)程終止,pause函數(shù)沒有機(jī)會(huì)返回;

如果信號(hào)的處理動(dòng)作是忽略,則進(jìn)程繼續(xù)處于掛起狀態(tài),pause不返回;

如果信號(hào)的處理動(dòng)作是捕捉,則調(diào)用了信號(hào)處理函數(shù)之后pause返回-1,errno設(shè)置為EINTR。

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

舉個(gè)栗子

  1. 定義一個(gè)鬧鐘,約定times秒后,內(nèi)核向該進(jìn)程發(fā)送一個(gè)SIGALRM信號(hào);
  2. 調(diào)用pause函數(shù)將進(jìn)程掛起,內(nèi)核切換到別的進(jìn)程運(yùn)行;
  3. times秒后,內(nèi)核向該進(jìn)程發(fā)送SIGALRM信號(hào),發(fā)現(xiàn)其處理動(dòng)作是一個(gè)自定義函數(shù),于是切回用戶態(tài)執(zhí)行該自定義處理函數(shù);
  4. 進(jìn)入sig_alrm函數(shù)時(shí)SIGALRM信號(hào)被自動(dòng)屏蔽,從sig_alrm函數(shù)返回時(shí)SIGALRM信號(hào)自動(dòng)解除屏蔽。然后自動(dòng)執(zhí)行特殊的系統(tǒng)調(diào)用sigreturn再次進(jìn)入內(nèi)核,之后再返回用戶態(tài)繼續(xù)執(zhí)行進(jìn)程的主控制流程(main函數(shù)調(diào)用的mytest函數(shù))。
  5. pause函數(shù)返回-1,然后調(diào)用alarm(0)取消鬧鐘,調(diào)用sigaction恢復(fù)SIGALRM信號(hào)以前的處理 動(dòng)作。
  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.     //注冊(cè)兩個(gè)信號(hào)處理動(dòng)作 
  15.     struct sigaction new,old; 
  16.     new.sa_handler=sig_alarm; //信號(hào)處理函數(shù) 
  17.     sigemptyset(&new.sa_mask);//不屏蔽任何信號(hào)屏蔽字 
  18.     new.sa_flags=0; 
  19.       
  20.     //對(duì)SIGALRM 信號(hào)的默認(rèn)處理動(dòng)作修改為自定義處理動(dòng)作 
  21.     sigaction(SIGALRM,&new,&old); 
  22.     alarm(times); 
  23.     pause(); //掛起等待 
  24.     alarm(1); 
  25.     sleep(2); 
  26.     alarm(0); //取消鬧鐘 
  27.     //恢復(fù)SIGALRM 信號(hào)到默認(rèn)處理動(dòng)作 
  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; 

定義一個(gè)鬧鐘并掛起等待,收到信號(hào)后執(zhí)行自定義處理動(dòng)作,在沒有恢復(fù)默認(rèn)處理動(dòng)作前,收到SIGALRM信號(hào)都會(huì)按照其自定義處理函數(shù)來處理?;謴?fù)自定義處理動(dòng)作之后收到SIGALRM信號(hào)則執(zhí)行其默認(rèn)處理動(dòng)作即終止進(jìn)程!

責(zé)任編輯:武曉燕 來源: 博客園
相關(guān)推薦

2020-10-18 07:13:44

Linux系統(tǒng)編程信號(hào)捕捉

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

2023-09-24 19:29:44

LinuxWebP圖像

2015-11-24 13:27:35

Linuxcool-retro-復(fù)古終端

2019-02-28 09:13:21

Linux用法交互模式

2019-03-28 08:00:00

Linux磁盤IO監(jiān)控存儲(chǔ)設(shè)備

2018-02-01 04:52:08

信號(hào)布線高速信號(hào)

2014-05-30 10:50:51

iOS捕捉簽名

2023-02-27 17:36:33

LinuxSIGINT信號(hào)

2017-08-07 16:41:39

LinuxOpenCV

2017-05-08 18:10:54

2014-03-20 10:31:02

Linuxbin

2010-08-25 13:46:28

入侵檢測(cè)IDS

2009-02-16 20:16:52

Linux網(wǎng)卡硬件查看

2022-03-09 14:43:38

LinuxDLNA

2009-07-17 14:26:40

在Linux下配置Jy

2009-02-16 19:47:03

LinuxBIOS備份
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)