欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Linux進(jìn)程信號(hào)的發(fā)送和保存方法

 更新時(shí)間:2025年04月01日 10:36:15   作者:s_little_monster_  
從信號(hào)產(chǎn)生到信號(hào)保存,中間經(jīng)歷了很多,當(dāng)操作系統(tǒng)準(zhǔn)備對(duì)信號(hào)進(jìn)行處理時(shí),還需要判斷時(shí)機(jī)是否 “合適”,在絕大多數(shù)情況下,只有在 “合適” 的時(shí)機(jī)才能處理信號(hào),即調(diào)用信號(hào)的執(zhí)行動(dòng)作,本文將給大家介紹Linux進(jìn)程信號(hào)的發(fā)送和保存方法,需要的朋友可以參考下

一、信號(hào)發(fā)送

1、信號(hào)動(dòng)作

通過(guò)指令man -7 signal查看信號(hào)的手冊(cè),然后往下翻翻可以看到普通信號(hào)發(fā)出后對(duì)應(yīng)的操作,以及它們的信號(hào)編號(hào),和詳細(xì)描述信息

2、信號(hào)發(fā)送的本質(zhì)

普通信號(hào)

信號(hào)發(fā)送的本質(zhì)實(shí)際上是寫(xiě)信號(hào),把信號(hào)寫(xiě)到進(jìn)程PCB結(jié)構(gòu)體對(duì)應(yīng)的位圖上去,在進(jìn)程的PCB中有這么一個(gè)位圖(是pending位圖,下面會(huì)說(shuō))正好對(duì)應(yīng)著我們從1 ~ 31的普通信號(hào)編號(hào),收到哪個(gè)信號(hào)就將哪一位對(duì)應(yīng)的比特位置為1,表示收到信號(hào),然后PCB再做對(duì)應(yīng)的工作

值得注意的是,如果連續(xù)發(fā)普通信號(hào),那么進(jìn)程只會(huì)處理最后一次的信號(hào),每次寫(xiě)都是覆蓋寫(xiě)的

實(shí)時(shí)信號(hào)

我們前面說(shuō)過(guò)信號(hào)分為31個(gè)普通信號(hào)和31個(gè)實(shí)時(shí)信號(hào),實(shí)時(shí)信號(hào)的作用類(lèi)似于我們嵌入式RTOS實(shí)時(shí)運(yùn)轉(zhuǎn)場(chǎng)景,要保持實(shí)時(shí)性,實(shí)時(shí)信號(hào)發(fā)送的本質(zhì)類(lèi)似于普通信號(hào),不過(guò)此時(shí)我們保存信號(hào)的載體不再是一個(gè)位圖,而是一個(gè)結(jié)構(gòu)體,它們被組織在信號(hào)隊(duì)列當(dāng)中,誰(shuí)先發(fā)送誰(shuí)就先入隊(duì),隊(duì)列遵循先入先出的規(guī)則,所以先發(fā)送也代表著先被處理

值得注意的是,如果連續(xù)發(fā)實(shí)時(shí)信號(hào),那么進(jìn)程會(huì)將隊(duì)列中的信號(hào)一個(gè)個(gè)全部處理

3、core dump

當(dāng)程序在運(yùn)行過(guò)程中發(fā)生崩潰(如段錯(cuò)誤、除零錯(cuò)誤等),Core dump 會(huì)記錄下程序崩潰瞬間的內(nèi)存狀態(tài),包括寄存器的值、調(diào)用棧信息、全局變量和局部變量的值等,開(kāi)發(fā)人員可以使用調(diào)試工具(如 GDB)加載 Core dump 文件,通過(guò)分析這些信息,準(zhǔn)確地找到程序崩潰的位置和原因

我們可以通過(guò)ulimit -c 10240將core文件的大小限制修改為10240字節(jié),出現(xiàn)錯(cuò)誤的時(shí)候core文件可能瞬間會(huì)被打滿(mǎn)的,所以我們?cè)品?wù)器上一般默認(rèn)core文件的大小限制為0,我們要是用的話(huà)再修改它的大小限制即可
形成的文件叫做core.pid,pid就是出錯(cuò)進(jìn)程的pid,假設(shè)test進(jìn)程出現(xiàn)錯(cuò)誤,12314是它的pid,我們可以通過(guò)在gdb模式下輸入gdb test core.12314打印錯(cuò)誤信息和原因

二、信號(hào)的保存

