国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【linux】信號(hào)——信號(hào)產(chǎn)生

這篇具有很好參考價(jià)值的文章主要介紹了【linux】信號(hào)——信號(hào)產(chǎn)生。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

自我名言只有努力,才能追逐夢(mèng)想,只有努力,才不會(huì)欺騙自己。【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
喜歡的點(diǎn)贊,收藏,關(guān)注一下把!【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

首先說(shuō)明一點(diǎn)信號(hào)不是信號(hào)量。不能把這兩個(gè)東西放在一起。

那信號(hào)講什么呢?
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

1.預(yù)備知識(shí)

那信號(hào)是怎么回事,這里只能這樣說(shuō),信號(hào)是針對(duì)進(jìn)行發(fā)送某種信號(hào)到來(lái)的一種機(jī)制,讓信號(hào)能被進(jìn)程處理。,讓我們?cè)诤竺娴闹R(shí)中,更能理解這句話的含義。

先見(jiàn)識(shí)見(jiàn)識(shí)信號(hào)。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
前面數(shù)字是信號(hào)的編號(hào),后面大寫(xiě)的是宏。
就比如殺死一個(gè)進(jìn)程

kill -9  進(jìn)程pid

這里可以使用編號(hào),也可以使用SIGKILL

再可以數(shù)一數(shù)信號(hào)有多少個(gè)。
其實(shí)并沒(méi)有64個(gè),0,32,33信號(hào)是沒(méi)有的。
【1,31】普通信號(hào)
【34,64】實(shí)時(shí)信號(hào) (我們不學(xué)這個(gè))

先說(shuō)信號(hào)的概念幫我們簡(jiǎn)單了解一下信號(hào),但再說(shuō)信號(hào)一些概念之前,我們先從生活角度中的信號(hào)來(lái)幫我們理解。

生活中的信號(hào):
1.紅綠燈
2.鬧鐘
3.信息通知
4.勞資蜀道三
5.女朋友把你拉黑
6.烽火臺(tái)狼煙
等等這些都是我們生活中的信號(hào)。

我們以紅綠燈為例。人是能夠識(shí)別紅綠燈的。
這里識(shí)別有兩層意思。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

第一個(gè)問(wèn)題可能會(huì)覺(jué)得很奇怪,你為什么能夠識(shí)別紅綠燈?

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

第二個(gè)問(wèn)題,當(dāng)信號(hào)來(lái)的時(shí)候,你不一定會(huì)立即處理這個(gè)信號(hào)

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

信號(hào)的產(chǎn)生是異步的。

舉個(gè)栗子,你正在宿舍打著游戲,這時(shí)外賣(mài)小哥給你打電話讓你下樓取餐,但是你忙著打著游戲并沒(méi)有立刻下樓去取,而是讓他把外賣(mài)放在樓下。當(dāng)你打完游戲,記起還有外賣(mài)沒(méi)拿,所以去樓下拿外賣(mài)。當(dāng)然還有另一種情況,你打游戲上頭了。然后忘記有外賣(mài)在樓下這回事。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

當(dāng)綠燈到達(dá)的時(shí)候,你有三種處理動(dòng)作

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

如何把上面的這些概念遷移到進(jìn)程中呢?

這里要有一個(gè)共識(shí):信號(hào)是給進(jìn)程發(fā)的

  1. 進(jìn)程是如何識(shí)別信號(hào)的?(認(rèn)識(shí)+動(dòng)作)
    進(jìn)程本身就是程序員編寫(xiě)的屬性和邏輯的集合。所以這里先粗略的說(shuō)是由程序員編碼完成的。(后面學(xué)了信號(hào)更多知識(shí)就可以詳細(xì)說(shuō)明了)。

  2. 當(dāng)進(jìn)程收到信號(hào)的時(shí)候,進(jìn)程可能正在執(zhí)行更重要的代碼,所以信號(hào)不一定會(huì)被立即處理

  3. 進(jìn)程本身必須要有對(duì)于信號(hào)的保存能力

  4. 進(jìn)程在處理信號(hào)的時(shí)候,一般有三種動(dòng)作(默認(rèn),自定義,忽略)【信號(hào)被捕捉】

在我們現(xiàn)在還沒(méi)有學(xué)過(guò)信號(hào),上面1,2,4我們都不能具體解釋?zhuān)贿^(guò)3我們可以根據(jù)以往學(xué)過(guò)的知識(shí)來(lái)分析分析。

如果一個(gè)信號(hào)是發(fā)給進(jìn)程的,而進(jìn)程要保存,那么應(yīng)該保存在哪里?
task_struct(PCB)結(jié)構(gòu)體中。

如何保存呢? 更準(zhǔn)確來(lái)說(shuō)如何保存是否收到了指定信號(hào)【1,31】。
是否是一種兩態(tài),我們是不是可以在task_struct結(jié)構(gòu)體里,當(dāng)然task_struct結(jié)構(gòu)體中包含其他一大堆的屬性,可以存在一個(gè)unsigned int signal32位比特位。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
所以在進(jìn)程中是不是只要存在對(duì)應(yīng)的位圖結(jié)構(gòu),然后當(dāng)我們收到信號(hào)時(shí),是不是只要將對(duì)應(yīng)信號(hào)的位置由0->1,就代表我們已經(jīng)完成了信號(hào)的發(fā)送,并且讓進(jìn)程暫時(shí)把這個(gè)信號(hào)保存起來(lái)了。

