日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

信号的基本概念

發布時間:2025/6/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 信号的基本概念 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.信號

? ?信號主要用來通知進程發生了異步事件,而不會給進程傳遞任何數據。信號總共有62個,前32個被稱為普通信號,34-64被稱為實時信號。通常只關心普通信號。

2.信號的產生

? 1> 鍵盤

? ? ? ?通過組合鍵發送一個信號,一定是給前臺進程的。例如ctrl+c

? 2>用系統函數發送信號

? ? ? 可以給指定進程發送信號,例如kill命令用kill()函數實現,abort函數是當前進程接收到信號而異常終止。raise自己給自己發送信號。

? 3>由軟件條件產生

? ? alarm(時間數),當alarm完成后直接終止進程。

3.信號的處理

? ?1>忽略

? ?2>執行信號默認處理方式

? ?3>自定義方式:捕捉信號

? ? ?使用sighandler_t signal(int signum, sighandler_t handler);

? ? ?注:第一個參數是哪個信號,第二個參數是捕捉信號的函數名

4.阻塞信號

? ?1>實際執行信號處理動作稱為信號遞達。

? ?2>信號從產生到遞達之間的狀態稱為信號未決。

?進程可以選擇阻塞某個信號,被阻塞的信號產生時將保持在未決狀態,直到進程解除對此信號的阻塞,才執行遞達的動作。(忽略與阻塞不同,忽略是在信號遞達之后)

信號不是立即處理的,是在一個合適的點上處理的。除了9號信號。

信號在內核中表示示意圖:

一個信號沒有pending,可以被block。block與pending沒有關系。

信號代碼舉例:

??1?#include<stdio.h>2?#include<signal.h>3?void?show(sigset_t*?sig_pending)//展示未決的信號4?{5???int?i=1;6???for(i=1;i<32;++i)7???{8?????if(sigismember(sig_pending,i))9?????{10???????????printf("1");11?????}12?13????else14???{15?????????printf("0");16????}17?18?19????}20?printf("\n");21?}22?23?void?handler(int?sig)//捕捉遞達的信號24?{25???printf("I??see?you!?%d\n",sig);26?27?28??}29?30?int?main()31?{32??????sigset_t?sig_mask;33??????sigset_t?sig_old;34??????sigset_t?sig_pending;35??????sigemptyset(&sig_mask);36??????sigemptyset(&sig_old);37??????sigemptyset(&sig_pending);38??????sigaddset(&sig_mask,SIGINT);//將2號信號放入信號集中阻塞39??????sigprocmask(SIG_SETMASK,&sig_mask,&sig_old);40??????int?count=10;41?????signal(SIGINT,handler);42??????while(1)43??????{44?????????sigpending(&sig_pending);//獲取當前進程信號集,與pending有關45?????????show(&sig_pending);46?????????sleep(1);47????????if(count<0)48?????????{49???????????sigprocmask(SIG_SETMASK,&sig_old,NULL);//恢復2號信號50?????????}51?????????count--;52??????}53????return?0;54?}

用戶模式與內核模式切換關于信號

5.捕捉信號

? 1>sigaction

#include <signal.h>

int sigaction(int signo, const struct sigaction *act, struct

sigaction *oact);

sigaction函數可以讀取和修改與指定信號相關聯的處理動作。調用成功則返回0,出錯則

返回- 1。signo是指定信號的編號。若act指針非空,則根據act修改該信號的處理動作。

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

構體

.

??1?#include<stdio.h>2?#include<signal.h>3?#include<string.h>4?void?handler(int?sig)5?{6???printf("I?am?that?signal...%d\n",sig);7?}?8?int?main()9?{10????struct?sigaction?old;11????struct?sigaction?act;12????act.sa_handler=handler;//自定義處理信號動作13????act.sa_flags=0;14????sigemptyset(&act.sa_mask);15????memset(&old,'\0',sizeof(old));16????sigaction(SIGINT,&act,&old);對2號信號設置17?????while(1)18?????{19??????printf("I?am?waiting??a?signal....\n");20??????sleep(2);21??????}22??????return?0;23?}

?2>pause

int pause(void);

pause函數使調用進程掛起直到有信號遞達。如果信號的處理動作是終止進程,則進程終

止,pause函數沒有機會返回;如果信號的處理動作是忽略,則進程繼續處于掛起狀態,pause

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

EINTR, 所以pause只有出錯的返回值(想想以前還學過什么函數只有出錯返回值?)。錯誤碼

EINTR表 示“被信號中斷”。

下面我們用alarm和pause實現sleep(3)函數,稱為mysleep。

? 1 #include<stdio.h>

? 2 #include<signal.h>

? 3 #include<string.h>

? 4 void handler(int sig)

? 5 {

? 6 //donothing

? 7 }

? 8 void ?my_sleep(int time)

? 9 {

?10 ?struct sigaction act,old;

?11 ?act.sa_handler=handler;

?12 ?act.sa_flags=0;

?13 ?sigemptyset(&act.sa_mask);

?14 ?sigaction(SIGALRM,&act,&old);

?15 ?alarm(time);//設置鬧鐘

?16 ?pause();

?17 ?int ret=alarm(0);//清理鬧鐘

?18 ?sigaction(SIGALRM,&old,NULL);恢復信號

?19 ?

?20 }

?21 int main()

?22 {

?23 ? ? while(1)

?26 ? ? ?{

?27 ? ? ?printf("I am waiting ?a signal....\n");

?28 ? ? ?my_sleep(5);

?29 ? ? ?}

?30 ? ? ?return 0;

?31 }?

?程序結果:每隔5秒打印一次信息,相當于調用了sleep()函數。


?程序分析:

? ?

1. main函數調用mysleep函數,后者調用sigaction注冊了SIGALRM信號的處理函數

sig_alrm。

2. 調用alarm(nsecs)設定鬧鐘。

3. 調用pause等待,內核切換到別的進程運行。

4. nsecs秒之后,鬧鐘超時,內核發SIGALRM給這個進程。

5. 從內核態返回這個進程的用戶態之前處理未決信號,發現有SIGALRM信號,其處理函數

是sig_alrm。

6. 切換到用戶態執行sig_alrm函數,進入sig_alrm函數時SIGALRM信號被自動屏蔽,

從sig_alrm函數返回時SIGALRM信號自動解除屏蔽。然后自動執行系統調用sigreturn再次進入 內核,再返回用戶態繼續執行進程的主控制流程(main函數調用的mysleep函數)。

7. pause函數返回-1,然后調用alarm(0)取消鬧鐘,調用sigaction恢復SIGALRM信號

以前的處理 動作。

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??




轉載于:https://blog.51cto.com/10541571/1770532

總結

以上是生活随笔為你收集整理的信号的基本概念的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。