信號

信號是軟中斷,包涵了4中異常控制(操做系統中程序的異常執行:中斷、陷阱、故障、終止)。java

  • ** sigprocmask、sigsuspend**能夠用來作子父進程喚醒
  • **sigaction、sigqueue **能夠用來作子父進程的信息傳遞

方法提要

方法 說明 成功 失敗
註冊感興趣信號
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 跳轉

名稱解釋

  • 信號概念:每一個信號都有一個名字,以SIG

特色

  • 信號來的時候。os會中止進程執行,執行信號處理程序。信號處理程序執行完成,繼續執行進程中止地方繼續執行。linux

  • 信號來源:git

    • 用戶按終端鍵時,引起終端產生的信號。例如:Ctrl+C<陷阱>
    • 硬件異常產生信號:除數爲0、無效的內存引用。例如:內存缺頁。<故障>
    • 進程調用kill(2)函數可將任意信號發送給另外一個進程或進程組。<終止>
    • 用戶能夠kill(1)命令將信號發送給其它進程。<終止>
    • 當檢測到某種軟條件已經發生,並應將其通知有關進程也產生信號。例如:<陷阱>
  • 信號處理:安全

    • 忽略信號:大多數信號可以使用這種方式處理,除了SIGKILL 和 SIGSTOP.
    • 捕捉信號: 進程在接受到某種信號的時候,內核調用一個用戶函數處理
    • 執行系統默認動做:大多數信號的系統默認動做是終止該進程。終止+core
  • 信號集:能表示多個信號集合 (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.函數

    • 自動重啓的系統調用:ioctl、read、write、readv、write、wait和waitpid.
    • linux中:signal默認重啓、sigaction可選。
  • 可重入函數:在信號處理程序中保證調用安全的函數,這些函數是可充入並被稱爲是異步信號安全的。ui

  • 可靠過程:信號由產生、發送、接受、處理過程。操作系統

    • 內核接受信號後,一般在進程表設置一個標誌。(發送、接受)
    • 進程能夠選擇不接受信號(阻塞、屏蔽信號接受)
    • 進程在屏蔽過程當中能夠改變對該信號的處理
    • 在阻塞過程當中,若是屢次發生屢次。內核對這些信號進行排隊
'產生-->發送-->接受-->處理

函數

signal :信號處理函數

#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");
  • 參數:

    • signo : 上表的信號常量
    • (*func)(int) :信號處理程序
  • 特色:

    • signal註冊一個信號及信號處理函數到內核
    • exec函數新啓動的進程不繼承父進程的信號設置

kill、raise:

#include <signal.h>

int kill(pid_t pid,int signo);

int raise(int signo); '進程向自身發送信號'

    -- '成功:0;出錯:-1'
# 使用

raise(signo) = kill(gitpid(), signo);
  • 參數:
    • pid:
pid 說明
pid>0 將該信號發送給進程ID爲pid的進程
pid0 將該信號發送給與發送進程屬於同一進程組的全部進程,需權限
pid<0 將該信號發送給其它進程組ID等於pid的絕對值,需權限
pid-1 將該信號發送給有權限發送的全部進程

alarm:定時器

#include <unistd.h>

unsigned int alarm(unsiged int secods);

    -- '0或之前設置的鬧鐘時間的餘留秒數'
  • 特色:
    • 超時發送SIGALRM信號
    • 還沒有超時則返回剩餘時間

pause:掛起進程直到捕捉到一個信號

#include <unistd.h>

 void pause(void);

    -- '-1,errno設置爲EINTR'
  • 特色:
    • sleep函數:用 alarm和pause 實現的定時器。
    • 執行了信號吹程序並從其返回時,pause才返回。

sigemptyset、sigfillset、sigaddset、sigdelset、sigismember:信號集設置

#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中

sigprocmask:屏蔽信號集

#include <signal.h>

int sigprocmask(int how,const sigset_t *restrict set, sigset_t *restrict oset);

    -- '成功:0;出錯:-1'
  • 參數:

    • oset: 進程以前的屏蔽字
    • how: 若set是空指針,則不改變該進程的信號屏蔽字,how無心義。
how 說明
SIG_BLOCK 該進程新的信號屏蔽字是當前信號屏蔽字和set指向信號集的 並集,set包含了但願阻塞的附加信號
SIG_UNBLOCK 該進程新的信號屏蔽字是當前信號屏蔽字和set所指向的信號屏蔽字的 交集。set包涵了但願解除阻塞的信號
SIG_SETMASK 該進程新的信號屏蔽是指set所指向的值

sigpending:信號處理註冊方法

#include <signal.h>

int sigpending(sigset_t *set);

    --'成功:0;失敗:-1'
  • 特色:

    • 相似於上面的pausewait方法,等待信號喚醒。

sigaction : 信號處理註冊方法

#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 信號處理程序會有信號的其它信息

sigsetjmp、siglongjmp: 跳轉,相似goto

#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);
}
  • 特色:
    • 原子操做:goto+sigprocmask
sigsuspend:原子操做:掛起進程,直到接收到信號集中的信號,執行信號處理函數,sigsuspend返回。
#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"); 
}
  • 特色:

    • 相似pause:掛起進程、等待某個信號。
    • 子父進程之間的通訊。

abort:使進程異常終止

#include <stdlib.h>

void abort(void);

sleep、nanosleep和clock_nanosleep

#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;出錯,返回錯誤碼'
  • 特色:

    • nanosleep:提供毫秒級

sigqueue:發送信號及信息,經過sigaction接受

#include <signal.h>

int sigqueue(pid_t pid,int signo,const union sigval value);

    --'成功:0;出錯:-1'
  • 特色:
    • sigaction 函數指定SA_SIGINFO標誌。
    • 子父進程之間的通訊。
相關文章
相關標籤/搜索