Linux信號之signal函數

1. 信號概述
何為信號:信號就是由用戶、系統或進程發送給目標進程的信息,以通知目標進程中某個狀態的改變或是異常。
信號產生:總體來說,其產生的條件有兩種,分別是:硬件和軟件原因,又稱為:硬中斷和軟中斷。可細分為如下幾種原因:
①系統終端Terminal中輸入特殊的字符來產生一個信號,比如按下:ctrl+\會產生SIGQUIT信號。
②系統異常。比如訪問非法內存和浮點數異常。
③系統狀態變化。如設置了alarm定時器,當該定時器到期時候會引起SIGVTALRM信號。
④調用了kill命令或是kill函數。
?

?

1. 1 系統如何處理信號
Linux系統對于接收到的信號(無論是硬中斷還是軟中斷)可以有三種處理方式:
(1)忽略此信號。SIG_IGN,該常數表示信號函數的忽略。在/usr/include/x86_64-linux-gnu/bits/signum.h
頭文件中有SIG_IGN的宏定義
?

#define SIG_IGN	((__sighandler_t) 1) /* 忽略信號  */

(2)執行系統默認的動作。SIG_DFL,該常數表示信號的默認值。對于大多數的系統來說,系統的默認動作就是終止該進程。在/usr/include/x86_64-linux-gnu/bits/signum.h
頭文件中有SIG_IGN的宏定義

#define SIG_DFL	((__sighandler_t) 0)  /* 默認動作  */

?值得注意的是:Linux下的系統默認動作一般有如下幾種:
①結束進程(Term)
②忽略信號(Ignore)
③結束進程并生成核心轉儲文件(Core),該文件用于gdb后期調試
④暫停進程(Stop)
⑤繼續進程(Continue),如果進程被掛起,則恢復進程的運行。否則,忽略該信號。
(3)捕捉該信號。這里需要用戶自定義一個函數,來對產生的信號進行捕捉,而在這個函數中可執行用戶希望對這個事件進行的處理操作。
?

2. 使用signal函數捕捉信號
在處理由系統產生的一個信號時候,首先得對產生的該信號進行安裝登記,這樣才能對其進行處理。何為安裝登記呢?其實很好理解,好比你去圖書館借閱圖書,當你找到了喜歡的書籍后,再用借書卡去機器上面掃描登記,然后就可以帶走該書籍去閱讀了。這里的圖書相當于信號,用借書卡登記和對信號進行登記同個道理,處理信號相當于你將書籍帶離圖書館閱讀。Linux上有兩個函數都可用來對信號進行登記,分別是:signal和 sigaction 。
這兩個函數的區別:
(1)signal是在系統調用的基礎上實現,是庫函數,它有兩個參數,不支持信號傳遞信息,主要用于kill -l 中的前32個非實時信號的安裝。
(2)sigaction是較新的函數,(由sys_signal和sys_rt_sigaction兩個系統調用實現 ),有3個參數。支持信號傳遞信息,主要用來和sigqueue系統調用配合使用。
?

2.1 signal詳解

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

- 函數說明:設置信號處理方式。signal()會依參數signum指定的信號編號(0~64)來設置該信號 的處理函數。當指定的信號到底時,就會跳轉到參數handler指定的函數執行。

signal函數成功時返回一個函數指針,該函數指針的類似也是sighandler_t。返回值是前一次調用signal函數時傳入的函數指針,或者是信號signum對應的默認處理函數指針SIG_DFL(如果是第一次調用的話)
signal系統調用出錯時返回SIG_ERR并設置errno。
?

#define SIG_ERR	((__sighandler_t) -1)		/* 錯誤返回  */

?代碼1

