在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一篇文章徹底搞定信號!

Linux愛好者 ? 來源:CSDN技術社區 ? 作者:903419 ? 2022-12-06 14:26 ? 次閱讀

1.信號是什么?

信號其實就是一個軟件中斷。

例:

輸入命令,在Shell下啟動一個前臺進程。

用戶按下Ctrl-C,鍵盤輸入產生一個硬件中斷。

如果CPU當前正在執行這個進程的代碼,則該進程的用戶空間代碼暫停執行, CPU從用戶態切換到內核態處理硬件中斷。

終端驅動程序將Ctrl-C解釋成一個SIGINT信號,記在該進程的PCB中(也可以說發送了一個SIGINT信號給該進程)。

當某個時刻要從內核返回到該進程的用戶空間代碼繼續執行之前,首先處理PCB中記錄的信號,發現有一個SIGINT信號待處理,而這個信號的默認處理動作是終止進程,所以直接終止進程而不再返回它的用戶空間代碼執行。

在這個例子中,由ctrl+c產生的硬件中斷就是一個信號。Ctrl+C產生的信號只能發送給前臺進程,命令后加&就可放到后臺運行。Shell可同時運行一個前臺進程和任意多個后臺進程,只有前臺進程才能接受到像CTRL+C這種控制鍵產生的信號。

2.信號的種類

使用命令查看:

kill-l

非可靠信號:1~31號信號,信號可能會丟失可靠信號:34~64號信號,信號不可能丟失

bf80fb7a-7387-11ed-8abf-dac502259ad0.png

SIGHUP:1號信號,Hangup detected on controlling terminal or death of controlling process(在控制終端上掛起信號,或讓進程結束),ation:term

SIGINT:2號信號,Interrupt from keyboard(鍵盤輸入中斷,ctrl + c ),action:term

SIGQUIT:3號信號,Quit from keyboard(鍵盤輸入退出,ctrl+ | ),action:core,產生core dump文件

SIGABRT:6號信號,Abort signal from abort(3)(非正常終止,double free),action:core

SIGKILL:9號信號,Kill signal(殺死進程信號),action:term,該信號不能被阻塞、忽略、自定義處理

SIGSEGV:11號信號,Invalid memory reference(無效的內存引用,解引用空指針、內存越界訪問),action:core

SIGPIPE:13號信號,Broken pipe: write to pipe with no readers(管道中止: 寫入無人讀取的管道,會導致管道破裂),action:term

SIGCHLD:17號信號,Child stopped or terminated(子進程發送給父進程的信號,但該信號為忽略處理的)

SIGSTOP:19號信號,Stop process(停止進程),action:stop

SIGTSTP:20號信號,Stop typed at terminal(終端上發出的停止信號,ctrl + z),action:stop

具體的信號采取的動作和詳細信息可查看:man 7 signal

3.信號的產生

3.1硬件產生

硬件產生即通過終端按鍵產生的信號:

ctrl + c:SIGINT(2),發送給前臺進程,& 進程放到后臺運行,fg 把剛剛放到后臺的進程,再放到前臺來運行

ctrl + z:SIGTSTP(20),一般不用,除非有特定場景

ctrl + | :SIGQUIT(3),產生core dump文件

產生core dump文件的條件:

當前OS一定不要限制coredump文件的大小,ulimit-a
磁盤空間要足夠
如何產生:
3.1解引用空指針,收到11號信號,產生coredump文件
3.2內存訪問越界,程序一旦崩潰,就會收到11號信號,也就會產生coredump文件
3.3 double free,收到6號信號,并產生core dump。
3.4free(NULL),不會崩潰

3.2軟件產生

軟件產生即調用系統函數向進程發信號

kill函數

#include
#include
intkill(pid_tpid,intsig);
參數解釋:
pid:進程號
sig:要發送的信號值
返回值:成功返回0,失敗返回-1,并設置錯誤

kill命令:kill -[信號] pid,

abort:void abort(void);,收到6號信號,誰調用該函數,誰就收到信號

alarm:unsigned int alarm(unsigned int seconds);,收到14號信號,告訴內核在seconds秒后給進程發送SIGALRM信號,該信號默認處理動作為終止當前進程。

4.信號的注冊

信號注冊又分為可靠信號的注冊和非可靠信號的注冊。信號注冊實際上是一個位圖和一個sigqueue隊列。bfbef272-7387-11ed-8abf-dac502259ad0.png

4.1非可靠信號的注冊

當進程收到非可靠信號時:

將非可靠信號對應的比特位置為1