那如何理解信號(hào)的發(fā)送呢?
發(fā)送信號(hào)的本質(zhì):修改PCB的信號(hào)位圖!
PCB是內(nèi)核維護(hù)的數(shù)據(jù)結(jié)構(gòu)對(duì)象----->PCB的管理者是OS,誰(shuí)有權(quán)力修改PCB中的內(nèi)容呢?------>OS!!

所以無(wú)論未來(lái)我們學(xué)習(xí)多少種發(fā)送信號(hào)的方式,本質(zhì)都是通過(guò)OS向目標(biāo)進(jìn)程發(fā)送的信號(hào)!!
未來(lái)想讓用戶(hù)也能發(fā)送信號(hào)------->OS必須要提供發(fā)送信號(hào),處理信號(hào)的相關(guān)系統(tǒng)調(diào)用!

我們使用kill命令,底層一定調(diào)用了對(duì)應(yīng)的系統(tǒng)調(diào)用!

2.信號(hào)產(chǎn)生

2.1通過(guò)鍵盤(pán)發(fā)送信號(hào)

int main()
{
    int cnt=0;
    while(true)
    {
        printf("我是一個(gè)進(jìn)程,我正在運(yùn)行%d\n",cnt++);
        sleep(1);
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
ctrl+c熱鍵,終止前臺(tái)進(jìn)程。
本質(zhì)ctrl+c是一個(gè)組合鍵---->OS識(shí)別---->OS將ctrl+c解釋成為2號(hào)信號(hào),2)SIGINT----->處理(三種動(dòng)作)。但我們對(duì)2號(hào)信號(hào)沒(méi)做任何改變,所以是默認(rèn)處理。

man 7 signal //查看信號(hào)對(duì)應(yīng)的手冊(cè)

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
Action(行為):Term (Terminal終端)結(jié)束進(jìn)程
Comment(解釋):從鍵盤(pán)中斷

所以2號(hào)信息的默認(rèn)動(dòng)作,結(jié)束進(jìn)程。

接下來(lái)驗(yàn)證一下是不是發(fā)送了2號(hào)信號(hào)。

先介紹一個(gè)函數(shù)signal,對(duì)指定的信號(hào)設(shè)置一個(gè)自定義動(dòng)作。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
signum:信號(hào)編號(hào)(捕捉那個(gè)信號(hào))
handler:函數(shù)指針(捕捉這個(gè)信號(hào)后,你想怎么做,這是一個(gè)回調(diào)函數(shù))

接下來(lái)驗(yàn)證

#include<iostream>
#include<unistd.h>
#include<cstdio>
#include<signal.h>

void handler(int signo)
{
    cout<<"捕捉到信號(hào):"<<signo<<endl;
}

int main()
{
    signal(2,handler);
    int cnt=0;
    while(true)
    {
        printf("我是一個(gè)進(jìn)程,我正在運(yùn)行%d\n",cnt++);
        sleep(1);
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
我不是對(duì)2號(hào)信號(hào)進(jìn)行捕捉嗎,并且代碼還做了修改,為什么運(yùn)行結(jié)果沒(méi)什么變化。

注意,這里是signal函數(shù)的調(diào)用,并不是handler的調(diào)用,并且僅僅是設(shè)置了對(duì)信號(hào)的捕捉方法,并不代表方法被調(diào)用了。所以一般這個(gè)方法不會(huì)執(zhí)行,除非收到對(duì)應(yīng)的信號(hào)。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
這兩種方法都可以發(fā)送信號(hào)。然后signal函數(shù)對(duì)2號(hào)信息進(jìn)行捕捉。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

現(xiàn)在發(fā)2號(hào)信號(hào),雖然能被捕捉,但是進(jìn)程怎么退不出來(lái)了。
這是因?yàn)槲覀儼?號(hào)信號(hào)默認(rèn)動(dòng)作,改成了自定義動(dòng)作。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
如果想退出怎么辦?

kill -9 編號(hào)  //殺死進(jìn)程

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
或者在自定義動(dòng)作種加一個(gè)exit。

void handler(int signo)
{
    cout<<"進(jìn)程捕捉到了一個(gè)信號(hào),信號(hào)編號(hào)是:"<<signo<<endl;
    exit(0);
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

其實(shí)還有一個(gè)組合建ctrl+\,發(fā)送的是3號(hào)信號(hào)。也能終止進(jìn)程。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
這里留了一個(gè)問(wèn)題,Core和Trem都是終止進(jìn)程。為什么OS要設(shè)置兩種不同的行為有什么用?

2.2系統(tǒng)調(diào)用接口向進(jìn)程發(fā)送信號(hào)

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

kill可以給任意進(jìn)程發(fā)送任意信號(hào)。

pid:目標(biāo)進(jìn)程pid
sig:發(fā)送幾號(hào)信號(hào)
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
成功返回0,識(shí)別返回-1。
我們給進(jìn)程發(fā)信號(hào)底層用的就是這個(gè)。

前面說(shuō)過(guò),信號(hào)是由OS向進(jìn)程發(fā)送的。OS有這個(gè)能力,但不代表有權(quán)限使用這個(gè)能力。
信號(hào)的發(fā)送是由用戶(hù)發(fā)起而OS執(zhí)行的。

接下來(lái)我們寫(xiě)的代碼想呈現(xiàn)這樣的效果,一個(gè)進(jìn)程正在運(yùn)行,另一個(gè)進(jìn)程在命令行給這個(gè)進(jìn)程發(fā)送任意信號(hào)。

//mysignal.cc

#include<iostream>
#include<unistd.h>
#include<cstdio>
#include<signal.h>
#include<sys/types.h>
#include<string>

using namespace std;


void Usage(const string& proc)
{
    cout<<"\nUsage "<<proc<<" pid signo\n"<<endl;
}

// ./mysignal pid signo------>命令行參數(shù)
int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        Usage(argv[0]);
        exit(1);
    }
    
    pid_t id=stoi(argv[1]);
    int signo=stoi(argv[2]);
    int n=kill(id,signo);
    if(n != 0)
    {
        perror("kill");
    }

    return 0;
}

//mytest.cc

#include<iostream>
#include<unistd.h>

int main()
{
    int cnt=0;
    while(true)
    {
        printf("我是一個(gè)進(jìn)程,pid:%d,我正在運(yùn)行%d\n",getpid(),cnt++);
        sleep(1);
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
這個(gè)不就是和我們?cè)诿钚袌?zhí)行kill命令一樣的原理嗎。

kill(),可以向任意進(jìn)程發(fā)送任意信號(hào)

raise,給自己發(fā)送任意信號(hào)。----->就相當(dāng)于 kill(getpid(),任意信號(hào))

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

int main()
{
    int cnt=0;
    while(true)
    {
        printf("cnt:%d,pid:%d\n",cnt++,getpid());
        if(cnt == 10)
            raise(9);
        sleep(1);
    }
        return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

abort,給自己發(fā)送指定的信號(hào)(6號(hào)信號(hào))。------>相當(dāng)于kill(getpid(),SIGABRT)

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

int main()
{
    int cnt=0;
    while(true)
    {
        printf("cnt:%d,pid:%d\n",cnt++,getpid());
        if(cnt == 10)
           abort();
        sleep(1);
    }
        return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

關(guān)于信號(hào)處理的行為的理解:有很多的情況,進(jìn)程收到大部分的信號(hào),默認(rèn)處理動(dòng)作都是終止進(jìn)程。

既然大部分信號(hào)默認(rèn)都是終止進(jìn)程,那有那么多類(lèi)的信號(hào)有什么用?

信號(hào)的意義:信號(hào)的不同,代表不同的事情,但是對(duì)事情發(fā)生之后的處理可以一樣。
也就是說(shuō)進(jìn)程意外終止了,我們可以根據(jù)信號(hào)不同來(lái)確定是什么原因?qū)е碌摹?/p>

2.3硬件異常產(chǎn)生信號(hào)

信號(hào)產(chǎn)生,不一定非得是用戶(hù)顯示發(fā)送的。

看下面一段代碼

int main()
{
    int cnt=0;
    while(true)
    {
         printf("cnt:%d,pid:%d\n",cnt++,getpid());
         int a=10;
         a/=0;       
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

為什么除0會(huì)終止進(jìn)程?
因?yàn)楫?dāng)前進(jìn)程會(huì)收到來(lái)自O(shè)S發(fā)送的信號(hào)。SIGPFE。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

如何證明呢?

void handler(int signo)
{
    cout<<"進(jìn)程捕捉到了一個(gè)信號(hào),信號(hào)編號(hào)是:"<<signo<<endl;
}

int main(int argc,char* argv[])
{
    signal(SIGFPE,handler);
    int cnt=0;
    while(true)
    {
         printf("cnt:%d,pid:%d\n",cnt++,getpid());
         int a=10;
         a/=0;       
    }
     return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
我確實(shí)捕捉到了8號(hào)信號(hào),但為什么OS一直發(fā)送信號(hào)呢?
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
難道是我這里一直在死循環(huán)的原因?

修改一下代碼

int main()
{
    signal(SIGFPE,handler);
    int cnt=0;
    int a=10;
    a/=0;   
    while(true)
    {
        printf("cnt:%d,pid:%d\n",cnt++,getpid());
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
發(fā)現(xiàn)還是一直在發(fā)送8號(hào)信號(hào)。
這到底是為什么?

先來(lái)解答,OS如何得知應(yīng)該給當(dāng)前進(jìn)程發(fā)送8號(hào)信號(hào)呢?或OS怎么知道我除0了呢?

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
CPU運(yùn)算異常了,OS會(huì)不會(huì)知道?
OS肯定會(huì)知道CPU運(yùn)算出現(xiàn)了問(wèn)題,因?yàn)镺S是軟硬件資源的管理者。

OS查看到狀態(tài)寄存器溢出位由0->1,OS就識(shí)別到CPU內(nèi)部出錯(cuò)了。
誰(shuí)導(dǎo)致CPU出錯(cuò)了?
CPU當(dāng)前正在調(diào)度誰(shuí),就是那個(gè)進(jìn)程出現(xiàn)了問(wèn)題,OS向目標(biāo)進(jìn)程發(fā)送8號(hào)信息,目標(biāo)進(jìn)程收到8號(hào)信號(hào),后序處理就會(huì)終止自己了。

那為什么一直發(fā)信息呢?
收到信號(hào),不一定會(huì)引起進(jìn)程退出,沒(méi)有退出,進(jìn)程可能還會(huì)被CPU調(diào)度。
CPU內(nèi)部的寄存器只有一份,但是寄存器種中的內(nèi)容,屬于當(dāng)前進(jìn)程的上下文,CPU內(nèi)部狀態(tài)寄存器溢出標(biāo)記位由0->1,你是沒(méi)有能力或者動(dòng)作去修改這個(gè)問(wèn)題的。
當(dāng)進(jìn)程被切換的時(shí)候,就有無(wú)數(shù)次狀態(tài)寄存器被保存和恢復(fù)的過(guò)程,所以每一次恢復(fù)的時(shí)候,就讓OS識(shí)別到了CPU內(nèi)部的狀態(tài)寄存器中標(biāo)記位是1,每一次都會(huì)發(fā)8號(hào)信號(hào)。

再看一種由硬件異常產(chǎn)生的信號(hào)。

int main()
{
    signal(SIGFPE,handler);
    int cnt=0; 
    while(true)
    {
        printf("cnt:%d,pid:%d\n",cnt++,getpid());
        int* ptr=NULL;
        *ptr=10;
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

為什么野指針就奔潰了?
因?yàn)镺S會(huì)給當(dāng)前進(jìn)程發(fā)送指定的11號(hào)信號(hào)。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

證明一下。

void handler(int signo)
{
    cout<<"進(jìn)程捕捉到了一個(gè)信號(hào),信號(hào)編號(hào)是:"<<signo<<endl;
}


int main()
{
    signal(11,handler);
    int cnt=0; 
    while(true)
    {
        printf("cnt:%d,pid:%d\n",cnt++,getpid());
        int* ptr=NULL;
        *ptr=10;
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

OS怎么知道我野指針了呢?

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
根據(jù)我們以前學(xué)的知識(shí),虛擬地址—>物理地址的轉(zhuǎn)換,要經(jīng)過(guò)頁(yè)表。今天我要告訴你除了頁(yè)表還有一種硬件MMU。MMU是內(nèi)存管理單元。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
MMU其實(shí)是通過(guò)讀取頁(yè)表中的內(nèi)容,在內(nèi)部形成對(duì)應(yīng)的物理地址,然后再去訪問(wèn)我們對(duì)應(yīng)的物理地址。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
當(dāng)我們ptr解引用,訪問(wèn)的是0號(hào)地址。經(jīng)過(guò)頁(yè)表映射,發(fā)現(xiàn)在映射的時(shí)候,當(dāng)前進(jìn)程是不允許去訪問(wèn)對(duì)應(yīng)的0號(hào)地址的。不允許訪問(wèn)當(dāng)然可以攔截不讓你訪問(wèn)。但更重要的是,你為什么會(huì)訪問(wèn),所以O(shè)S覺(jué)得你犯錯(cuò)了就應(yīng)該付出相應(yīng)的代價(jià),所以MMU這個(gè)硬件因?yàn)閷?duì)應(yīng)的越界訪問(wèn)(野指針訪問(wèn))發(fā)送異常。OS知道當(dāng)前硬件發(fā)生異常,所以O(shè)S將異常轉(zhuǎn)換成11號(hào)信號(hào)發(fā)送給目標(biāo)進(jìn)程。

2.4軟件條件

在管道我們說(shuō)過(guò)匿名管道的一個(gè)場(chǎng)景,讀端關(guān)閉,寫(xiě)端一直寫(xiě)沒(méi)有任何意義,OS會(huì)給當(dāng)前寫(xiě)進(jìn)程發(fā)送SIGPIPE信號(hào),然后進(jìn)程終止了。

所謂的進(jìn)程,OS,管道,尤其是管道和這一整套OS發(fā)信號(hào)的原因和OS發(fā)信號(hào)的過(guò)程,和硬件都沒(méi)有關(guān)系。而是僅僅因?yàn)樽x端關(guān)閉了這一軟件條件所觸發(fā)的OS發(fā)送信號(hào)給目標(biāo)進(jìn)程,這種場(chǎng)景我們就稱(chēng)之為軟件條件會(huì)觸發(fā)信號(hào)。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

下面我們要說(shuō)的是一種定時(shí)器軟件條件。給當(dāng)前進(jìn)程設(shè)定鬧鐘,alarm()

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
設(shè)置一個(gè)時(shí)鐘時(shí)刻發(fā)送信號(hào)。

seconds:多少秒之后發(fā)送信號(hào)
返回值是0或者是以前設(shè)定的鬧鐘時(shí)間還余下的秒數(shù)

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
發(fā)送的是SIGALRM(14)信號(hào)。

int main()
{
	//這個(gè)鬧鐘是給現(xiàn)在設(shè)的還是給未來(lái)設(shè)的?
	//是不是我調(diào)用了alarm,我的進(jìn)程會(huì)立馬收到對(duì)應(yīng)的鬧鐘呢?
	//答案:并不是。這是給未來(lái)設(shè)置的鬧鐘。是1秒之后向我這個(gè)進(jìn)程發(fā)信號(hào)。
    alarm(1);
    int cnt=0;
    while(true)
    {
        printf("cnt: %d\n",cnt++);
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

根據(jù)運(yùn)行結(jié)果,請(qǐng)問(wèn)我們這段代碼有什么用呢?

其實(shí)這是統(tǒng)計(jì)1S左右,我們計(jì)算機(jī)能夠?qū)?shù)據(jù)累計(jì)多次次。

修改一下代碼再看一下效果。

int cnt=0;

void catchSig(int signo)
{
    cout<<"進(jìn)程捕捉到了一個(gè)信號(hào),信號(hào)編號(hào)是:"<<signo<<" cnt :"<<cnt<<endl;
}

int main()
{
    signal(SIGALRM,catchSig);
    alarm(1);
    while(true)
    {
        cnt++;
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
次數(shù)多了很多次,這是因?yàn)閜rintf會(huì)訪問(wèn)外設(shè),而訪問(wèn)外設(shè)比較慢。
還有就是這個(gè)鬧鐘是一次性鬧鐘,響了之后就不響了。

如果想響多次,要重新在設(shè)定鬧鐘。

void catchSig(int signo)
{
    cout<<"進(jìn)程捕捉到了一個(gè)信號(hào),信號(hào)編號(hào)是:"<<signo<<" cnt :"<<cnt<<endl;
    alarm(1);
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

alarm(0),取消鬧鐘,并且返回鬧鐘剩下多少時(shí)間。

int main(int argc,char* argv[])
{
    signal(SIGALRM,catchSig);
    alarm(5);
    while(true)
    {
        cnt++;
        if(cnt == 3)
        {
        	int n=alarm(0);
        	cout<<n<<endl;
        }
        sleep(1);
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

為什么設(shè)鬧鐘就是軟件條件了呢?
"鬧鐘"其實(shí)就是用軟件條件實(shí)現(xiàn)的。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

2.5總結(jié)

1.上面所說(shuō)的所有信號(hào)產(chǎn)生,最終都要有OS來(lái)進(jìn)行執(zhí)行,為什么?

OS是進(jìn)程的管理者

  1. 信號(hào)的處理是否是立即處理的?

在合適的時(shí)候(什么合適的時(shí)候,下面說(shuō))。

3.信號(hào)如果不是被立即處理,那么信號(hào)是否需要暫時(shí)被進(jìn)程記錄下來(lái)?記錄在哪里最合適呢?
4.一個(gè)進(jìn)程在沒(méi)有收到信號(hào)的時(shí)候,能否能知道,自己應(yīng)該對(duì)合法信號(hào)作何處理呢?
5.如何理解OS向進(jìn)程發(fā)送信號(hào)?能否描述一下完整的發(fā)送處理過(guò)程?

上面的問(wèn)題,我們都可以從接下來(lái)信號(hào)的學(xué)習(xí)中得到答案。

信號(hào)產(chǎn)生這里還有最后一個(gè)問(wèn)題。

man 7 signal  //信號(hào)手冊(cè)

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
Stop暫停進(jìn)程,Cont繼續(xù)進(jìn)程,Ign忽略進(jìn)程(這個(gè)信號(hào)說(shuō)完最后面解釋)這些都沒(méi)有問(wèn)題。
Term,Core都是終止進(jìn)程,有什么區(qū)別?
其實(shí)這有關(guān)于,進(jìn)程退出時(shí),核心轉(zhuǎn)儲(chǔ)問(wèn)題。

看下面一段代碼

int main()
{
    //核心轉(zhuǎn)儲(chǔ)
    while(true)
    {
        int a[10];
        a[100]=10;
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

int main()
{
    //核心轉(zhuǎn)儲(chǔ)
    while(true)
    {
        int a[10];
        a[1000]=10;
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
數(shù)組明明都越界了啊,怎么進(jìn)程沒(méi)有奔潰報(bào)錯(cuò)?
其實(shí)在C的時(shí)候就說(shuō)過(guò),數(shù)組越界不一定會(huì)報(bào)錯(cuò),因?yàn)閷?duì)數(shù)組的檢查是隨機(jī)的。這是我們?cè)谡Z(yǔ)言層面的理解。

int main()
{
    //核心轉(zhuǎn)儲(chǔ)
    while(true)
    {
        int a[10];
        a[10000]=10;
    }
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
那這次怎么就檢測(cè)出來(lái)了。按照語(yǔ)言層面解釋可能是因?yàn)檫@次越界被檢測(cè)到了。

接下來(lái)我們從底層理解:

編譯器上編譯你的代碼時(shí),在棧上給你開(kāi)辟多大空間和編譯器是強(qiáng)相關(guān)的,你要申請(qǐng)10個(gè)int大小元素的數(shù)組,它確實(shí)給你的就是10個(gè)元素,指的是數(shù)組的元素,但是并不代表給你的代碼塊或者函數(shù)分配棧幀結(jié)構(gòu)是10個(gè)元素的大小,可能給你的會(huì)很大,所以呢,即便你越界了,但是你還是在有效棧區(qū)里,所以沒(méi)有報(bào)錯(cuò),除非你訪問(wèn)了一個(gè)完全不是你的空間。比如你現(xiàn)在訪問(wèn)的時(shí)候,訪問(wèn)的是系統(tǒng)的地址空間中或者訪問(wèn)到一個(gè)不讓你訪問(wèn)的區(qū)域,那么此時(shí)OS系統(tǒng)就能識(shí)別出來(lái)。所以O(shè)S在識(shí)別越界的問(wèn)題上有可能也死別不出來(lái),從而出現(xiàn)把數(shù)據(jù)改變了,但用戶(hù)不知情的情況。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
這個(gè)信號(hào)是11號(hào)信號(hào),段錯(cuò)誤,它的終止方式是Core。
像Trem這種結(jié)束,是正常結(jié)束,OS不會(huì)做額外操作的。而以Core這種結(jié)束,OS除了終止進(jìn)程,它還要做其他工作。

但是以Core為終止,我也沒(méi)見(jiàn)OS做什么額外工作啊, 除了給我打印出一個(gè)錯(cuò)誤描述,像Trem終止進(jìn)程不也是給我打印出一個(gè)錯(cuò)誤描述嗎。

在云服務(wù)器上,默認(rèn)如果進(jìn)程是Core退出的,我們暫時(shí)看不到明顯現(xiàn)象,如果想看到需要打開(kāi)一個(gè)選項(xiàng)。

ulimit -a  //可以看到系統(tǒng)給我們當(dāng)前資源設(shè)置的上限

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
core file size 大小為0,這是云服務(wù)器默認(rèn)關(guān)閉了core file選項(xiàng)。
想要打開(kāi),ulimit就帶上你想要設(shè)置誰(shuí),-c(選項(xiàng)),大小為多少。

ulimit -c 1024  //打開(kāi)云服務(wù)器core file選項(xiàng),默認(rèn)可以向OS中形成最大為1024個(gè)block的數(shù)據(jù)塊

然后運(yùn)行同樣的代碼
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
相比較我們之前運(yùn)行的時(shí)候,除了段錯(cuò)誤后面還跟了一個(gè)(core dumped)
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
發(fā)現(xiàn)我們當(dāng)前目錄下多了一個(gè)以core命名的文件。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
所謂的核心轉(zhuǎn)儲(chǔ):當(dāng)進(jìn)程出現(xiàn)異常的時(shí)候,我們將進(jìn)程在對(duì)應(yīng)的時(shí)刻,在內(nèi)存中的有效數(shù)據(jù)(二進(jìn)制數(shù)據(jù))轉(zhuǎn)儲(chǔ)到磁盤(pán)中。

該文件我們用vim打開(kāi)是一堆亂碼。我們是無(wú)法識(shí)別的。
那形成核心轉(zhuǎn)儲(chǔ)有什么意義呢?或者說(shuō)為什么要有核心轉(zhuǎn)儲(chǔ)?

一般進(jìn)程在運(yùn)行的時(shí)候出現(xiàn)崩潰,其實(shí)我們更想知道的是,為什么會(huì)崩潰,在哪里崩潰。所以O(shè)S為了便于我們后期做調(diào)試,會(huì)將進(jìn)程在運(yùn)行期間出現(xiàn)崩潰的代碼的相關(guān)上下文數(shù)據(jù)全部dump到磁盤(pán)中,用來(lái)進(jìn)行支持調(diào)試

如何支持呢?
linux下默認(rèn)編譯都是release不能調(diào)試,debug才能調(diào)試,因此我們編譯時(shí)帶上-g選項(xiàng)。
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
當(dāng)前自動(dòng)幫我們?cè)u(píng)判,進(jìn)程收到11號(hào)信號(hào)引起的段錯(cuò)誤,報(bào)錯(cuò)是在mysignal.cc的第37行,代碼是a[10000]=10引起的錯(cuò)誤。直接就幫我們找到了錯(cuò)誤。
這種直接快速定位到出問(wèn)題的方式,我們稱(chēng)之為事后調(diào)試。

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
像這種以2號(hào)信號(hào),Trem終止進(jìn)程,并不會(huì)在當(dāng)前目錄下形成core文件。

Trem,Core都是進(jìn)程終止,它們的區(qū)別是,以Core退出的可以被核心轉(zhuǎn)儲(chǔ)的以便于后序快遞定位問(wèn)題,以Trem退出就是正常終止進(jìn)程。

以后進(jìn)程出現(xiàn)異常退出,你可以查看是什么信號(hào)的什么行為導(dǎo)致的,如果是Core,把Core打開(kāi),再執(zhí)行一下,gdb快速定位問(wèn)題。

信號(hào)產(chǎn)生到目前為止差不多講完了,但這里可能有人會(huì)有這樣的疑問(wèn)。如果我們把所有信號(hào)都捕捉,換成自定義動(dòng)作,不讓進(jìn)程退出,那進(jìn)程是不是無(wú)法被殺死了。

void catchSig(int signo)
{
    cout<<"進(jìn)程捕捉到了一個(gè)信號(hào),信號(hào)編號(hào)是:"<<signo<<endl;
}

int main()
{
    for(int signo=1;signo<=31;++signo)
    {
        signal(signo,catchSig);
    }
    while(true) sleep(1);
    
    return 0;
}

【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
難道真的無(wú)法殺死了?
【linux】信號(hào)——信號(hào)產(chǎn)生,Linux,linux,運(yùn)維,服務(wù)器
kill -9還是可以殺死進(jìn)程,無(wú)論你怎么修改,無(wú)法對(duì)9號(hào)信號(hào)設(shè)定捕捉,即使你做了,OS也不會(huì)給你設(shè)置。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-751876.html

到了這里,關(guān)于【linux】信號(hào)——信號(hào)產(chǎn)生的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Linux本地部署1Panel服務(wù)器運(yùn)維管理面板并實(shí)現(xiàn)公網(wǎng)訪問(wèn)

    Linux本地部署1Panel服務(wù)器運(yùn)維管理面板并實(shí)現(xiàn)公網(wǎng)訪問(wèn)

    1Panel 是一個(gè)現(xiàn)代化、開(kāi)源的 Linux 服務(wù)器運(yùn)維管理面板。高效管理,通過(guò) Web 端輕松管理 Linux 服務(wù)器,包括主機(jī)監(jiān)控、文件管理、數(shù)據(jù)庫(kù)管理、容器管理等 下面我們介紹在Linux 本地安裝1Panel 并結(jié)合cpolar 內(nèi)網(wǎng)穿透工具實(shí)現(xiàn)遠(yuǎn)程訪問(wèn)1Panel 管理界面 執(zhí)行如下命令一鍵安裝 1Panel: 安

    2024年02月04日
    瀏覽(107)
  • Linux服務(wù)器常見(jiàn)運(yùn)維性能測(cè)試(1)綜合跑分unixbench、superbench

    Linux服務(wù)器常見(jiàn)運(yùn)維性能測(cè)試(1)綜合跑分unixbench、superbench

    最近需要測(cè)試一批服務(wù)器的相關(guān)硬件性能,以及在常規(guī)環(huán)境下的硬件運(yùn)行穩(wěn)定情況,需要持續(xù)拷機(jī)測(cè)試穩(wěn)定性。所以找了一些測(cè)試用例。本次測(cè)試包括在服務(wù)器的高低溫下性能記錄及壓力測(cè)試,高低電壓下性能記錄及壓力測(cè)試,常規(guī)環(huán)境下CPU滿載穩(wěn)定運(yùn)行的功率記錄。 這個(gè)系

    2024年02月04日
    瀏覽(103)
  • [1Panel]開(kāi)源,現(xiàn)代化,新一代的 Linux 服務(wù)器運(yùn)維管理面板

    [1Panel]開(kāi)源,現(xiàn)代化,新一代的 Linux 服務(wù)器運(yùn)維管理面板

    本期測(cè)評(píng)試用一下1Panel這款面板。1Panel是國(guó)內(nèi)飛致云旗下開(kāi)源產(chǎn)品。整個(gè)界面簡(jiǎn)潔清爽,后端使用GO開(kāi)發(fā),前端使用VUE的Element-Plus作為UI框架,整個(gè)面板的管理都是基于docker的,想法很先進(jìn)。官方還提供了視頻的使用教程,本期為大家按照本專(zhuān)欄的基本內(nèi)容進(jìn)行多方面的測(cè)評(píng)。

    2024年02月07日
    瀏覽(67)
  • Linux服務(wù)器常見(jiàn)運(yùn)維性能測(cè)試(3)CPU測(cè)試super_pi、sysbench

    Linux服務(wù)器常見(jiàn)運(yùn)維性能測(cè)試(3)CPU測(cè)試super_pi、sysbench

    最近需要測(cè)試一批服務(wù)器的相關(guān)硬件性能,以及在常規(guī)環(huán)境下的硬件運(yùn)行穩(wěn)定情況,需要持續(xù)拷機(jī)測(cè)試穩(wěn)定性。所以找了一些測(cè)試用例。本次測(cè)試包括在服務(wù)器的高低溫下性能記錄及壓力測(cè)試,高低電壓下性能記錄及壓力測(cè)試,常規(guī)環(huán)境下CPU滿載穩(wěn)定運(yùn)行的功率記錄。 這個(gè)系

    2024年02月02日
    瀏覽(51)
  • 華為云云耀云服務(wù)器L實(shí)例評(píng)測(cè) | Linux系統(tǒng)寶塔運(yùn)維部署H5游戲

    華為云云耀云服務(wù)器L實(shí)例評(píng)測(cè) | Linux系統(tǒng)寶塔運(yùn)維部署H5游戲

    本章節(jié)內(nèi)容,我們主要介紹華為云耀服務(wù)器L實(shí)例,從云服務(wù)的優(yōu)勢(shì)講起,然后講解華為云耀服務(wù)器L實(shí)例資源面板如何操作,如何使用寶塔運(yùn)維服務(wù),如何使用運(yùn)維工具可視化安裝nginx,最后部署一個(gè)自研的H5的小游戲(6歲的小朋友玩的很開(kāi)心??)。 前端的同學(xué)如果想把自己

    2024年02月07日
    瀏覽(26)
  • 【linux】信號(hào)——信號(hào)產(chǎn)生

    【linux】信號(hào)——信號(hào)產(chǎn)生

    自我名言 : 只有努力,才能追逐夢(mèng)想,只有努力,才不會(huì)欺騙自己。 喜歡的點(diǎn)贊,收藏,關(guān)注一下把! 首先說(shuō)明一點(diǎn)信號(hào)不是信號(hào)量。不能把這兩個(gè)東西放在一起。 那信號(hào)講什么呢? 那信號(hào)是怎么回事,這里只能這樣說(shuō), 信號(hào)是針對(duì)進(jìn)行發(fā)送某種信號(hào)到來(lái)的一種機(jī)制,讓

    2024年02月05日
    瀏覽(19)
  • Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

    Linux進(jìn)程信號(hào)【信號(hào)產(chǎn)生】

    ?個(gè)人主頁(yè): 北 海 ??所屬專(zhuān)欄: Linux學(xué)習(xí)之旅 ??操作環(huán)境: CentOS 7.6 阿里云遠(yuǎn)程服務(wù)器 在 Linux 中,進(jìn)程具有獨(dú)立性,進(jìn)程在運(yùn)行后可能 “放飛自我”,這是不利于管理的,于是需要一種約定俗成的方式來(lái)控制進(jìn)程的運(yùn)行,這就是 進(jìn)程信號(hào) ,本文將會(huì)從什么是進(jìn)程信號(hào)

    2024年02月11日
    瀏覽(18)
  • Linux進(jìn)程(一)信號(hào)-----信號(hào)產(chǎn)生

    Linux進(jìn)程(一)信號(hào)-----信號(hào)產(chǎn)生

    在? Linux ?中,進(jìn)程具有獨(dú)立性,進(jìn)程在運(yùn)行后可能 “放飛自我”,這是不利于管理的,于是需要一種約定俗成的方式來(lái)控制進(jìn)程的運(yùn)行,這就是? 進(jìn)程信號(hào) ,本文將會(huì)從什么是進(jìn)程信號(hào)開(kāi)篇,講述各種進(jìn)程信號(hào)的產(chǎn)生方式及作用。 信號(hào) 是信息傳遞的承載方式,一種信號(hào)往

    2024年02月21日
    瀏覽(16)
  • 【Linux】信號(hào)概念與信號(hào)產(chǎn)生

    【Linux】信號(hào)概念與信號(hào)產(chǎn)生

    生活中類(lèi)似信號(hào)的概念也不少,例如上課鈴聲響,就是信號(hào)的發(fā)出,我們聽(tīng)到上課鈴聲,就是接收到信號(hào),我們快速回到教室上課就是對(duì)信號(hào)做出處理。那么我們是怎么認(rèn)識(shí)這些信號(hào)的呢?那必定是有人教我們,然后我們記住了。而且我們不單單要認(rèn)識(shí)信號(hào),還要識(shí)別信號(hào),

    2024年02月19日
    瀏覽(20)
  • 【Linux】第八講:Linux進(jìn)程信號(hào)詳解(一)_ 認(rèn)識(shí)信號(hào) | 產(chǎn)生信號(hào)

    【Linux】第八講:Linux進(jìn)程信號(hào)詳解(一)_ 認(rèn)識(shí)信號(hào) | 產(chǎn)生信號(hào)

    「前言」文章是關(guān)于Linux進(jìn)程信號(hào)方面的知識(shí),本文的內(nèi)容是Linux進(jìn)程信號(hào)第一講,講解會(huì)比較細(xì),下面開(kāi)始! 「歸屬專(zhuān)欄」Linux系統(tǒng)編程 「主頁(yè)鏈接」個(gè)人主頁(yè) 「筆者」楓葉先生(fy) ?「楓葉先生有點(diǎn)文青病」「每篇一句」? 人生天地間,忽如遠(yuǎn)行客。 ——《樂(lè)府·青青陵上

    2023年04月25日
    瀏覽(24)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包