信號是軟中斷,包涵了4中異常控制(操做系統中程序的異常執行:中斷、陷阱、故障、終止)。java
方法 | 說明 | 成功 | 失敗 |
---|---|---|---|
註冊感興趣信號 | |||
signal | 註冊感興趣的信號到內核 | 以前設置的信號處理 | SIG_ERR |
sigaction | 註冊感興趣的信號到內核 | 0 | 1 |
kill | 發送給其它進程關閉信號 | 0 | -1 |
raise | 發送給本身關閉信號 | 0 | -1 |
alarm | 定時器 | 0或之前設置的鬧鐘時間的餘留秒數 | |
pause | 掛起線程直到捕捉到一個信號 | ||
信號集合 | |||
sigemptyset | 清空、初始化一個信號集 | 0 | -1 |
sigfillset | 初始化一個信號集 | 0 | -1 |
sigaddset | 添加一個信號 | 0 | -1 |
sigdelset | 刪除一個信號 | 0 | -1 |
sigismember | 判斷集合中是否有這個信號 | 1 | 0 |
屏蔽信號操做 | |||
sigprocmask | 屏蔽一個信號集 | 1 | 0 |
sigpending | 返回在信號被阻塞時,傳遞到進程的阻塞信號 | 1 | 0 |
sigsuspend | 原子操做:掛起進程,直到接收到信號集中的信號,執行信號處理函數,sigsuspend返回 | -1,errno=EINTR | |
abort | 使進程異常終止 | ||
sleep | 進程休眠 | 0或未休眠完的秒數 | |
sigqueue | 發送信號及信息,經過sigaction接受 | 0 | -1 |
跳轉 | 原子操做,不會被新的信號中斷 | ||
sigsetjmp | 跳轉點 | 直接調用,返回0;siglongjmp調用,返回非0 | |
siglongjmp | 跳轉 |
信號來的時候。os會中止進程執行,執行信號處理程序。信號處理程序執行完成,繼續執行進程中止地方繼續執行。linux
信號來源:git
信號處理:安全
信號集:能表示多個信號集合 (signal set) 的數據類型。網絡
信號列表:併發
名稱 | 產生 | 說明 | 默認動做 | 建議處理方式 |
---|---|---|---|---|
SIGABRT | abort函數 | 異常終止(abort) | 終止+core | |
SIGALRM | alrm函數設置的定時器超時 | 定時器異常(alarm) | 終止 | |
SIGBUS | 出現某些類型的內存故障,當進程經過mmap訪問內存I/O,並超出了範圍 | 硬件故障 | 終止+core | |
SIGCANCEL | solaris線程 | 線程庫內部使用 | 忽略 | |
SIGCHLD | 當一個進程終止或中止時,SIGCHLD信號被送給其父進程。 | 子進程狀態改變 | 忽略 | 父進程在信號處理函數中調用wait函數能夠取得子進程的ID和其終止狀態 |
SIGCONT | 此做業控制信號發給須要繼續運行,但當前處於中止狀態的進程 | 是暫停進程繼續 | 繼續/忽略 | |
SIGEMT | 硬件故障 | 終止+core | ||
SIGFPE | 除以0、浮點數溢出 | 算術異常 | 終止+core | |
SIGFREEZE | 此信號僅solaris定義 | 檢查單凍結 | 忽略 | |
SIGHUP | 終端接口檢查到一個鏈接斷開,則將次信號送給與該終端相關的控制進程(會話首進程) | 鏈接端口 | 終止 | |
SIGILL | 非法硬件指令 | 終止+core | ||
SIGINFO | BSD的信號,當用戶按狀態鍵(Ctrl+T)時,終端驅動程序產生此信號併發送至前臺進程組中的每個信號。 | 請求 | 忽略 | |
SIGINT | Ctrl+C | 終端中斷符 | 終止 | |
SIGIO | linux中,SIGIO與SIGPOLL具備相同值 | 異步I/O | 終止/忽略 | |
SIGIOT | 硬件故障 | 終止+core | ||
SIGJVM1 | Solaris上爲java虛擬機預留的一個信號 | java虛擬機內部使用 | 忽略 | |
SIGJVM2 | Solaris上爲java虛擬機預留的一個信 | java虛擬機內部使用 | 忽略 | |
SIGKILL | 不能被捕捉 | 終止 | 終止 | |
SIGLOST | 運行在Solaris NFSv4 客戶端系統中的進程,恢復階段不能從新得到鎖,此時將由這個信號通知進程 | 資源丟失 | 終止 | |
SIGLWP | Solaris的線程庫內部使用 | 線程庫內部使用 | 終止/忽略 | |
SIGPIPE | 管道的讀進程終止時寫寫管道,則產生次信號 | 寫至無讀進程的管道 | 終止 | |
SIGPOLL | 在SUSv4中被棄用 | 可輪訓事件(poll) | 終止 | |
SIGPROF | 在SUSv4中被棄用 | 梗概時間超時(setitimer) | 終止 | |
SIGPWR | 依賴於系統的信號,用於不間斷電影(UPS)的系統 | 電源失效/重啓 | 終止/忽略 | |
SIGQUIT | Ctrl+|終端退出符 | 終止+core | ||
SIGSEGV | 進程進行了一次無效的內存引用(程序出錯:訪問一個未經初始化的指針) | 無效內存引用 | 終止+core | |
SIGSTKFLT | Linux定義:數序協處理器棧的故障 | 協處理器棧故障 | 終止 | |
SIGSTOP | 做業控制信號,中止一個進程 | 中止 | 中止進程 | |
SIGSYS | 早期版本的系統調用,如今不兼容 | 無效系統調用 | 終止+core | |
SIGTERM | kill(1)命令發送的系統默認終止信號,進程退出以前作好清理工做 | 終止 | 忽略 | |
SIGTHAW | Solais定義,被系統掛起的進程恢復時 | 檢查單解凍 | 忽略 | |
SIGTHR | BSD線程庫預留的信號 | 線程庫內部使用 | 忽略 | |
SIGTRAP | 硬件故障 | 硬件故障 | 終止+core | |
SIGTSTP | 交互中止型號:Ctrl+z。 | 終端中止符 | 中止進程 | |
SIGTTIN | 後臺進程試圖讀取其控制終端時,終端驅動產生 | 後臺讀控制tty | 中止進程 | |
SIGTTOU | 一個後臺進程試圖寫其控制終端時,終端驅動產生次型號 | 後臺寫向控制tty | 中止進程 | |
SIGURG | 在網絡鏈接上鍊接到帶外的數據,可選擇產生 | 緊急狀況(套接字) | 忽略 | |
SIGUSR1 | 用戶自定義信號 | 終止 | ||
SIGUSR2 | 用戶自定義信號 | 終止 | ||
SIGVTALRM | setitimer(2)函數設置的虛擬間隔時間超時 | 虛擬時間鬧鐘(setitimer) | 終止 | |
SIGWAITING | 內核維護與每一個終端或僞終端相關聯窗口的大小 | 線程庫內部使用 | 忽略 | |
SIGWINCH | 內核維持與每一個終端或僞終端相關聯窗口的大小 | 終端窗口大小改變 | 忽略 | |
SIGXCPU | 超過CPU限制(setrlimit) | 終止或終止+core | ||
SIGXFSZ | 超過文件長度限制(setrlimit) | 終止或終止+core | ||
SIGXRES | 超過資源控制 | 忽略 |
不可靠信號: 在早起版本中信號是不可靠的。信號可能會丟失,一個信號發生了,但進程可能一直不知道這點。異步
中斷的系統調用:若是進程在執行一個低速系統(主要是I/O)調用而阻塞期間捕捉到一個信號,則系統調用被中斷。該系統調用返回 errno =EINTR.函數
可重入函數:在信號處理程序中保證調用安全的函數,這些函數是可充入並被稱爲是異步信號安全的。ui
可靠過程:信號由產生、發送、接受、處理過程。操作系統
'產生-->發送-->接受-->處理
#include <signal.h> void (*signal(int signo,void (*func)(int)))(int); --- '成功:返回之前的信號處理配置;出錯:返回SIG_ERR' # 使用方式 if(signal(SIGUSER1,sig_usr)SIG_ERR) printf("can't catch SIGUSER1"); if(signal(SIGUSER2,sig_user)SIG_ERR) printf("can't catch SIGUSER1");
參數:
特色:
#include <signal.h> int kill(pid_t pid,int signo); int raise(int signo); '進程向自身發送信號' -- '成功:0;出錯:-1' # 使用 raise(signo) = kill(gitpid(), signo);
pid | 說明 |
---|---|
pid>0 | 將該信號發送給進程ID爲pid的進程 |
pid0 | 將該信號發送給與發送進程屬於同一進程組的全部進程,需權限 |
pid<0 | 將該信號發送給其它進程組ID等於pid的絕對值,需權限 |
pid-1 | 將該信號發送給有權限發送的全部進程 |
#include <unistd.h> unsigned int alarm(unsiged int secods); -- '0或之前設置的鬧鐘時間的餘留秒數'
#include <unistd.h> void pause(void); -- '-1,errno設置爲EINTR'
#include <signal.h> int sigemptyset(sigset_t *secods); int sigfillset(sigset_t *set); int sigaddset(sigset_t *set, int signo); int sigdelset(sigset_t *set,int signo); -- '成功:0;出錯:-1' int sigismember(const sigset_t *set, int signo); --'真:1;假:0'
pid | 說明 |
---|---|
sigemptyset | 初始化set,並清除其中全部信號 |
sigfillset | 初始化set,使其包涵全部信號 |
sigaddset | 新增一個signo信號到set中 |
sigdelset | 刪除一個signo信號到set中 |
sigismember | 定位signo是否在set中 |
#include <signal.h> int sigprocmask(int how,const sigset_t *restrict set, sigset_t *restrict oset); -- '成功:0;出錯:-1'
參數:
how | 說明 |
---|---|
SIG_BLOCK | 該進程新的信號屏蔽字是當前信號屏蔽字和set指向信號集的 並集,set包含了但願阻塞的附加信號 |
SIG_UNBLOCK | 該進程新的信號屏蔽字是當前信號屏蔽字和set所指向的信號屏蔽字的 交集。set包涵了但願解除阻塞的信號 |
SIG_SETMASK | 該進程新的信號屏蔽是指set所指向的值 |
#include <signal.h> int sigpending(sigset_t *set); --'成功:0;失敗:-1'
特色:
#include <signal.h> int sigaction(int signo,const struct sigaction *restrict act, struct sigaction *restrict oact); --'成功:0;失敗:-1' # sigaction結構 struct sigaction { void (*sa_handler)(int); '信號處理函數' sigset_t sa_mask; '屏蔽字信號集' int sa_flags; '選項' void (*sa_sigaction)(int,siginfo_t * , void *); '交替操做' } # sa_handler 函數 # 默認 void handler(int signo); # sa_flags設置SA_SIGINFO void handler(int signo, siginfo_t *info,void *context); # siginfo_t 結構 struct siginfo { int si_sigo; '信號數量' int si_errno; 'if nonozero,errno value from <errno.h>' int si_code; 'additional info (depends on signal)' int si_pid; '信號發送的進程id' int si_uid; '信號發送的進程user id' int si_addr; '失敗引發的地址' int si_status; 'exit value or signal number' union sigval si_value; '特殊的應用值' .... }
參數:
sa_mask:在調用信號處理程序的時候,將被加入到進程的信號屏蔽字中。等待信號處理程序執行完成,則進程信號屏蔽字恢復。同一信號,一次處理一個
sa_flags:
選項 | 說明 |
---|---|
SA_INTERRUPT | 此信號終端的系統調用不自動重啓 |
SA_NOCLDSTOP | 若signo是SIGCHLD,當子信號進程終止時,不產生此信號。 默認:當子進程終止時,仍舊產生次信號。設置:中止的進程繼續運行時,不產生SIGCHLD信號。 |
SA_NOCLDWAIT | 若signo是SIGCHLD,則當調用進程的子進程終止時,不建立僵死進程。若調用進程隨後調用wait,則阻塞到它全部子進程都終止,此時返回-1 |
SA_NODEFER | 當捕捉到此信號時,在執行其信號捕捉函數時,系統不自動阻塞此信號。 |
SA_ONSTACK | 若sigaltstack已聲明瞭ige替換棧,則次信號遞送給替換棧上的進程。 |
SA_RESETHAND | 信號處理函數的入口,將該信號的處理方式重置爲SIG_DFL,並清除SA_SIGINFO標誌。 |
SA_RESTART | 信號中斷的系統調用自動重啓 |
SA_SIGINFO | 信號處理程序會有信號的其它信息 |
#include <setjmp.h> int sigsetjmp(sigjmp_buf env,int savemask); -- '直接調用,返回0;siglongjmp調用,返回非0' void siglongjmp(sigjmp_buf env,int val); # 使用方式 main(){ if(signal(SIGUSER1,sig_user1) SIG_ERR) printf("signal error"); if(sigsetjmp(jmpbuf,1)){ printf("ending main:"); //siglongjmp調用 } } static void sig_usr1(int signo) { siglongjmp(jmpbuf,1); }
#include <signal.h> int sigsuspend(const sigset_t *sigmask); -- '返回:-1,並將errno設置爲EINTR' # 用法 sigset_t newmask,oldmask,waitmask sigemptyset(&waitmask); sigaddset(&waitmask,SIGUSER1); sigemptyset(&newmask); sigaddset(&newmask,SIGINT); '屏蔽SIGINT信號' if(sigprocmask(SIG_BLOCK,&newmask,&oldmask)<0){ printf("SIG_BLOCK error"); } '掛起進程、等待用戶進程' if(sigsuspend(&waitmask)!=-1){ printf("sigsuspend error"); } '將進程設置回去' if(sigprocmask(SIG_BLOCK,&oldmask,NULL)<0){ printf("SIG_BLOCK error"); }
特色:
#include <stdlib.h> void abort(void);
#include<unistd.h> unsigned int sleep(unsigned int seconds); --'0或未休眠完的秒數' #include <time.h> int nanosleep(const struct timespec *reqtp,struct timespec *remtp); -- '若休眠到要求的時間,返回0;出錯:-1' int clock_nanosleep(clockid_t clock_id,int flags, const struct timesepc *reqtp, struct timespec *remtp); -- '休眠要求的時間,返回0;出錯,返回錯誤碼'
特色:
#include <signal.h> int sigqueue(pid_t pid,int signo,const union sigval value); --'成功:0;出錯:-1'