亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

一、信號發(fā)送

1、信號動(dòng)作

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

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

普通信號

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

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

實(shí)時(shí)信號

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

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

3、core dump

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

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

二、信號的保存

1、前置概念

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

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

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

2、阻塞信號

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

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

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

3、保存信號

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

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

實(shí)際上blockpending都屬于保存信號,只不過因?yàn)橛袃蓚€(gè)位圖,我們分開來說罷了

4、信號遞達(dá)

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

5、總結(jié)

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

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

信號集操作函數(shù)顧名思義就是操作信號集的函數(shù),sigset_t被稱作信號集,是操作系統(tǒng)提供的數(shù)據(jù)類型,用于描述位圖,下面就是信號集操作函數(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è)信號是否在信號集中,不在返回0,在返回1,出錯(cuò)返回-1

1、設(shè)置block位圖

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

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

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

how:指定對信號掩碼的操作方式

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

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

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

2、設(shè)置pending位圖

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

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

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

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

3、設(shè)置handler行為

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

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

#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號信號
    signal(2, handler);

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

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

    // 重復(fù)打印當(dāng)前進(jìn)程的 pending 信號集,期間向進(jìn)程發(fā)送 2號信號
    // 因?yàn)?2號信號被阻塞了,所以 2號信號會(huì)一直被保存在 pending 中
    sigset_t pset; 
    sigemptyset(&pset);// pset信號集清空
    int cnt = 0;
    //在15秒內(nèi),未接受信號前,都是一直打印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號新號,不阻塞2號
            //設(shè)置當(dāng)前信號屏蔽字為oset指向的值,也就是0
            sigprocmask(SIG_SETMASK, &oset, nullptr);
         }
    }

    return 0;
}

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

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

相關(guān)文章

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

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

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

    apache的access.log和error.log減肥

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

    linux在vim中查找和替換方式

    Linux中使用Vim編輯器查找和替換文本的方法非常直觀和強(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的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(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用戶,可能不屑于網(wǎng)上免費(fèi)Linux Web一鍵包、管理面板的安裝,然后自己編譯或者自由的一套環(huán)境安裝配置環(huán)境。但是,對于大部分用戶而言,麥子個(gè)人建議還是選擇較為成熟的WEB一鍵包或者面板安裝環(huán)境
    2017-02-02
  • cloudera manager 設(shè)置開機(jī)自啟的方法

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

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

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

    這篇文章主要介紹了Apache?Pulsar集群搭建過程,搭建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的幾種方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08

最新評論