Linux信号实践(1) --Linux信号编程概述
中斷
? ? 中斷是系統對于異步事件的響應,?進程執行代碼的過程中可以隨時被打斷,然后去執行異常處理程序;
? ? 計算機系統的中斷場景:中斷源發出中斷信號?->?CPU判斷中斷是否屏蔽屏蔽以及保護現場?->?CPU(查詢中斷向量表,?找到中斷服務程序的入口地址)執行中斷處理程序?->(處理完中斷之后)?->恢復現場,繼續執行原來的任務
?
中斷分類
硬件中斷(外部中斷)
? 外部中斷是指由外部設備通過硬件請求的方式產生的中斷,也稱為硬件中斷
軟件中斷(內部中斷)
? 內部中斷是由CPU運行程序錯誤或執行內部程序調用引起的一種中斷,也稱為軟件中斷(如:執行除0操作,?由用戶空間陷入內核空間等)。
?
信號
? 信號是UNIX/Linux系統響應某些狀況而產生的事件,進程在接收到信號時會采取相應的行動。信號一般是因為某些錯誤條件而產生的,比如內存段沖突、浮點處理器錯誤或者非法指令等;信號是在軟件層次上對中斷的一種模擬,所以通常把它稱為是軟中斷;
?
信號與中斷的相似點:
(1)采用了相同的異步通信方式;
(2)當檢測出有信號或中斷請求時,都暫停正在執行的程序而轉去執行相應的處理程序;
(3)都在處理完畢后返回到原來的斷點;
(4)對信號或中斷都可進行屏蔽。
?
信號與中斷的區別:
(1)中斷有優先級,而信號沒有優先級,所有的信號都是平等的;
(2)信號處理程序是在用戶態下運行的,而中斷處理程序是在核心態下運行;
(3)中斷響應是及時的,而信號響應通常都有較大的時間延遲。
?
常用信號
信號名稱 | 描述 |
SIGABRT(6) | 進程停止運行? |
SIGALRM | 警告鐘 |
SIGFPE | 算述運算例外(如除0) |
SIGHUP | 系統掛斷 |
SIGILL | 非法指令 |
SIGINT(2) | 終端中斷?? |
SIGKILL | 停止進程(此信號不能被忽略或捕獲) |
SIGPIPE | 向沒有讀者的管道寫入數據 |
SIGSEGV | 無效內存段訪問 |
SIGQUIT | 終端退出??? |
SIGTERM | 終止 |
SIGUSR1 | 用戶定義信號1 |
SIGUSR2 | 用戶定義信號2 |
SIGCHLD | 子進程已經停止或退出 |
SIGCONT | 如果被停止則繼續執行 |
SIGSTOP | 停止執行 |
SIGTSTP | 終端停止信號 |
SIGTOUT | 后臺進程請求進行寫操作 |
SIGTTIN | 后臺進程請求進行讀操作 |
?
進程對信號的響應?
忽略信號??
? 不采取任何操作、有兩個信號不能被忽略:SIGKILL和SIGSTOP。
? [為什么進程不能忽略SIGKILL/SIGSTOP信號。(如果應用程序可以忽略這2個信號,系統管理無法殺死、暫停進程,無法對系統進行管理。)]
捕獲并處理信號???
? 內核中斷正在執行的代碼,轉去執行先前注冊過的處理程序。
執行默認操作???
? 默認操作通常是終止進程,這取決于被發送的信號。
?
信號的默認操作:通過?man?7?signal?查看
?
信號安裝-signal
typedef void (*__sighandler_t) (int); #define SIG_ERR ((__sighandler_t) -1) #define SIG_DFL ((__sighandler_t) 0) #define SIG_IGN ((__sighandler_t) 1) __sighandler_t signal(int signum, __sighandler_t handler);參數
? signal是一個帶signum和handler兩個參數的函數,準備捕捉或屏蔽的信號由參數signum給出,接收到指定信號時將要調用的函數由handler給出
? handler這個函數必須有一個int類型的參數(即接收到的信號代碼),它本身的類型是void,?handler也可以是下面兩個特殊值:
SIG_IGN 屏蔽該信號
SIG_DFL 恢復默認行為
//示例1 void handler(int sigNum) {cout << "recv a signal = " << sigNum << endl; }int main(int argc, char *argv[]) {signal(SIGINT, handler);while (true)sleep(1); }RETURN?VALUE
?signal()?returns?the?previous?value?of?the?signal?handler,?or?SIG_ERR?on?error.???
?In??the?event?of?an?error,?errno?is?set?to?indicate?the?cause.
int main(int argc, char *argv[]) {sighandler_t oldHandler = signal(SIGINT, handler);if (oldHandler == SIG_ERR)err_exit("signal error");while (getchar() != '\n')sleep(1);// 等價于 signal(SIGINT, SIG_DFL)if (signal(SIGINT, oldHandler) == SIG_ERR)err_exit("signal error");while (true)sleep(1); } //實例: 捕獲所有信號, 并打印信號的信息 int main() {for (int i = 1; i < NSIG; ++i){if (signal(i, sigHandler) == SIG_ERR){cerr << "signal " << i << ": " << strsignal(i) << " set error";cerr << ", errno desc: " << strerror(errno) << endl;}}while (true)pause(); }void sigHandler(int signo) {cout << "catch a signal, signo = " << signo << ", desc: " << strsignal(signo) << endl; }總結
以上是生活随笔為你收集整理的Linux信号实践(1) --Linux信号编程概述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux IPC实践(7) --Pos
- 下一篇: [原创] JS 继承详解。欢迎拍砖