珠海 網(wǎng)站建設(shè)深圳網(wǎng)絡(luò)營(yíng)銷(xiāo)推廣公司
信號(hào)的處理方式是遠(yuǎn)遠(yuǎn)比信號(hào)的產(chǎn)生
當(dāng)鬧鐘響了就知道時(shí)間到了,說(shuō)明對(duì)應(yīng)信號(hào)處理方法比信號(hào)產(chǎn)生更早
操作系統(tǒng)的信號(hào)處理方法在編寫(xiě)操作系統(tǒng)的時(shí)候就已經(jīng)編寫(xiě)好了
signal函數(shù)
1.1所有的信號(hào)

1.2 signal函數(shù)的概念和簡(jiǎn)單使用
捕捉信號(hào)就是自定義對(duì)應(yīng)的信號(hào)的處理方法
9號(hào)信號(hào)殺死進(jìn)程;不可以被捕捉,因?yàn)槿绻徊蹲?#xff0c;那么對(duì)應(yīng)進(jìn)程就是無(wú)敵的不能被殺死

#include<stdio.h>
#include<unistd.h>
#include<signal.h>void headler(int signo)
{printf("signal NO.%d change\n",signo);
}
int main()
{signal(2,headler);//函數(shù)名不加()就是一個(gè)函數(shù)指針while(1){printf("hello world pid: %d\n",getpid());sleep(1);}return 0;
}
執(zhí)行結(jié)果:ctrl+c發(fā)送二號(hào)信號(hào),二號(hào)信號(hào)默認(rèn)是終止進(jìn)程

2.信號(hào)的產(chǎn)生方式
2.1.鍵盤(pán)產(chǎn)生
Ctrl+c 2號(hào)信號(hào)
Ctrl+\ 3號(hào)信號(hào)
Ctrl+z 20號(hào)信號(hào)
給對(duì)應(yīng)進(jìn)程發(fā)對(duì)應(yīng)信號(hào),命令格式:kill -信號(hào)編號(hào) 進(jìn)程的pid
2.2程序奔潰,OS給進(jìn)程發(fā)信號(hào)
代碼中有一個(gè)除零錯(cuò)誤
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
void headler(int signo)
{printf("signal NO.%d change\n",signo);
}
int main()
{int i=1;while(i<=31){//捕獲“”所有”信號(hào)signal(i,headler);i++;}int tem=10;//除零錯(cuò)誤tem/=0;return 0;
}
執(zhí)行錯(cuò)誤:會(huì)發(fā)送一個(gè)8號(hào)信號(hào)

2.3.系統(tǒng)調(diào)用
kill:給任意一個(gè)進(jìn)程發(fā)任意信號(hào)

raise:給當(dāng)前進(jìn)程發(fā)信號(hào)

2.4軟件條件
概念:通過(guò)某種軟件(OS),來(lái)觸發(fā)信號(hào)的發(fā)送,定時(shí)器或者某種操作達(dá)到條件不就緒等這樣等場(chǎng)景,來(lái)觸發(fā)信號(hào)發(fā)送;
定時(shí)器或者某種操作達(dá)到條件不就緒:比如管道的讀端不寫(xiě)且關(guān)閉讀端,那么就會(huì)向?qū)懚税l(fā)送SIGPIPE信號(hào)
2.alarm定時(shí)器

2.4.1.可以使用alarm證明CPU的計(jì)算速度遠(yuǎn)大于打印的速度
1s中count計(jì)算打印了多少次;
#include<stdio.h>
#include<unistd.h>
#include<signal.h>int main()
{int count=0;alarm(1);while(1){count++;printf("count: %d\n",count);}return 0;
}

1s中count計(jì)算會(huì)有多少次
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
int count=0;
void handler(int signo)
{printf("count: %d\n",count);
}int main()
{alarm(1);signal(14,handler);while(1){count++;}return 0;
}
執(zhí)行結(jié)果:可以證明CUP計(jì)算速度遠(yuǎn)大于打印速度

