中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

平邑網(wǎng)站定制太原seo軟件

平邑網(wǎng)站定制,太原seo軟件,wordpress 域名更改,大連個(gè)人做網(wǎng)站索引 一.初始信號(hào)1.什么是信號(hào)2.前后臺(tái)進(jìn)程3.信號(hào)的種類4.信號(hào)的管理 二.信號(hào)產(chǎn)生前1.驗(yàn)證鍵盤是可以產(chǎn)生信號(hào)的2.通過系統(tǒng)調(diào)用接口發(fā)送信號(hào)3.由軟件條件產(chǎn)生信號(hào)4.硬件異常產(chǎn)生信號(hào)5.總結(jié)6.core dump 信號(hào)產(chǎn)生中1.信號(hào)在內(nèi)核中的表示2.信號(hào)集操作函數(shù) 信號(hào)產(chǎn)生后1.了解內(nèi)核態(tài)和…

索引

  • 一.初始信號(hào)
      • 1.什么是信號(hào)
      • 2.前后臺(tái)進(jìn)程
      • 3.信號(hào)的種類
      • 4.信號(hào)的管理
  • 二.信號(hào)產(chǎn)生前
      • 1.驗(yàn)證鍵盤是可以產(chǎn)生信號(hào)的
      • 2.通過系統(tǒng)調(diào)用接口發(fā)送信號(hào)
      • 3.由軟件條件產(chǎn)生信號(hào)
      • 4.硬件異常產(chǎn)生信號(hào)
      • 5.總結(jié)
      • 6.core dump
  • 信號(hào)產(chǎn)生中
      • 1.信號(hào)在內(nèi)核中的表示
      • 2.信號(hào)集操作函數(shù)
  • 信號(hào)產(chǎn)生后
      • 1.了解內(nèi)核態(tài)和用戶態(tài)
      • 2.內(nèi)存如何實(shí)現(xiàn)信號(hào)的捕捉
      • 3.sigaction

一.初始信號(hào)

1.什么是信號(hào)

生活的角度: 紅綠燈,鬧鐘,下課鈴等
1.我們是如何得知這些東西的?有人教,(能夠認(rèn)識(shí)這些場(chǎng)景下的信號(hào)以及其表示的含義)也就是能夠識(shí)別這些信號(hào)
2.我們提前知道這些信號(hào)產(chǎn)生時(shí)要做什么也就是我們已經(jīng)提前知道了信號(hào)處理的方法

從上述可以看出

即使信號(hào)沒有產(chǎn)生,我們已經(jīng)具備了處理信號(hào)的能力!

因此:信號(hào)是給進(jìn)程發(fā)送的,進(jìn)程要具備處理信號(hào)的能力

1.該能力一定是預(yù)先已經(jīng)早就有了的
2.進(jìn)程能夠識(shí)別對(duì)應(yīng)的信號(hào)
3.進(jìn)程能夠處理對(duì)應(yīng)的信號(hào)
這個(gè)能力是OS給我們提供的

對(duì)于進(jìn)程來講,即使信號(hào)還沒有產(chǎn)生,我們進(jìn)程已經(jīng)具有識(shí)別和處理這個(gè)信號(hào)的能力了

2.前后臺(tái)進(jìn)程

while (true){sleep(1);}return 0;

當(dāng)我們直接運(yùn)行上述程序時(shí),該程序會(huì)變成一個(gè)前臺(tái)進(jìn)程,此時(shí)直接ctrl+C可以直接終止,是因?yàn)?code>ctrl+C可以發(fā)送一個(gè)信號(hào)給前臺(tái)進(jìn)程,使得該進(jìn)程退出。
但當(dāng)我們將前臺(tái)進(jìn)程變成后臺(tái)進(jìn)程時(shí),其接不到類似ctrl + C的信號(hào),也就無法退出了

理解用戶按下Ctrl + C,這個(gè)鍵盤輸入產(chǎn)生一個(gè)硬件中斷,被OS獲取,解釋成信號(hào),發(fā)送給目標(biāo)前臺(tái)進(jìn)程,前臺(tái)進(jìn)程因?yàn)槭盏叫盘?hào),進(jìn)而引起進(jìn)程退出。