1、前置概念

實(shí)際執(zhí)行信號(hào)的處理動(dòng)作稱(chēng)為信號(hào)遞達(dá)

信號(hào)從產(chǎn)生到遞達(dá)之間的狀態(tài),稱(chēng)為信號(hào)未決

被阻塞的信號(hào)產(chǎn)生是將保持在未決狀態(tài),直到進(jìn)程解除對(duì)此信號(hào)的阻塞,才執(zhí)行遞達(dá)的動(dòng)作

2、阻塞信號(hào)

信號(hào)被阻塞就是將信號(hào)阻塞在信號(hào)未決狀態(tài),具體實(shí)現(xiàn)阻塞功能的,是一個(gè)位圖block

block是一個(gè)位圖,共31位,對(duì)應(yīng)1 ~ 31號(hào)信號(hào),當(dāng)對(duì)應(yīng)比特位為1時(shí),表示該編號(hào)信號(hào)被阻塞,為0則表示不阻塞

如果信號(hào)被阻塞則進(jìn)入阻塞態(tài),若沒(méi)有被阻塞那么信號(hào)進(jìn)入未決狀態(tài)

3、保存信號(hào)

未決狀態(tài)的作用就是保存信號(hào),它保存信號(hào)的方式也是通過(guò)位圖pending

pending也是一個(gè)位圖,與block一致,對(duì)應(yīng)的下標(biāo)和信號(hào)編號(hào)也是一一對(duì)應(yīng),當(dāng)對(duì)應(yīng)比特位為1時(shí),表示該編號(hào)信號(hào)處于未決狀態(tài),為0則信號(hào)遞達(dá)

實(shí)際上blockpending都屬于保存信號(hào),只不過(guò)因?yàn)橛袃蓚€(gè)位圖,我們分開(kāi)來(lái)說(shuō)罷了

4、信號(hào)遞達(dá)

信號(hào)遞達(dá)后的信號(hào),會(huì)執(zhí)行相對(duì)應(yīng)的行為,有SIG_DFL:默認(rèn)處理動(dòng)作,SIG_IGN:忽略,和自定義處理sighandler,這在前面提到過(guò)

5、總結(jié)

一個(gè)信號(hào),首先要經(jīng)過(guò)block,block為0來(lái)到pending,pending為0來(lái)到handler執(zhí)行動(dòng)作,其中,9號(hào)和19號(hào)新號(hào)還是特例,它們是不能被阻塞和保存的,這兩個(gè)信號(hào)一旦發(fā)出就是直接handler,其實(shí)也不用handler了,它們對(duì)應(yīng)的不可能為忽略和信號(hào)捕捉后的自定義函數(shù),只能為默認(rèn)動(dòng)作終止和暫停

三、信號(hào)集操作函數(shù)

信號(hào)集操作函數(shù)顧名思義就是操作信號(hào)集的函數(shù),sigset_t被稱(chēng)作信號(hào)集,是操作系統(tǒng)提供的數(shù)據(jù)類(lèi)型,用于描述位圖,下面就是信號(hào)集操作函數(shù)

#include <signal.h>

int sigemptyset(sigset_t *set); 
// 將位圖全部設(shè)置為 0

int sigfillset(sigset_t *set); 
// 將位圖全部都設(shè)置為 1

int sigaddset (sigset_t *set, int signo); 
// 將位圖中的某一位設(shè)置為 1

int sigdelset(sigset_t *set, int signo); 
// 將位圖中的某一位設(shè)置為 0

int sigismember(const sigset_t *set, int signo); 
// 判斷一個(gè)信號(hào)是否在信號(hào)集中,不在返回0,在返回1,出錯(cuò)返回-1

1、設(shè)置block位圖

sigprocmask是一個(gè)在信號(hào)處理中非常重要的系統(tǒng)調(diào)用,主要用于檢查、修改進(jìn)程的信號(hào)掩碼(阻塞信號(hào)集)

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

返回值:若成功則為0,若出錯(cuò)則為-1

how:指定對(duì)信號(hào)掩碼的操作方式