/************************************************************************** File Name: signal.cpp* Author:    The answer* Function:  Other        * Mail:      2412799512@qq.com * Created Time: 2018年05月13日 星期四 18時47分11秒************************************************************************/#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
using namespace std;void sig_handler(int signum)
{if(0 > signum){fprintf(stderr,"sig_handler param err. [%d]\n",signum);return;}if(SIGINT == signum){printf("Received signal [%s]\n",SIGINT==signum?"SIGINT":"Other");}if(SIGQUIT == signum){printf("Received signal [%s]\n",SIGQUIT==signum?"SIGQUIT":"Other");}return;
}int main(int argc,char **argv)
{printf("Wait for the signal to arrive.\n ");/*登記信息*/signal(SIGINT,sig_handler);signal(SIGQUIT,sig_handler);pause();pause();signal(SIGINT,SIG_IGN);return 0;
}

程序運行后會一直等待用戶的輸入,當在終端按下ctrl+c時候會打印^C Received signal [SIGINT]
說明捕獲到了SIGINT信號,接著程序繼續等待,當按下ctrl+\時候會打印^\Received signal [SIGQUIT]
表明捕獲到了SIGQUIT信號,如下圖所示:

在Linux的目錄/usr/include/x86_64-linux-gnu/bits/signum.h下有對所有信號的宏定義,所以可以用來和int值進行比較。

3. Linux標準信號

在Linux終端下 kill -l 可以查看所有的信號。

這里是上面64種信號的說明:

信號?? ?起源?? ?默認行為?? ?含義
SIGHUP?? ?POSIX?? ?Term?? ?控制終端掛起
SIGINT?? ?ANSI?? ?Term?? ?鍵盤輸入以終端進程(ctrl + C)
SIGQUIT?? ?POSIX?? ?Core?? ?鍵盤輸入使進程退出(Ctrl + \)
SIGILL?? ?ANSI?? ?Core?? ?非法指令
SIGTRAP?? ?POSIX?? ?Core?? ?斷點陷阱,用于調試
SIGABRT?? ?ANSI?? ?Core?? ?進程調用abort函數時生成該信號
SIGIOT?? ?4.2BSD?? ?Core?? ?和SIGABRT相同
SIGBUS?? ?4.2BSD?? ?Core?? ?總線錯誤,錯誤內存訪問
SIGFPE?? ?ANSI?? ?Core?? ?浮點異常
SIGKILL?? ?POSIX?? ?Term?? ?終止一個進程。該信號不可被捕獲或被忽略
SIGUSR1?? ?POSIX?? ?Term?? ?用戶自定義信號之一
SIGSEGV?? ?ANSI?? ?Core?? ?非法內存段使用
SIGUSR2?? ?POSIX?? ?Term?? ?用戶自定義信號二
SIGPIPE?? ?POSIX?? ?Term?? ?往讀端關閉的管道或socket鏈接中寫數據
SIGALRM?? ?POSIX?? ?Term?? ?由alarm或settimer設置的實時鬧鐘超時引起
SIGTERM?? ?ANSI?? ?Term?? ?終止進程。kill命令默認發生的信號就是SIGTERM
SIGSTKFLT?? ?Linux?? ?Term?? ?早期的Linux使用該信號來報告數學協處理器棧錯誤
SIGCLD?? ?System V?? ?Ign?? ?和SIGCHLD相同
SIGCHLD?? ?POSIX?? ?Ign?? ?子進程狀態發生變化(退出或暫停)
SIGCONT?? ?POSIX?? ?Cont?? ?啟動被暫停的進程(Ctrl+Q)。如果目標進程未處于暫停狀態,則信號被忽略
SIGSTOP?? ?POSIX?? ?Stop?? ?暫停進程(Ctrl+S)。該信號不可被捕捉或被忽略
SIGTSTP?? ?POSIX?? ?Stop?? ?掛起進程(Ctrl+Z)
SIGTTIN?? ?POSIX?? ?Stop?? ?后臺進程試圖從終端讀取輸入
SIGTTOU?? ?POSIX?? ?Stop?? ?后臺進程試圖往終端輸出內容
SIGURG?? ?4.3 BSD?? ?Ign?? ?socket連接上接收到緊急數據
SIGXCPU?? ?4.2 BSD?? ?Core?? ?進程的CPU使用時間超過其軟限制
SIGXFSZ?? ?4.2 BSD?? ?Core?? ?文件尺寸超過其軟限制
SIGVTALRM?? ?4.2 BSD?? ?Term?? ?與SIGALRM類似,不過它只統計本進程用戶空間代碼的運行時間
SIGPROF?? ?4.2 BSD?? ?Term?? ?與SIGALRM 類似,它同時統計用戶代碼和內核的運行時間
SIGWINCH?? ?4.3 BSD?? ?Ign?? ?終端窗口大小發生變化
SIGPOLL?? ?System V?? ?Term?? ?與SIGIO類似
SIGIO?? ?4.2 BSD?? ?Term?? ?IO就緒,比如socket上發生可讀、可寫事件。因為TCP服務器可觸發SIGIO的條件很多,故而SIGIO無法在TCP服務器中用。SIGIO信號可用在UDP服務器中,但也很少見
SIGPWR?? ?System V?? ?Term?? ?對于UPS的系統,當電池電量過低時,SIGPWR信號被觸發
SIGSYS?? ?POSIX?? ?Core?? ?非法系統調用
SIGUNUSED?? ??? ?Core?? ?保留,通常和SIGSYS效果相同
?