在這里插入圖片描述
注意:

  • 1.只有前臺(tái)進(jìn)程才能收到Ctrl+C產(chǎn)生的信號(hào),后臺(tái)進(jìn)程無法收到,一個(gè)運(yùn)行進(jìn)程的命令后面+&可以使得前臺(tái)進(jìn)程轉(zhuǎn)化成后臺(tái)進(jìn)程,轉(zhuǎn)化為后臺(tái)進(jìn)程之后shell不必等到進(jìn)程結(jié)束才可以接受新的命令,可以直接啟動(dòng)新進(jìn)程
  • 2.前臺(tái)進(jìn)程在運(yùn)行過程中用戶隨時(shí)按下ctrl+C而產(chǎn)生一個(gè)信號(hào),也就是說該進(jìn)程的用戶空間代碼執(zhí)行到任何地方都有可能受到SIGINT(就是Ctrl+C)而終止,所以信號(hào)相對(duì)于進(jìn)程的控制流程來說是異步的。

3.信號(hào)的種類

kill -l 可以顯示信號(hào)列表

在這里插入圖片描述
數(shù)字是信號(hào)編號(hào),右側(cè)是宏,二者一個(gè)意思

1-31是分時(shí)信號(hào),產(chǎn)生信號(hào)了不用立即處理
34-64是實(shí)時(shí)信號(hào),信號(hào)產(chǎn)生了就必須處理。
我們學(xué)習(xí)的是1-31的普通信號(hào)。

4.信號(hào)的管理

在這里插入圖片描述
那么進(jìn)程又是如何管理信號(hào)的呢?
是在進(jìn)程的PCB中

eg:
task_struct {
uint32_t sig;//位圖 0000 0000

}

位圖的內(nèi)容表示有沒有該信號(hào),位圖的位置表示是哪一個(gè)信號(hào),由于PCB是在內(nèi)核數(shù)據(jù)結(jié)構(gòu),所以只有OS有資格修改位圖,OS是進(jìn)程的管理者,進(jìn)程的所有屬性的獲取和設(shè)置只能又操作系統(tǒng)來設(shè)置,因此無論信號(hào)怎么產(chǎn)生,最終一定是OS幫我們進(jìn)行信號(hào)的設(shè)置

下面我將從三個(gè)部分:信號(hào)產(chǎn)生前,信號(hào)產(chǎn)生中,信號(hào)產(chǎn)生后來敘述進(jìn)程間信號(hào)

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

上述可以了解到,信號(hào)在OS中是由位圖表示的,所以信號(hào)的產(chǎn)生OS發(fā)送給進(jìn)程的時(shí)候不如說是寫入信號(hào)。

1.驗(yàn)證鍵盤是可以產(chǎn)生信號(hào)的

sighandler_t signal(int signum, sighandler_t handler); 對(duì)信號(hào)設(shè)置回調(diào)

 #include <signal.h>typedef void (*sighandler_t)(int);sighandler_t signal(int signum, sighandler_t handler);

驗(yàn)證Ctrl + C是2號(hào)信號(hào),我們先對(duì)
-定義捕捉動(dòng)作當(dāng)我們?cè)阪I盤上按Ctrl+C的時(shí)候,如果調(diào)用了我們的自定義函數(shù),驗(yàn)證成功!

void handler(int signo)
{cout << "i am a process ,我獲取了一個(gè)信號(hào): " << signo << endl;
}
int main()
{signal(SIGINT, handler);sleep(3);cout << "自定義信號(hào)捕捉函數(shù)設(shè)置完畢" << endl;while (true){cout << "我是一個(gè)正在運(yùn)行的進(jìn)程" << endl;sleep(1);}return 0;
}

signal(SIGINT, handler); 這里不是在調(diào)用handler方法,只有信號(hào)產(chǎn)生的時(shí)候,才會(huì)調(diào)用handler方法.
實(shí)驗(yàn)結(jié)果如下
在這里插入圖片描述
因此可以得出結(jié)論:Ctrl + C :本質(zhì)就是給前臺(tái)進(jìn)程發(fā)送2號(hào)信號(hào)給目標(biāo)進(jìn)程,目標(biāo)進(jìn)程默認(rèn)對(duì)2號(hào)信號(hào)的處理動(dòng)作就是終止自己,然而現(xiàn)在我們?cè)O(shè)置了用戶對(duì)信號(hào)的自定義處理動(dòng)作。

Ctrl + C 產(chǎn)生2號(hào)信號(hào)
Ctrl +\ 產(chǎn)生3號(hào)信號(hào),同樣也是終止進(jìn)程

注意:9號(hào)信號(hào)是不能設(shè)置自定義的,即使設(shè)置了,kill -9 PID 照樣也可以殺死進(jìn)程,因此9號(hào)信號(hào)也叫做管理員信號(hào)