how 取值含義示例說(shuō)明
SIG_BLOCK將 set 所指向的信號(hào)集中的信號(hào)添加到當(dāng)前的信號(hào)掩碼中,即阻塞 set 中的信號(hào)若當(dāng)前信號(hào)掩碼已阻塞 SIGINT,使用 SIG_BLOCK 并傳入包含 SIGTERM 的信號(hào)集,SIGTERM 也會(huì)被阻塞
SIG_UNBLOCK從當(dāng)前的信號(hào)掩碼中移除 set 所指向的信號(hào)集中的信號(hào),即解除對(duì) set 中信號(hào)的阻塞若當(dāng)前信號(hào)掩碼阻塞了 SIGINT 和 SIGTERM,使用 SIG_UNBLOCK 并傳入包含 SIGINT 的信號(hào)集,SIGINT 信號(hào)的阻塞狀態(tài)將被解除
SIG_SETMASK將當(dāng)前的信號(hào)掩碼設(shè)置為 set 所指向的信號(hào)集,覆蓋原來(lái)的信號(hào)掩碼若原信號(hào)掩碼阻塞 SIGINT,使用 SIG_SETMASK 并傳入包含 SIGTERM 的信號(hào)集,信號(hào)掩碼將只阻塞 SIGTERM

set:指向一個(gè)sigset_t類(lèi)型的信號(hào)集,該信號(hào)集包含了要操作的信號(hào),如果how的值為SIG_BLOCKSIG_UNBLOCK,則set表示要添加或移除的信號(hào)集;如果how的值為SIG_SETMASK,則set表示要設(shè)置的新的信號(hào)掩碼,若該參數(shù)為NULL,則不改變當(dāng)前的信號(hào)掩碼,僅獲取當(dāng)前信號(hào)掩碼,此時(shí)oset不能為NULL

oset:指向一個(gè)sigset_t類(lèi)型的信號(hào)集,用于存儲(chǔ)調(diào)用sigprocmask之前的信號(hào)掩碼,如果不需要保存舊的信號(hào)掩碼,可以將該參數(shù)設(shè)置為NULL

2、設(shè)置pending位圖

sigpending是一個(gè)用于獲取進(jìn)程當(dāng)前未決信號(hào)集的系統(tǒng)調(diào)用

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

返回值:成功返回0,失敗返回-1

setsigpending函數(shù)會(huì)將當(dāng)前進(jìn)程中處于未決狀態(tài)(即已發(fā)送但由于被阻塞而尚未被處理)的信號(hào)集存儲(chǔ)到set所指向的sigset_t對(duì)象中

3、設(shè)置handler行為

三種情況,默認(rèn),忽略和自定義,自定義那當(dāng)然是signal函數(shù),前面有,不再贅述

四、驗(yàn)證信號(hào)保存行為

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

using namespace std;
//打印出位圖
void PrintPending(const sigset_t &pset)
{
    for(int i = 31; i >= 1; i--)
    {
        cout << sigismember(&pset, i);
    }
    cout << endl;
}

void handler(int signum)
{
    cout << "catch a signum: " << signum << endl;
}

int main()
{
	//自定義捕捉2號(hào)信號(hào)
    signal(2, handler);

    sigset_t bset, oset; 
    sigemptyset(&bset); // bset信號(hào)集清空
    sigemptyset(&oset); // oset信號(hào)集清空
    sigaddset(&bset, 2); // 將bset的第2位設(shè)為1,也就是給bset中添加上2號(hào)信號(hào)

    // 調(diào)用系統(tǒng)調(diào)用,將數(shù)據(jù)設(shè)置進(jìn)內(nèi)核,設(shè)置block,此時(shí)2號(hào)信號(hào)被阻塞
    sigprocmask(SIG_SETMASK, &bset, &oset);

    // 重復(fù)打印當(dāng)前進(jìn)程的 pending 信號(hào)集,期間向進(jìn)程發(fā)送 2號(hào)信號(hào)
    // 因?yàn)?2號(hào)信號(hào)被阻塞了,所以 2號(hào)信號(hào)會(huì)一直被保存在 pending 中
    sigset_t pset; 
    sigemptyset(&pset);// pset信號(hào)集清空
    int cnt = 0;
    //在15秒內(nèi),未接受信號(hào)前,都是一直打印0
    while(true)
    {
         int n = sigpending(&pset);
         if(n < 0) continue;
         //打印位圖
         PrintPending(pset);
         sleep(1);
         cnt++;
         if(cnt == 15)
         {
            cout << "unblock 2 signo" << endl;
            // 打印15次位圖后解除阻塞
            sigdelset(&bset, 2);//將bset的第2位設(shè)置為0,也就是給bset去除2號(hào)新號(hào),不阻塞2號(hào)
            //設(shè)置當(dāng)前信號(hào)屏蔽字為oset指向的值,也就是0
            sigprocmask(SIG_SETMASK, &oset, nullptr);
         }
    }

    return 0;
}