3.OS如何識(shí)別信號(hào)
實(shí)際執(zhí)行信號(hào)的處理動(dòng)作稱(chēng)為信號(hào)遞達(dá)(Delivery) ;
信號(hào)從產(chǎn)生到遞達(dá)之間的狀態(tài),稱(chēng)為信號(hào)未決(Pending);(接受到信號(hào)了,但是還沒(méi)有處理)
進(jìn)程可以選擇阻塞 (Block )某個(gè)信號(hào);(保持這個(gè)信號(hào)為未決)
識(shí)別信號(hào)
先看block位圖(也叫信號(hào)屏蔽字)是否被阻塞;
如果沒(méi)有阻塞再看pending位圖是否接收到信號(hào);
如果接收到信號(hào)再看handler函數(shù)指針數(shù)組按SIG_DFL(默認(rèn))、SIG_IGN(忽略)、具體的函數(shù)指針就是自定義執(zhí)行

4.信號(hào)集操作函數(shù)
4.1.sigset_t的接口
sigset_t是一個(gè)位圖結(jié)構(gòu)

#include<signal.h>
int sigemptyset(sigset_t *set);//初始化對(duì)象,全為設(shè)為為0
int sigfillset(sigset_t *set);//把所有信號(hào)置為1
int sigaddset (sigset_t *set, int signo);//把幾號(hào)信號(hào)為1
int sigdelset(sigset_t *set, int signo);//把幾號(hào)信號(hào)為0
int sigismember(const sigset_t *set, int signo); //判斷是否有幾號(hào)信號(hào),返回真1假0
4.2.sigprocmask
調(diào)用函數(shù)sigprocmask可以讀取或更改進(jìn)程的信號(hào)屏蔽字(阻塞信號(hào)集)。
#include<signall.h>
int sigprocmask(int how, const sigset_t *set, sigset_t *oset); 返回值:若成功則為0,若出錯(cuò)則為-1

4.3.sigpending
#include<signal.h>
sigpending(sigset_t* set);
讀取當(dāng)前進(jìn)程的未決信號(hào)集
4.4.簡(jiǎn)單使用
#include<stdio.h>
#include<unistd.h>
#include<signal.h>void show(sigset_t* set)
{int i=1;while(i<32){if(sigismember(set,i))//信號(hào)為1則為真printf("1");elseprintf("0");i++;}printf("\n");
}
int main()
{sigset_t iset,pending;sigemptyset(&iset);//初始化sigaddset(&iset,2);//添加2號(hào)信號(hào)sigprocmask(SIG_SETMASK,&iset,NULL);//把信號(hào)屏蔽字改為isetwhile(1){sigemptyset(&pending);//初始化sigpending(&pending);//獲取pending位圖show(&pending);sleep(1);}return 0;
}
執(zhí)行結(jié)果:屏蔽了2號(hào)信號(hào),2號(hào)信號(hào)是未決的

5.信號(hào)的捕捉的全過(guò)程和信號(hào)的處理時(shí)機(jī)
信號(hào)的處理時(shí)機(jī):從內(nèi)核態(tài)返回到用戶(hù)態(tài),做信號(hào)的檢測(cè)并處理;

6.volatile
volatile:告訴編譯器,不要優(yōu)化被volatile修飾的變量
#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#include<iostream>
using namespace std;
int main()
{const int t=10;int* p=const_cast<int*>(&t);*p=20;printf("t: %d\n",t);printf("*p: %d\n",*p);return 0;
}
執(zhí)行結(jié)果:t被const修飾,編譯器去t的值不會(huì)取內(nèi)存中取

volatile const int t=10;//既可以解決
7.SIGCHLD信號(hào)
SIGCHLD:當(dāng)子進(jìn)程退出會(huì)給父進(jìn)程發(fā)17號(hào)信號(hào)SIGCHLD
#include<unistd.h>
#include<signal.h>
#include<iostream>
using namespace std;
void handler(int signo)
{cout<<signo<<endl;cout<<getpid()<<endl;
}
int main()
{signal(SIGCHLD,handler);if(fork()==0){int cnt=5;while(cnt){cout<<"I am child process, "<<getpid()<<endl;cnt--;sleep(1);}return 0;}while(1);
}


可以使用下面代碼替換上面的signal(SIGCHLD,handler);就可以做到在不需要子進(jìn)程的退出信息時(shí)自動(dòng)釋放
signal(SIGCHLD,SIG_IGN);