2.通過系統(tǒng)調(diào)用接口發(fā)送信號(hào)

int kill(pid_t pid, int sig);不僅是一個(gè)命令,還是一個(gè)系統(tǒng)調(diào)用接口,表示對(duì)某個(gè)進(jìn)程發(fā)送某個(gè)信號(hào)
我自己寫一個(gè)mykill進(jìn)程,該進(jìn)程是調(diào)用了kill這個(gè)函數(shù)的,可以得出結(jié)論,代碼如下

mykill.cc

static void Usage(const string &proc)
{cerr << " Usage :\n\t" << proc << " signo pid " << endl;
}
int main(int argc, char *argv[])
{if (argc != 3){Usage(argv[0]);exit(1);}if (kill(static_cast<pid_t>(atoi(argv[2])), atoi(argv[1])) == -1){cerr << "kill :" << strerror(errno) << endl;}}

myproc.cc

while (true){sleep(1);cout << "我的PID是: " << getpid() << endl;}

在這里插入圖片描述
int raise(int sig); 給自身發(fā)信號(hào)
在這里插入圖片描述

NAMEabort - cause abnormal process terminationSYNOPSIS#include <stdlib.h>void abort(void);//直接終止進(jìn)程

abort()直接終止進(jìn)程
在這里插入圖片描述

3.由軟件條件產(chǎn)生信號(hào)

NAMEalarm - set an alarm clock for delivery of a signalSYNOPSIS#include <unistd.h>unsigned int alarm(unsigned int seconds);

調(diào)用alarm函數(shù)可以設(shè)定一個(gè)鬧鐘,也就是告訴內(nèi)核在seconds秒之后給當(dāng)前進(jìn)程發(fā)送SIGALRM信號(hào),該信號(hào)的默認(rèn)處理動(dòng)作是終止當(dāng)前進(jìn)程。函數(shù)的返回值是0或者是設(shè)定鬧鐘時(shí)間的剩余秒數(shù)。

int cnt = 0;void handler(int signo)
{cout << "i am a process ,我獲取了一個(gè)信號(hào): " << signo << endl;cout << "cnt: " << cnt << endl;
}
int main()
{signal(SIGALRM, handler);alarm(1);while (1){cnt++;}
}

在這里插入圖片描述
一秒鐘之后就會(huì)捕捉SIGALRM信號(hào)

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

下面先列舉兩個(gè)崩潰的進(jìn)程

在這里插入圖片描述
猜想一下:上述兩個(gè)進(jìn)程崩潰的本質(zhì)也是收到了某個(gè)信號(hào),驗(yàn)證一下,先將每個(gè)信號(hào)都設(shè)置自定義動(dòng)作,然后再運(yùn)行。
在這里插入圖片描述

進(jìn)程崩潰的本質(zhì):是該進(jìn)程收到了異常信號(hào),因?yàn)橛布惓?#xff0c;而導(dǎo)致OS向目標(biāo)進(jìn)程發(fā)信號(hào),進(jìn)而導(dǎo)致進(jìn)程終止的現(xiàn)象。
除0:CPU內(nèi)部,狀態(tài)寄存器,當(dāng)我們除0的時(shí)候,CPU內(nèi)的狀態(tài)寄存器會(huì)被設(shè)置成為有報(bào)錯(cuò):浮點(diǎn)數(shù)越界,CPU內(nèi)部寄存器(硬件),OS就會(huì)識(shí)別到CPU內(nèi)有報(bào)錯(cuò)->1,然后OS就會(huì)向目標(biāo)進(jìn)程發(fā)信號(hào),目標(biāo)進(jìn)程在合適的時(shí)候處理信號(hào),終止進(jìn)程
越界&野指針 我們?cè)谡Z言層面使用的地址(指針),其實(shí)都是虛擬地址->物理地址->物理內(nèi)存->讀取對(duì)應(yīng)的數(shù)據(jù)和代碼,如果虛擬地址有問題,而地址轉(zhuǎn)化的工作是由MMU(硬件)+頁表(軟件)構(gòu)成,轉(zhuǎn)化過程就會(huì)引起問題->表現(xiàn)在硬件MMU上->OS就會(huì)發(fā)現(xiàn)硬件出了問題->OS向目標(biāo)進(jìn)程發(fā)送信號(hào)->目標(biāo)進(jìn)程在合適的時(shí)候處理信號(hào)->終止進(jìn)程

由此可得出結(jié)論:我們?cè)?code>C/C++ 中除0,內(nèi)存越界等異常,在系統(tǒng)層面上是被當(dāng)成信號(hào)處理的。