查看一下效果,在3秒后,我按下ctrl+c,然后我們的捕捉信號(hào)函數(shù)沒(méi)有工作,說(shuō)明信號(hào)被阻塞了,然后15秒后我們自動(dòng)放開(kāi)阻塞,瞬間打印出handler函數(shù)定義要打印的信息,再按ctrl+c就正常進(jìn)行handler行為了

到此這篇關(guān)于Linux進(jìn)程信號(hào)的發(fā)送和保存方法的文章就介紹到這了,更多相關(guān)Linux進(jìn)程信號(hào)發(fā)送和保存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • apache time_wait連接數(shù)太多問(wèn)題解決方法

    apache time_wait連接數(shù)太多問(wèn)題解決方法

    這篇文章主要介紹了apache time_wait連接數(shù)太多問(wèn)題解決方法,本文使用調(diào)整內(nèi)核參數(shù)來(lái)解決,需要的朋友可以參考下
    2014-11-11
  • apache的access.log和error.log減肥

    apache的access.log和error.log減肥

    我的服務(wù)器是用apache搭建的,里面的access.log和error.log這兩個(gè)文件要經(jīng)常上去看,和清理,如果時(shí)間忙,忘記看和清理了,過(guò)不了多久,這兩個(gè)文件就膨脹的非常的大,打都打不開(kāi)了。
    2009-09-09
  • linux在vim中查找和替換方式

    linux在vim中查找和替換方式

    Linux中使用Vim編輯器查找和替換文本的方法非常直觀(guān)和強(qiáng)大,Vim支持多種查找和替換的命令,包括向前查找、向后查找、查找并替換文本、替換所有匹配項(xiàng)、確認(rèn)每個(gè)替換和在多個(gè)文件中進(jìn)行替換等
    2025-02-02
  • CentOS服務(wù)器apache綁定多個(gè)域名的方法

    CentOS服務(wù)器apache綁定多個(gè)域名的方法

    這篇文章主要為大家詳細(xì)介紹了CentOS服務(wù)器apache綁定多個(gè)域名的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • windows10 更新Ubuntu20.04 LTS的方法步驟

    windows10 更新Ubuntu20.04 LTS的方法步驟

    這篇文章主要介紹了windows10 更新Ubuntu20.04 LTS的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Linux VPS配置Web網(wǎng)站環(huán)境一鍵包(LNMP/LAMP/LNMPA)

    Linux VPS配置Web網(wǎng)站環(huán)境一鍵包(LNMP/LAMP/LNMPA)

    如果我們是資深Linux用戶(hù),可能不屑于網(wǎng)上免費(fèi)Linux Web一鍵包、管理面板的安裝,然后自己編譯或者自由的一套環(huán)境安裝配置環(huán)境。但是,對(duì)于大部分用戶(hù)而言,麥子個(gè)人建議還是選擇較為成熟的WEB一鍵包或者面板安裝環(huán)境
    2017-02-02
  • cloudera manager 設(shè)置開(kāi)機(jī)自啟的方法

    cloudera manager 設(shè)置開(kāi)機(jī)自啟的方法

    下面小編就為大家?guī)?lái)一篇cloudera manager 設(shè)置開(kāi)機(jī)自啟的方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-01-01
  • Apache?Pulsar集群搭建部署詳細(xì)過(guò)程

    Apache?Pulsar集群搭建部署詳細(xì)過(guò)程

    這篇文章主要介紹了Apache?Pulsar集群搭建過(guò)程,搭建Pulsar集群至少需要3個(gè)組件:ZooKeeper集群、BookKeeper集群和Broker集群,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2022-02-02
  • Xshell實(shí)現(xiàn)Windows上傳文件到Linux主機(jī)的方法

    Xshell實(shí)現(xiàn)Windows上傳文件到Linux主機(jī)的方法

    這篇文章主要介紹了Xshell實(shí)現(xiàn)Windows上傳文件到Linux主機(jī)的方法,需要的朋友可以參考下
    2017-12-12
  • 詳解ubuntu安裝CMake的幾種方式

    詳解ubuntu安裝CMake的幾種方式

    這篇文章主要介紹了詳解ubuntu安裝CMake的幾種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評(píng)論