文章目錄
- 1. 信號的捕捉流程
- 1.1 引導
- 1.2 捕捉流程
- 2. 信號的阻塞
- 3. volatile
1. 信號的捕捉流程
1.1 引導
1.信號的注冊,是不是和作業系統維護的行程的PCB有關系呀?
????????struct task_struct ==> sigset_t signal
??結論:信號的注冊是在作業系統和PCB打交道的,,注冊是在行程的PCB當中,
1.2 捕捉流程
問題: 信號什么時候進行處理?
??信號的處理是在內核態完成的

??1.從內核態切換回用戶態的時候,一定會呼叫do_signal函式來處理行程收到的信號,sig位圖當中有信號注冊,就執行信號注銷的邏輯,sig位圖當中沒有信號注冊,則直接回傳用戶態
??2.處理信號(信號注銷)
????(1)默認處理方式(直接在作業系統內核的代碼當中就完成了)
????(2)忽略處理方式(直接在作業系統內核的代碼當中就完成了)
????(3)自定義處理方式(呼叫程式員自己寫的函式)
??do_signal函式直接去用戶態找sigcallback函式,執行完通過sigreturn函式,切換回內核態,然后再呼叫一次do_signal函式,判斷如果沒有信號來,通過sys_sigreturn函式回傳到用戶態,
??3.流程
????1.在用戶執行程式員自己定義的函式
????2.呼叫sigreturn函式再次回到作業系統內核
????3.再次呼叫do_signal函式判斷是否有信號注冊
????4.呼叫sys_sigreturn函式回到用戶態繼續去執行代碼
問題: 什么時候進入到作業系統內核?
??1.呼叫系統呼叫函式的時候
??2.呼叫C庫函式的時候,因為C庫函式的內部也是呼叫了系統呼叫函式
??3.記憶體訪問越界,訪問空指標
2. 信號的阻塞
??1.信號的阻塞不會影響信號的注冊
??2.內核的代碼
struct task_struct
{
...
sigset_t blocked;
...
};
??blocked位圖,作用是阻塞某一個信號的處理,也就是意味著,執行流進入到內核之后,呼叫do_signal函式判斷是否有信號需要處理的時候,發現某一個信號注冊了,同時也是需要判斷block位圖當中該信號對應的bite位是否為1,如果不為1,則暫時不處理該信號(暫時不信號注銷),如果為0,則進行處理,
??3.介面

??how:想讓sigprocmask函式做什么
????SIG_BLOCK:設定某個信號為阻塞狀態
????SIG_UNBLOCK:設定信號為非阻塞狀態
????SIG_SETMASK:設定新的block位圖
??set:使用set去設定block位圖
????SIG_BLOCK:設定某個信號為阻塞狀態
??block(new)= block(old)| set
??eg:block(old): 0101 0000
????set: 0000 1000
????> 0101 1000
??SIG_UNBLOCK:設定信號為非阻塞狀態
??block(new)= block(old)&(~set)
??eg:block(old):0101 0000
????&(~set):1011 1111
????> 0001 0000
??SIG_SETMASK: 設定新的block位圖
????block(new)= set
例外:
??信號的阻塞不會將9號信號阻塞掉,也不會阻塞19號信號
問題: 驗證非可靠信號的注冊,驗證可靠信號的注冊
??結論:非可靠信號注冊一次只添加一個sigqueue結點,可靠信號注冊每添加一次,增加一個sigqueue結點
3. volatile
??作用:使變數保證記憶體可見,通俗的講cpu在資料計算的時候,為了快,對已經從記憶體當中拿回來的資料不會再從記憶體獲取,而是直接從暫存器當中獲取,加上volatile之后變數的來源一定從記憶體獲取,
??記憶體–>快取–>暫存器–>cpu
#include <stdio.h>
#include <signal.h>
volatile int g_val = 1;
void sigcallback(int sig)
{
g_val = 0;
printf("sig: %d\n", sig);
}
int main()
{
signal(2, sigcallback);
while(g_val)
{}
return 0;
}
??上述這段代碼執行時,g_val是一個全域變數,它的值為1,因此程式執行到while的時候是死回圈,當我們通過計算機發送一個2號信號ctrl+c,執行回呼函式,將全域變數g_val的值置為0,為了驗證執行過回呼函式,列印sig,回呼函式執行結束,while回圈就結束了,
??-O0,-O1,-O2,-O3:優化級別是由高低到高的,使用g_val的時候一定要從記憶體獲取,不要從暫存器獲取,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/281011.html
標籤:其他
上一篇:C++---繼承
下一篇:C++ this指標和空指標