5.總結(jié)

  1. 上面所說的信號(hào)的產(chǎn)生,信號(hào)的發(fā)送,最終都是要由OS來執(zhí)行的,因?yàn)镺S是進(jìn)程的管理者
  2. 信號(hào)不是被立即執(zhí)行,而是在進(jìn)程合適的時(shí)候
  3. 信號(hào)不是被立即執(zhí)行的,那么信號(hào)就會(huì)被記錄下來,記錄在進(jìn)程的PCB
  4. 一個(gè)進(jìn)程在沒有收到信號(hào)的時(shí)候,能否知道自己應(yīng)該對(duì)合法信號(hào)做何處理?能,處理方式已經(jīng)由之前的程序員寫在內(nèi)核了

6.core dump

Coredump叫做核心轉(zhuǎn)儲(chǔ),是進(jìn)程在運(yùn)行時(shí)突然崩潰的一個(gè)內(nèi)存快照。

pid_t wait(int *status);pid_t waitpid(pid_t pid, int *status, int options);

在這里插入圖片描述
wait 與waitpid都有一個(gè)status參數(shù),該參數(shù)是一個(gè)輸出型參數(shù),由OS填充,其他比特位在我之前的博客有提過,當(dāng)生成Core dump文件的時(shí)候,該標(biāo)記位會(huì)設(shè)置成1.

在這里插入圖片描述
由上可以看出,并不是所有的信號(hào)都會(huì)生成core文件的,只有程序自身內(nèi)部出了問題才會(huì)產(chǎn)生core文件。

int main()
{pid_t id = fork();if (id == 0) // 子進(jìn)程{int *p = nullptr;*p = 10000; // 野指針問題exit(1);}int status = 0;waitpid(id, &status, 0);printf("exitcode: %d,signo: %d, core dump flag: %d \n", (status >> 8) & 0xff, status * 0x7f, (status >> 7) & 0x1);
}

運(yùn)行結(jié)果
在這里插入圖片描述
可以子進(jìn)程的退出信號(hào)是11,符合野指針出錯(cuò)信號(hào),但此時(shí)的core dump標(biāo)記位還是0,為什么呢?
在這里插入圖片描述
因?yàn)槲沂蔷€上的的云服務(wù)器,廠商設(shè)置的默認(rèn)core文件個(gè)數(shù)就是0,也就是說禁止生成core文件。
在這里插入圖片描述
設(shè)置之后此時(shí)允許生成core文件。
在這里插入圖片描述
但這不是真正的用途,此時(shí)我們要生成可調(diào)試版本的程序。
在這里插入圖片描述

為什么線上的云服務(wù)器將core dump文件關(guān)閉?
因?yàn)樵品?wù)器上的產(chǎn)品一般都是release版本,但是我們生成的core文件是可調(diào)式版本的,并且如果線上的產(chǎn)品掛掉了,最重要的不是找bug而是重啟,并且一旦服務(wù)掛掉了,會(huì)直接重啟,eg一秒鐘重啟一萬次的話,每次都有core文件的話,此時(shí)磁盤占據(jù)大量的文件,磁盤被打滿了會(huì)危急到操作系統(tǒng),很危險(xiǎn)!
總結(jié)一下:

信號(hào)從產(chǎn)生到遞達(dá)之間的狀態(tài)稱為信號(hào)未決
進(jìn)程可以選擇阻塞某個(gè)信號(hào),當(dāng)進(jìn)程阻塞信號(hào)時(shí),信號(hào)無法被抵達(dá)
被阻塞的信號(hào)產(chǎn)生時(shí)將保持在未決狀態(tài),直到進(jìn)程解除對(duì)此信號(hào)的阻塞,才執(zhí)行遞達(dá)的動(dòng)作
阻塞和忽略是不同的,只要信號(hào)被阻塞那么信號(hào)即使產(chǎn)生了也不會(huì)被遞達(dá),忽略是信號(hào)處理的一個(gè)動(dòng)作

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

1.信號(hào)在內(nèi)核中的表示

信號(hào)在內(nèi)核中的表示
在這里插入圖片描述

信號(hào)在內(nèi)核中task_struct指向三張表,三張表都是用
位圖表示的。