原文地址:https://blog.csdn.net/lixiaogang_theanswer/article/details/80301624

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384458.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384458.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384458.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux pause函數 詳解

int pause(void);   作用&#xff1a;使調用進程&#xff08;線程&#xff09;進入休眠狀態&#xff08;就是掛起&#xff09;&#xff1b;直到接收到信號且信號函數成功返回 pause函數才會返回   返回值&#xff1a;始終返回-1  示例代碼: #include <sys/types.h>…

Linux中wait()函數及waitpid()函數

編程過程中&#xff0c;有時需要讓一個進程等待另一個進程&#xff0c;最常見的是父進程等待自己的子進程&#xff0c;或者父進程回收自己的子進程資源包括僵尸進程。這里簡單介紹一下系統調用函數&#xff1a;wait() 函數原型是 #include <sys/types.h> #include <…

Linux下Kill函數用法

&#xff3b; KILL &#xff3d;功能描述&#xff1a; 用于向任何進程組或進程發送信號。 頭文件用法&#xff1a; 1 #include < sys / types.h > 2 3 #include < signal.h > 4 5 int kill(pid_t pid, int sig); 6 7 參數&#xff1a; pid&#xff1…

學習筆記 --- DM9000網卡原理與基地址設置

前面有文章分析了網卡也是屬于類內存總線的設備&#xff0c;類內存總線的設備有地址總線和數據總線&#xff0c;先來看下DM9000的管腳&#xff1a; 從上面可以看出DM9000的地址總線就一根&#xff0c;它不像CS8900那樣地址總線和數據總線都齊全。而這里只有一根地址線(CMD)&…

Micrium/UCOS官網賬號密碼重新改問題

https://blog.csdn.net/qq_42312125/article/details/104122502

靜態VLAN的配置

在一臺交換機上連接3臺PC機&#xff0c;然后創建兩個VLAN&#xff0c;分別為VLAN 10 和VLAN 20&#xff0c;把第一臺PC機分配給VLAN 10&#xff0c;把其他兩臺分配給VLAN 20.然后測試他們的互通情況。 在這里命令我用的都是簡化命令&#xff0c;想卡完整版命令&#xff0c;請到…

靜態路由原理

1、路由器的工作原理 路由工作簡單原理圖 1&#xff09;主機1.1要發生數據包給主機4.1.因為IP地址不在同一網段&#xff0c;所以主機會將數據包發送給本網段的網關路由器。 2&#xff09;路由器A 接收到數據包&#xff0c;先查看數據包IP首部中的目標IP地址。再查找自己的路由表…