添加sigqueue節點到sigqueue隊列當中,但是,在添加sigqueue節點的時候,隊列當中已然有了該信號的sigqueue節點,則不添加

4.2可靠信號的注冊

當進程所受到可靠信號時:

在sig位圖中更改信號對應的比特位為1不論之前sigqueue隊列中是否存在該信號的sigqueue節點,都再次添加sigqueue節點到sigqueue隊列當中去

5.信號的注銷

5.1非可靠信號的注銷

信號對應的比特位從1置為0將該信號的sigqueue節點從sigqueue隊列當中進行出隊操作

5.2可靠信號的注銷

將該信號的sigqueue節點從sigqueue隊列當中進行出隊操作需要判斷sigqueue隊列當中是否還有相同的sigqueue節點:①沒有了:信號比特位從1置為0②還有:不會更改sig位圖中的比特位

6.信號阻塞

6.1信號是怎樣阻塞的?

bfdf9c20-7387-11ed-8abf-dac502259ad0.png

信號的阻塞,并不會干擾信號的注冊。信號能注冊,但不能被立即處理,將block位圖中對應的信號比特位置為1,表示阻塞該信號進程收到該信號,還是一如既往的注冊當進程進入到內核空間,準備返回用戶空間的時候,調用do_signal函數,就不會立即去處理該信號了當該信號不被阻塞后,就可以進行處理了

6.2sigprocmask

函數原型:int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);參數解釋:

how,該做什么樣的操作
SIG_BLOCK:設置信號為阻塞
SIG_UNBLOCK:解除信號阻塞
SIG_SETMASK:替換阻塞位圖
set:用來設置阻塞位圖
SIG_BLOCK:設置某個信號為阻塞,block(new)=block(old)|set
SIG_UNBLOCK:解除某個信號阻塞,block(new)=block(old)&(~set)
SIG_SETMASK:替換阻塞位圖,block(new)=set
oldset:原來的阻塞位圖

例:下述例子,信號全部被阻塞,采用kill -9,將該進程結束掉

#include
#include
#include