pending:未決信號(hào)集,表示該信號(hào)是否產(chǎn)生
block:阻塞信號(hào)集,表示該信號(hào)是否被阻塞
handler:指向的是每個(gè)信號(hào)的自定義函數(shù).
以上述的SIGQUIT為例,此時(shí)該信號(hào)未產(chǎn)生,一旦產(chǎn)生該信號(hào),他的處理動(dòng)作是用戶的自定義函數(shù)sighandler,但是由于此時(shí)該信號(hào)被阻塞了,此時(shí)該信號(hào)不會(huì)抵達(dá),除非接觸對(duì)該信號(hào)的阻塞,才會(huì)抵達(dá)。

同時(shí),如果一個(gè)信號(hào)最初未被阻塞,但是在某信號(hào)抵達(dá)之前,也可以說是該信號(hào)正在處理的時(shí)候,如果繼續(xù)產(chǎn)生該信號(hào),該信號(hào)也還是只會(huì)被記錄一次,實(shí)時(shí)信號(hào)在抵達(dá)之前可以產(chǎn)生多次,這里不討論。

2.信號(hào)集操作函數(shù)

從上圖來看,每個(gè)信號(hào)只有一個(gè)bit的未決標(biāo)志,非0即1,不記錄該信號(hào)產(chǎn)生了多少次,阻塞標(biāo)志也一樣,因此,未決和阻塞標(biāo)志可以用相同的數(shù)據(jù)類型sigset_t來儲(chǔ)存。
sigset_t類型對(duì)于每種信號(hào)用一個(gè)bit表示有效無效,這個(gè)類型內(nèi)部如何儲(chǔ)存這些bit則依賴于系統(tǒng)實(shí)現(xiàn),我們不必關(guān)心,我們只要會(huì)使用如下幾個(gè)函數(shù)就可以了。

typedef __sigset_t sigset_t;
......
typedef struct{unsigned long int __val[_SIGSET_NWORDS];} __sigset_t;