靜態路由和默認路由

一、靜態路由的配置 下邊實驗對該拓撲圖進行配置 實驗目標&#xff1a;配置靜態路由&#xff0c;實現全網互通 1、配置路由器R1 進入接口f0/0&#xff0c;配置IP&#xff0c;并開啟。 進入接口f0/1&#xff0c;配置IP&#xff0c;并開啟。 設置靜態路由。 查看PC1的路由表 2、配…

IP地址192.168.1.1/24中的/24是什么意思

/24是指子網掩碼的位數。 子網掩碼的位數總共有32個&#xff0c;寫的的/24個就是24個1&#xff0c;其它8位都是0。 /24就可以寫成子網掩碼是&#xff1a;11111111 11111111 11111111 00000000 例如&#xff1a; /25&#xff0c;就代表有25個1&#xff0c;7個0&#xff0c;…

VLAN與子網劃分區別

轉自&#xff1a;http://bbs.51cto.com/thread-1514066-1.html 經常看到論壇里有新手上來發貼說已經弄了VLAN了&#xff0c;為什么還要劃分IP子網的問題。今天詳細講一下。 VLAN與IP子網&#xff08;劃分&#xff09;的區別。有點類似于重量和質量的區別: 重量的的單位是牛頓&…

IP地址中A類、B類、C類地址的區別

區別如下&#xff1a; 1、IP地址表示方法不同&#xff1a; 一個A類IP地址是指&#xff0c; 在IP地址的四段號碼中&#xff0c;第一段號碼為網絡號碼&#xff0c;剩下的三段號碼為本地計算機的號碼。如果用二進制表示IP地址的話&#xff0c;A類IP地址就由1字節的網絡地址和3字…

原始套接字簡介

一 原始套接字概述 原始套接字&#xff0c;指在傳輸層下面使用的套接字。流式套接字和數據報套接字這兩種套接字工作在傳輸層&#xff0c;主要為應用層的應用程序提供服務&#xff0c;并且在接收和發送時只能操作數據部分&#xff0c;而不能對IP首部或TCP和UDP首部進行操作&am…

原始socket例子

https://blog.csdn.net/qq_35426012/article/details/98858401 https://blog.51cto.com/u_13603157/2095503

Ucosii消息郵箱使用

https://blog.csdn.net/oyhb_1992/article/details/75270739 https://www.cnblogs.com/itloverhpu/p/3139511.html

ucosii中消息隊列、消息郵箱、信號量的區別

1、用信號量進行行為同步時&#xff0c;只能提供同步的時刻信息&#xff0c;不能提供內容信息。若被控制方要求得到控制方的內容信息時&#xff0c;可以使用消息郵箱或消息隊列。 2、但由于消息郵箱里只能存放一條消息&#xff0c;所以使用消息郵箱進行任務的同步時&#xff0c…

宏的使用 extern

https://www.cnblogs.com/chulin/p/9389254.html

#ifdef __cplusplus extern “C”的作用詳解

https://blog.csdn.net/dayou1024/article/details/107017432

C++和C語言函數相互調用

C代碼調用C函數&#xff1a; 在C中引用C語言中的函數和變量&#xff0c;在包含C語言頭文件&#xff08;假設為cExample.h&#xff09;時&#xff0c;需進行下列處理&#xff1a; extern "C" { #include "cExample.h" } …

淺談可重入函數與不可重入函數

淺談可重入函數與不可重入函數【轉】_shareinfo2018-CSDN博客_可重入函數

TCP socket心跳包示例程序

TCP socket心跳包示例程序_xqhrs232的專欄-CSDN博客_setsockopt 心跳包 原文地址::TCP socket心跳包示例程序_神奕的專欄-CSDN博客_tcp心跳包 相關文章 1、Linux網絡編程--服務端判斷客戶端斷開的經驗方法 ----Linux網絡編程--服務端判斷客戶端斷開的經驗方法_志存高遠-CSDN博…