voidsigncallback(intsignumber)
{
printf("changethesignal%d
",signumber);
}

intmain()
{
sigset_tset;
sigset_toldset;
sigfillset(&set);//所有比特位全置為1,則信號全部會被阻塞
sigprocmask(SIG_BLOCK,&set,&oldset);
while(1)
{
sleep(1);
}

return0;
}

結果:此時發送信號是不會有作用的,采用kill -9強殺掉

bffb4074-7387-11ed-8abf-dac502259ad0.png

7.信號未決

7.1 未決概念

實際執行信號的處理動作稱為信號遞達(Delivery),信號從產生到遞達之間的狀態,稱為信號未決(Pending)。進程可以選擇阻塞(Block)某個信號。被阻塞的信號產生時將保持在未決狀態,直到進程解除對此信號的阻塞,才執行遞達的動作。注意,阻塞和忽略是不同的,只要信號被阻塞就不會遞達,而忽略是、在遞達之后可選的一種處理動作。

7.2 sigpending

函數原型:int sigpending(sigset_t *set);讀取當前進程的未決信號集,通過set參數傳出。調用成功返回0,出錯返回-1.

例:

#include
#include
#include

voidsignalcallback(intsignumber)
{
printf("changsignumber%d
",signumber);
}
voidprintsigset(sigset_t*set)
{
inti=0;
for(;i

結果:c0119a22-7387-11ed-8abf-dac502259ad0.png

8.信號的處理方式

c044a598-7387-11ed-8abf-dac502259ad0.png

每個信號都有兩個標志位分別表示阻塞和未決,還有一個函數指針表示處理動作。

在上述例子中:

SIGHUP信號未阻塞也未產生過,當它遞達時執行默認處理動作。

SIGINT信號產生過,但正在被阻塞,所以暫時不能遞達。雖然它的處理動作是忽略,但在沒有解除阻塞之前不能忽略這個信號,因為進程仍有機會改變處理動作之后再解除阻塞。

SIGQUIT信號未產生過,一旦產生SIGQUIT信號將被阻塞,它的處理動作是用戶自定義函數sighandler。

8.1signal函數

該函數可以更改信號的處理動作。

typedefvoid(*sighandler_t)(int);
sighandler_tsignal(intsignum,sighandler_thandler);
參數解釋:

signum:更改的信號值
handler:函數指針,要更改的動作是什么

實際上,該函數內部也調用了sigaction函數。

8.2sigaction函數

讀取和修改與指定信號相關聯的處理動作。

intsigaction(intsignum,conststructsigaction*act,structsigaction*oldact);

參數解釋:

signum:待更改的信號值

struct sigaction結構體:

void(*sa_handler)(int);//函數指針,保存了內核對信號的處理方式
void(*sa_sigaction)(int,siginfo_t*,void*);//
sigset_tsa_mask;//保存的是當進程在處理信號的時候,收到的信號
intsa_flags;//SA_SIGINFO,OS在處理信號的時候,調用的就是sa_sigaction函數指針當中
//保存的值0,在處理信號的時候,調用sa_handler保存的函數
void(*sa_restorer)(void);

例:

#include
#include
#include

voidsigncallback(intsignumber)
{
printf("changesignumber%d
",signumber);
}


intmain()
{
structsigactionact;//act為入參
sigemptyset(&act.sa_mask);
act.sa_flags=0;
act.sa_handler=signcallback;

structsigactionoldact;//oldact為出參
sigaction(3,&act,&oldact);
while(1)
{
sleep(1);
}
return0;
}

結果:c06ab7f6-7387-11ed-8abf-dac502259ad0.png

8.3 自定義信號處理的流程

c082b806-7387-11ed-8abf-dac502259ad0.png

task_struct結構體中有一個struct sighand_struct結構體。

struct sighand_struct結構體有一個struct k_sigaction action[_NSIG]結構體數組。

該數組中,其中的_sighandler_t sa_handler保存的是信號的處理方式,通過改變其指向,可以實現我們對自定義信號的處理。

9.信號的捕捉

9.1信號捕捉的條件

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

9.2信號捕捉流程

c097d182-7387-11ed-8abf-dac502259ad0.png

內核態返回用戶態會調用do_signal函數,兩種情況:

無信號:sys_return函數,返回用戶態

有信號:先處理信號,信號返回,再調用do_signal函數例:

程序注冊了SIGQUIT信號的處理函數sighandler。

當前正在執行main函數,這時發生中斷或異常切換到內核態。

在中斷處理完畢后要返回用戶態的main函數之前檢查到有信號SIGQUIT遞達。

內核決定返回用戶態后不是恢復main函數的上下文繼續執行,而是執行sighandler函數, sighandler和main函數使用不同的堆棧空間,它們之間不存在調用和被調用的關系,是兩個獨立的控制流程。

sighandler函數返回后自動執行特殊的系統調用sigreturn再次進入內核態。

如果沒有新的信號要遞達,這次再返回用戶態就是恢復main函數的上下文繼續執行了。

10.常用信號集操作函數

intsigemptyset(sigset_t*set);://將比特位圖全置為0

intsigfillset(sigset_t*set);//將比特位圖全置為1

intsigaddset(sigset_t*set,intsignum);//將該set位圖,多少號信號置為1

intsigdelset(sigset_t*set,intsignum);//將該set位圖,多少號信號置為0

intsigismember(constsigset_t*set,intsignum);//信號signum是否是set位圖中的信號

11.SIGCHLD信號

該信號是子進程在結束是發送給父進程的信號,但是該信號的處理方式是默認處理的。父進程對子進程發送過來的SIGCHLD信號進行了忽略處理,就會導致子進程成為僵尸進程。

可以自定義該信號的處理方式:

#include
#include
#include
#include
#include
#include

voidsigncallback(intsignumber)
{
printf("changesignal%d
",signumber);
wait(NULL);
}

intmain()
{
signal(17,signcallback);
pid_tpid=fork();
if(pid

指令查看后臺:ps aux | grep ./fork

c0b0f310-7387-11ed-8abf-dac502259ad0.png

審核編輯:湯梓紅

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • cpu
    cpu
    +關注

    關注

    68

    文章

    10889

    瀏覽量

    212389
  • 信號
    +關注

    關注

    11

    文章

    2797

    瀏覽量

    76940
  • 中斷
    +關注

    關注

    5

    文章

    900

    瀏覽量

    41590

原文標題:一篇文章徹底搞定信號!

文章出處:【微信號:LinuxHub,微信公眾號:Linux愛好者】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    全面認識MOS管,文章就夠了

    今天勢必要來文章,徹底掌握mos管!
    的頭像 發表于 06-13 10:37 ?2w次閱讀
    全面認識MOS管,<b class='flag-5'>一</b><b class='flag-5'>篇</b>文章就夠了

    徹底掌握MOS管

    基礎知識中 MOS 部分遲遲未整理,實際分享的電路中大部分常用電路都用到了MOS管, 今天勢必要來文章,徹底掌握mos管!
    發表于 07-05 11:56 ?3w次閱讀

    文章徹底搞定Linux信號

    輸入命令,在 Shell 下啟動個前臺進程。
    發表于 11-21 11:26 ?319次閱讀

    徹底搞定指針

    本帖最后由 zgzzlt 于 2012-8-16 13:43 編輯 徹底搞定指針
    發表于 08-07 14:00

    徹底搞定C指針

    本帖最后由 發燒友之麒麟 于 2014-10-6 09:17 編輯 徹底搞定C指針教程,個人覺得寫得很好,希望對大家有幫助[attach]214619[/attach下面是個更深入理解C指針
    發表于 09-30 13:47

    如何搞定PCB設計的差分信號

    來源:互聯網在高速PCB設計中,差分信號的應用越來越廣泛,這主要原因是和普通的單端信號走線相比,差分信號具有抗干擾能力強、能有效抑制EMI、時序定位精確的優勢。作為名(準)PCB設計
    發表于 10-23 08:36

    徹底搞定電路設計中的接地問題

    徹底搞定電路設計中的接地問題
    發表于 06-08 06:53

    【178頁完整版】輕松搞定C語言(提高)!!

    【178頁完整版】輕松搞定C語言(提高)!!需要完整版的朋友可以下載附件保存哦~
    發表于 08-16 10:58

    輕松搞定C語言(提高)

    太大,上傳不了附件,以下是網盤鏈接:輕松搞定C語言(提高)鏈接:https://pan.baidu.com/s/1epKmrHjVZddkOiRugTSgXQ 提取碼:cq6c
    發表于 09-14 17:29

    徹底搞定C指針_姚云飛

    徹底搞定C指針》是互聯網上下載次數最多的針對C指針問題的中文資源之。現在,經由修訂者的重新修訂、編輯與排版,本書的《完全版修訂增補版》全新登場。新版本中的技術用
    發表于 02-02 10:58 ?0次下載
    <b class='flag-5'>徹底</b><b class='flag-5'>搞定</b>C指針_姚云飛

    徹底搞定C指針

    徹底搞定C指針。
    發表于 03-17 09:59 ?1次下載

    徹底搞定C語言指針詳解完整版

    徹底搞定C語言指針詳解完整版。
    發表于 05-10 17:04 ?0次下載

    幾招搞定iPhone手機WiFi信號不穩定

    有的時候,我們會發現我們的iPhone WiFi信號總是不滿格,用起來還很卡。對此許多果粉都束手無策,其實只要簡單幾招,就可以搞定這個問題。
    發表于 08-22 18:22 ?10.1w次閱讀

    多軸伺服,搞定

    多軸伺服,搞定
    的頭像 發表于 10-19 17:54 ?677次閱讀
    多軸伺服,<b class='flag-5'>一</b>芯<b class='flag-5'>搞定</b>

    難搞的工業信號調節,零漂移運算放大器是如何搞定的?

    難搞的工業信號調節,零漂移運算放大器是如何搞定的?
    的頭像 發表于 12-06 16:59 ?623次閱讀
    難搞的工業<b class='flag-5'>信號</b>調節,零漂移運算放大器是如何<b class='flag-5'>搞定</b>的?
    主站蜘蛛池模板: 床上激情四射| 中国色老头| 草草操| 国产成+人+综合+亚洲欧美丁香花| 你懂的网站在线| 巨乳色最新网址| 国产精品人成在线播放新网站| 欧美网站免费| 久久澡人人澡狠狠澡| 日本大片黄色| 可以免费看的黄色片| 欧美一级日韩在线观看| 免费网站成人亚洲| 国产三级播放| 天天做天天添天天谢| 久久成人影视| 一区二区三区四区视频| 成人啪啪免费视频| 男女视频在线观看| 日本不卡视频在线| 亚洲成在人色婷婷| 欧美.成人.综合在线| 操农村妇女| 久久久久国产免费| 亚洲夂夂婷婷色拍ww47| 亚洲香蕉国产高清在线播放| 日韩a一级欧美一级| 永久黄色免费网站| 中文字幕一区二区三| 黄色国产在线观看| 国产亚洲第一| 日韩欧美一区二区三区视频| 三级第一页| 国内a级毛片免费···| 午夜久久久久久久| 视频在线观看网站| 在线免费观看一级毛片| 亚洲欧美人成网站综合在线| 不卡视频一区二区| 色老头久久久久| 国产码一区二区三区|