根據(jù)上述源碼可以看到sigset_t的實(shí)現(xiàn)與系統(tǒng)自身有關(guān),所以我們不必關(guān)心。
int sigemptyset(sigset_t *set)
初始化set所指向的信號(hào)集,使其中所有信號(hào)的對(duì)應(yīng)bit清零,表示該信號(hào)集不包含任何有效信號(hào)
int sigfillset(sigset_t *set)
使其中所有信號(hào)的對(duì)應(yīng)bit置位,表示該信號(hào)集的有效信號(hào)包括系統(tǒng)支持的所有信號(hào)
int sigaddset(sigset_t *set, int signo)
該函數(shù)允許將一個(gè)指定的信號(hào)添加到一個(gè)自定義信號(hào)集中,也就是將該信號(hào)的標(biāo)準(zhǔn)為設(shè)為1,表示阻塞該信號(hào)。
int sigdelset(sigset_t *set,int signo)
與上述函數(shù)相反,表示解除該信號(hào)的阻塞
int sigismember(const sigset_t *set, int signo)
判斷一個(gè)信號(hào)集的有效信號(hào)中是否包含某種信號(hào),也就是檢查是否屏蔽該信號(hào),如果包含則返回1,反之0
int sigpending(sigset_t *set);
獲取當(dāng)前進(jìn)程(誰調(diào)用,獲取誰)的pending信號(hào)集,通過set參數(shù)傳出,調(diào)用成功返回0,失敗返回-1
int sigpromask(int how, const sigset_t *set, sigset_t *oset
成功返回0,失敗返回-1
若oset非空:當(dāng)前進(jìn)程的信號(hào)屏蔽字通過oset傳出
set非空:更改進(jìn)程的信號(hào)屏蔽字
how:指示如何更改
如果oset 和 set都非空,則將原來的信號(hào)屏蔽字備份到oset,然后根據(jù)set和how參數(shù)更改信號(hào)屏蔽字。 假設(shè)當(dāng)前的信號(hào)屏蔽字為mask,下述說明了how參數(shù)的可選值

SIG_BLOCKset包含了我們希望添加到當(dāng)前信號(hào)屏蔽字的信號(hào)
SIG_UNBLOCKset包含了從當(dāng)前信號(hào)屏蔽字接觸的·信號(hào)
SIG_SETMASK設(shè)置當(dāng)前信號(hào)屏蔽字為set所指向的值

V1.1版本的代碼先指示將2號(hào)信號(hào)添加到信號(hào)屏蔽字中
預(yù)期結(jié)果:初始的pending信號(hào)集都是0,當(dāng)我們向進(jìn)程發(fā)送2號(hào)信號(hào)后,pending信號(hào)集中表示2號(hào)信號(hào)的比特位變成1

#include <unistd.h>
#include <iostream>
#include <signal.h>
using namespace std;void showpending(sigset_t *pendings)
{for (int sig = 1; sig <= 31; sig++){if (sigismember(pendings, sig)){cout << "1";}else{cout << "0";}}cout << endl;
}
void handler(int signo)
{cout << "我是一個(gè)進(jìn)程,剛剛獲得了一個(gè)信號(hào): " << signo << endl;
}
int main()
{// 2.屏蔽掉2號(hào)信號(hào)sigset_t bsig, obsig;sigemptyset(&bsig);sigemptyset(&obsig);// 2.1添加2號(hào)信號(hào)到信號(hào)屏蔽字中sigaddset(&bsig, 2);// 2.2 設(shè)置用戶級(jí)的信號(hào)屏蔽字到內(nèi)核中,讓當(dāng)前進(jìn)程屏蔽2號(hào)信號(hào)sigprocmask(SIG_SETMASK, &bsig, &obsig);cout << "pid: " << getpid() << endl;signal(SIGINT, handler);// 1.不斷獲取當(dāng)前進(jìn)程的pending信號(hào)集sigset_t pendings;int cnt = 0;while (true){// 1.1清空信號(hào)集sigemptyset(&pendings);// 1.2獲取當(dāng)前進(jìn)程pending信號(hào)集(誰調(diào)用就獲取誰)if (sigpending(&pendings) == 0){// 1.3打印一下當(dāng)前進(jìn)程的pending信號(hào)集sleep(1);showpending(&pendings);cnt++;}cout << "cnt: " << cnt << endl;}return 0;
}

在這里插入圖片描述
V2.0
先將所有的信號(hào)都屏蔽,在20秒之后解除2號(hào)和3號(hào)信號(hào)
下面只貼部分更改的代碼

 sigset_t bsig, obsig;sigemptyset(&bsig);sigemptyset(&obsig);// 2.1添加1-31號(hào)信號(hào)到信號(hào)屏蔽字中for (int sig = 1; sig < 32; sig++){sigaddset(&bsig, sig);}// 2.2 設(shè)置用戶級(jí)的信號(hào)屏蔽字到內(nèi)核中,讓當(dāng)前進(jìn)程屏蔽2號(hào)信號(hào)sigprocmask(SIG_SETMASK, &bsig, &obsig);cout << "pid: " << getpid() << endl;signal(SIGINT, handler);signal(3, handler);// 1.不斷獲取當(dāng)前進(jìn)程的pending信號(hào)集sigset_t pendings;int cnt = 0;while (true){// 1.1清空信號(hào)集sigemptyset(&pendings);// 1.2獲取當(dāng)前進(jìn)程pending信號(hào)集(誰調(diào)用就獲取誰)if (sigpending(&pendings) == 0){// 1.3打印一下當(dāng)前進(jìn)程的pending信號(hào)集sleep(1);showpending(&pendings);cnt++;}if (cnt == 20){// sigprocmask(SIG_SETMASK,&obsig,nullptr); 直接用該方法可以直接解除所有信號(hào)集sigset_t sigs;sigemptyset(&sigs);sigaddset(&sigs, 2);sigaddset(&sigs, 3);sigprocmask(SIG_UNBLOCK, &sigs, nullptr);}cout << "cnt: " << cnt << endl;}

在這里插入圖片描述
根據(jù)上述結(jié)果可以看出,當(dāng)我們將信號(hào)添加到信號(hào)集之后,我們向進(jìn)程發(fā)送信號(hào)時(shí),此時(shí)代表該信號(hào)的比特位由0 --> 1
解除信號(hào)屏蔽之后,就會(huì)重新由1 --> 0
但是根據(jù)結(jié)果可以看出 9號(hào)信號(hào)即使被屏蔽了還是可以殺死進(jìn)程

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

1.了解內(nèi)核態(tài)和用戶態(tài)

上述提到信號(hào)產(chǎn)生后,OS系統(tǒng)是在什么時(shí)候處理信號(hào)呢?
實(shí)在合適的時(shí)候,那合適的時(shí)候具體是什么時(shí)候呢?
當(dāng) 當(dāng)前進(jìn)程從內(nèi)核態(tài)切換回用戶態(tài)的時(shí)候進(jìn)行信號(hào)的檢測(cè)與處理!
每個(gè)進(jìn)程都有自己的task_struct指向其虛擬地址,虛擬地址到物理地址的轉(zhuǎn)化是通過頁表實(shí)現(xiàn)的,而每個(gè)進(jìn)程對(duì)于自己的用戶空間3G是獨(dú)立的,還有一份公共的內(nèi)核頁表,如下所示.
在這里插入圖片描述
那么OS在不在內(nèi)存中被加載?答案是肯定的
無論進(jìn)程如何切換,我們都可以找到內(nèi)核的代碼和數(shù)據(jù),前提是你要有足夠的權(quán)利進(jìn)行訪問!
那么當(dāng)前的進(jìn)程如何具備權(quán)利訪問內(nèi)核頁表乃至訪問內(nèi)核數(shù)據(jù)呢?
要進(jìn)行身份切換。我們要讓OS知道此時(shí)訪問數(shù)據(jù)的是內(nèi)核還是頁表
CPU內(nèi)有對(duì)應(yīng)的狀態(tài)寄存器CR3寄存器,當(dāng)比特位是0的時(shí)候表示內(nèi)核態(tài),當(dāng)比特位是3的時(shí)候表示用戶態(tài):

用戶態(tài):只能訪問用戶級(jí)頁表
內(nèi)核態(tài):既能訪問內(nèi)核級(jí)頁表也能訪問用戶級(jí)頁表
內(nèi)核態(tài)相比于用戶態(tài)擁有更高的權(quán)限

那么一般什么時(shí)候會(huì)從用戶態(tài)切換回內(nèi)核態(tài)呢?

  • 系統(tǒng)調(diào)用的時(shí)候
  • 時(shí)間片到了進(jìn)行進(jìn)程間切換等

2.內(nèi)存如何實(shí)現(xiàn)信號(hào)的捕捉

我們必須要了解一個(gè)知識(shí):
我們的程序,會(huì)無數(shù)次直接或者間接的訪問系統(tǒng)級(jí)軟硬件資源(管理是OS),本質(zhì)上,你并沒有去操作這些軟硬件資源,而是必須通過OS–>無數(shù)次陷入內(nèi)核(1.切換身份 2.切換頁表) -->調(diào)用內(nèi)核的代碼–>完成訪問的動(dòng)作–>結(jié)果返回給用戶(1.切換身份 2.切換頁表)–>得到結(jié)果
eg:
while(1);
僅僅是這一行代碼存在從用戶態(tài)切換成內(nèi)核態(tài)嗎?
一定是有的,因?yàn)槊總€(gè)進(jìn)程都有自己的時(shí)間片,當(dāng)時(shí)間片到了,需要轉(zhuǎn)換成內(nèi)核態(tài)然后更換內(nèi)核級(jí)頁表 -->為了保護(hù)上下文,執(zhí)行調(diào)度算法–>切換新的進(jìn)程–>恢復(fù)新進(jìn)程的上下文–>再切換成用戶態(tài)–>CPU執(zhí)行的就是新進(jìn)場(chǎng)的代碼!

