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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux之信号

發(fā)布時間:2023/11/30 linux 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux之信号 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

信號:在生活中,我們遇到過不同種類的信號,比如:(交通信號,乃至某個人的表情,動作等帶給你不同的信號)然而,在我們的linux下,我們最熟悉的就是,當遇到一個死循環(huán)的程序時,我們第一想到的就是按ctrl+c,此時這個進程立馬終止,這是一種通過鍵盤產生的信號。而說起ctrl+c,就引出了前臺進程和后臺進程。當ctrl+c產生的信號只能發(fā)給前臺進程。

用kill -l命令就可以查看信號了;


產生信號的另一種方式是:信號異常觸發(fā)系統(tǒng)使該進程終止:

例子:

運行結果:



還有一種方式,通過指令來使該進程終止


然后直接運行./test:



還有一種方式,通過alarm使進程終止

說起alarm給大家舉個例子吧,alarm意思是鬧鐘,在這里也同樣代表著當你執(zhí)行某個進程時,突然用alarm定時的時間到了,這時鬧鐘發(fā)揮了作用,使得你的進程被迫停止,比如:


這是一個統(tǒng)計1秒鐘計數(shù)的程序,當一秒鐘到時,就會被SIGALRM信號終止。

運行結果:


下面我們來說一下處理信號的幾種方式吧!

忽略信號;執(zhí)行默認;執(zhí)行自定義(信號的捕捉)三種方式。(那么問題來了,什么時候處理呢?答案是適當?shù)臅r候處理)


執(zhí)行信號的處理動作稱為信號遞達,信號從產生到遞達之間的狀態(tài),稱為信號未決。進程可以選擇阻塞某個信號,被阻塞的信號產生時將保持在未決狀態(tài),直到進程解除對此信號的阻塞,才執(zhí)行遞達的動作。

阻塞和忽略是不同,只要信號被阻塞就不會遞達,而忽略則是在遞達之后可選的一種處理動作。

信號在內核中是這樣表示的:


block:代表屏蔽狀態(tài)字(1表示阻塞,0表示不阻塞)

pending:代表未決(1表示未決,0表示可以遞達)

handler:代表信號的處理方式(默認,忽略,自定義)

每個信號都有兩個標志位分別表示阻塞(block)和未決(pending),還有一個函數(shù)指針表示處理動作。信號產生時,內核在進程控制塊中設置該信號的未決標志,直到信號遞達才清除該標志。

上面那張表說明:SIGHUP是沒有阻塞也沒有產生,所以處理動作為默認處理動作

SIGINT的block為1,pending也為1,表示正在阻塞,無法遞達。它的處理動作為忽略,但是在沒有解除阻塞之前不能忽略該信號,很可能在解除阻塞前改變?yōu)槠渌奶幚韯幼鳌?/span>

對于上述的三張表,操作系統(tǒng)中的每個進程運行時都會存在。

SIGQUIT的block為1,pending為0,說明正在被阻塞,解除阻塞后就可以遞達。處理動作為用戶自定義的處理動作。

還有一種現(xiàn)象是,對于解除阻塞之前可能會發(fā)送多次信號,這時操作系統(tǒng)該作何處理呢。這里主要是分為普通信號和實時信號,普通信號出現(xiàn)發(fā)送多次的情況,會當做是一次信號進行處理。而實時信號發(fā)送多次的情況,會將這多個信號存在一個隊列中,分別處理各個信號。我們一般討論的是普通信號,因此只記錄一次,我們將未決和阻塞狀態(tài)用同一個數(shù)據(jù)類型來存儲sigset_t,信號集為sigset_t。還需要注意的一點是,阻塞信號集也叫做當前進程的信號屏蔽字。

說了信號集,我們之前說過這些普通信號是以位圖的形式存放的。每一個bit位表示一種信號是否存在。

對于信號的操作,我們有一組信號集操作函數(shù),如下:


函數(shù)sigemptyset初始化set所指向的信號集,使其中所有信號的對應bit清零,表示該信號集不包含任何有效信號。

函數(shù)sigfillset初始化set所指向的信號集,使其中所有信號的對應bit置位,表?示 該信號集的有效信號包括系統(tǒng)支

持的所有信號。

在使?用sigset_t類型的變量之前,?一定要調 ?用sigemptyset或sigfillset做初始化,使信號集處于確定的狀態(tài)。

做完初始化之后調用sigaddset和sigdelset來添加或者刪除信號。

這四個函數(shù)成功返回0,失敗返回-1;

sigismember用來表示某種信號是否出現(xiàn)在有效信號集中。出現(xiàn)返回1,不出現(xiàn)返回0.

*還有函數(shù)sigprocmask:(讀取或更改進程的信號屏蔽字)

#include <signal.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset);

成功返回0,出錯返回-1

這里的oset為輸出型參數(shù),如果oset為非空,則輸出當前進程的信號屏蔽字,通過oset輸出。如果set為非空,則更改信號屏蔽字,how指示如何更改。如果set和oset都為非空,則將當前進程的信號屏蔽字備份在oset中,然后再通過how參數(shù)更改信號屏蔽字。

how主要有三種表示:SIG_BLOCK(包含了我們希望添加的信號屏蔽字),SIG_UNBLOCK(包含了我們希望從信號屏蔽字中阻塞的信號),SIG_SETMASK(設置了當前的信號屏蔽字的值);

*函數(shù)sigpending:(讀取當前進程的未決信號集)

#include <signal.h>
int sigpending(sigset_t *set);

set為輸出型參數(shù),將信號通過set輸出

?小栗子:

#include<stdio.h> #include<signal.h>void PrintSigset(sigset_t *sig) {int i = 0;for(i = 1; i < 32; i++){if(sigismember(sig,i)){printf("1 ");}else{printf("0 ");}}printf("\n"); }int main() {sigset_t sigset,osigset;sigemptyset(&sigset);sigemptyset(&osigset);sigaddset(&sigset,SIGINT);sigprocmask(SIG_BLOCK,&sigset,&osigset);while(1){sigpending(&sigset);PrintSigset(&sigset);sleep(1);}return 0; } 這個程序實現(xiàn)了將2號信號設置為阻塞信號。所以一直無法遞達。

程序運行時,每秒鐘把各信號的未決狀態(tài)打印一遍,由于我們阻塞了SIGINT信號,按Ctrl-C將會使SIGINT信號處于未決

狀態(tài),按Ctrl-\和ctrl+z仍然可以終止程序,因為SIGQUIT信號沒有阻塞。

運行結果:


還有一個小栗子,我們將2號信號阻塞之后,5秒后解除阻塞。并打印原來信號的狀態(tài)。

#include<stdio.h> #include<signal.h>void PrintSigset(sigset_t *sig) {int i = 0;for(i = 1; i < 32; i++){if(sigismember(sig,i)){printf("1 ");}else{printf("0 ");}}printf("\n"); }void handler(int sig) {printf("pid: %d sig:%d \n",getpid(),sig); } int main() {sigset_t sigset,osigset;sigemptyset(&sigset);sigemptyset(&osigset);sigaddset(&sigset,SIGINT);sigprocmask(SIG_BLOCK,&sigset,&osigset);int count = 0;signal(2,handler);//signal(2,SIG_DFL);while(1){sigpending(&sigset);PrintSigset(&sigset);sleep(1);if(count++ > 5){sigprocmask(SIG_SETMASK,&osigset,NULL);count = 0;}}return 0; }
運行結果:




總結

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

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