下面一個(gè)場(chǎng)景,當(dāng)我們調(diào)用完系統(tǒng)調(diào)用之后,返回內(nèi)核態(tài)時(shí),檢測(cè)出了錯(cuò)誤;
在這里插入圖片描述
快速記憶

在這里插入圖片描述

3.sigaction

該函數(shù)可以讀取和修改指定信號(hào)相關(guān)聯(lián)的處理動(dòng)作,成功返回0,失敗返回-1.

#include<signal.h>
int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
struct sigaction {
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};

參數(shù)解析
signum:指定信號(hào)編號(hào)
act:非空,根據(jù)指針act修改該信號(hào)的處理動(dòng)作
oldact:非空,通過其傳出該信號(hào)原來的處理動(dòng)作
act和oldact都是sigaction結(jié)構(gòu)體
上述有該結(jié)構(gòu)體的具體組成
sa_handler:表示該信號(hào)的處理動(dòng)作
當(dāng)某個(gè)信號(hào)正在被處理時(shí),內(nèi)核會(huì)自動(dòng)將當(dāng)前信號(hào)加入進(jìn)程的信號(hào)屏蔽字,當(dāng)信號(hào)處理函數(shù)返回時(shí)自動(dòng)恢復(fù)成原來的信號(hào)屏蔽字,這樣的話,當(dāng)前進(jìn)程正在被處理時(shí),如果這個(gè)信號(hào)再次產(chǎn)生,該信號(hào)會(huì)被阻塞直到當(dāng)前信號(hào)處理結(jié)束。
如果在調(diào)用信號(hào)處理函數(shù)時(shí),除了希望自動(dòng)屏蔽當(dāng)前信號(hào),還希望自動(dòng)屏蔽其他信號(hào),則用sa_mask字段說明這些需要額外屏蔽的信號(hào),當(dāng)信號(hào)處理函數(shù)返回時(shí)恢復(fù)成原來的狀態(tài)
sa_flags設(shè)為0.

實(shí)驗(yàn)一:先不給sa_mask添加信號(hào)

void handler(int signo)
{cout << "我是一個(gè)進(jìn)程,剛剛獲得了一個(gè)信號(hào): " << signo << endl;sigset_t pending;// 此時(shí)會(huì)永遠(yuǎn)在處理某個(gè)信號(hào)while (true){sigpending(&pending);for (int i = 1; i <= 31; i++){if (sigismember(&pending, i))cout << "1";elsecout << "0";}cout << endl;sleep(1);}
}
int main()
{cout << "my pid: " << getpid() << endl;struct sigaction act, oldact;act.sa_handler = handler;act.sa_flags = 0;sigemptyset(&act.sa_mask);// sigaddset(&act.sa_mask, 3);sigaction(2, &act, &oldact);while (true){cout << "main running" << endl;sleep(1);}return 0;
}

在這里插入圖片描述

實(shí)驗(yàn)二:給sa_mask添加信號(hào)

    sigaddset(&act.sa_mask, 3);

在這里插入圖片描述

http://www.risenshineclean.com/news/54071.html

相關(guān)文章:

  • cpa網(wǎng)站怎么做百度知道電腦版網(wǎng)頁入口
  • 用易語言做網(wǎng)站電商平臺(tái)排行榜前十名
  • 千圖主站的功能介紹網(wǎng)店運(yùn)營推廣
  • 免費(fèi)創(chuàng)建個(gè)人網(wǎng)站上海網(wǎng)站快速優(yōu)化排名
  • 揚(yáng)州市建設(shè)局網(wǎng)站網(wǎng)站點(diǎn)擊量 哪里查詢
  • 揭陽做網(wǎng)站的windows優(yōu)化大師收費(fèi)
  • 怎么做網(wǎng)站 高中信息技術(shù)百度搜索引擎下載免費(fèi)
  • 惠州網(wǎng)站建設(shè)推廣公司網(wǎng)絡(luò)營銷師工作內(nèi)容
  • 網(wǎng)站建站視頻口碑營銷案例2021
  • 跨境電商b2c是什么網(wǎng)站關(guān)鍵詞百度自然排名優(yōu)化
  • 天眼查公司信息查詢東莞seo優(yōu)化推廣
  • 自治區(qū)住房和城鄉(xiāng)建設(shè)部網(wǎng)站天津網(wǎng)絡(luò)推廣公司
  • 網(wǎng)站用圖片怎么交換友情鏈接
  • 自己的網(wǎng)站怎么做搜索引擎制作免費(fèi)個(gè)人網(wǎng)站
  • 網(wǎng)站建設(shè)與維護(hù)筆記優(yōu)就業(yè)seo課程學(xué)多久
  • 專業(yè)品牌設(shè)計(jì)網(wǎng)站建設(shè)seo查詢軟件
  • 怎么生成網(wǎng)站地圖5118素材網(wǎng)站
  • 網(wǎng)站開發(fā)實(shí)踐意義足球比賽直播2021歐冠決賽
  • acg的wordpress主題深圳百度推廣優(yōu)化
  • 主流網(wǎng)站模板網(wǎng)址查詢域名
  • java 企業(yè)網(wǎng)站開發(fā)搜索引擎優(yōu)化簡稱seo
  • 濟(jì)南企業(yè)建站系統(tǒng)企業(yè)員工培訓(xùn)總結(jié)
  • 電子商務(wù)網(wǎng)站實(shí)例建站模板平臺(tái)
  • 網(wǎng)站建設(shè)推廣方案網(wǎng)絡(luò)項(xiàng)目推廣平臺(tái)
  • 用wex5可以做網(wǎng)站嗎中國培訓(xùn)網(wǎng)的證書含金量
  • 怎樣做社交網(wǎng)站互聯(lián)網(wǎng)廣告推廣好做嗎
  • 可以做軟件的網(wǎng)站有哪些功能成都百度業(yè)務(wù)員電話
  • 網(wǎng)站控制面板網(wǎng)站查詢
  • 哪家公司做網(wǎng)站比較好成都百度seo公司
  • 昆明企業(yè)建網(wǎng)站多少錢萬網(wǎng)域名注冊(cè)官網(wǎng)