signal()函數


函數原型

void (*signal(int sig,void(*func)(int)))(int);

指定使用sig指定的信號編號處理信號的方法。參數func指定程序可以處理信號的三種方式之一:

  1. l  默認處理(SIG_DFL):          信號由該特定信號的默認動作處理
  2. l  忽略信號(SIG_IGN):      忽略信號,即使沒有意義,代碼執行仍然繼續。
  3. l  函數處理程序:                 定義一個特定的函數來處理信號。

或SIG_DFL要么SIG_IGN被設置為程序啟動時每個支持信號的默認信號處理行為。

參數:

SIG設置處理功能的信號值,以下宏常量表達式標識標准信號值:

 

信號

SIGABRT

(信號終止)異常終止,例如由…發起的退出功能

SIGFPE

(信號浮點異常)錯誤的算術運算,比如零分頻或導致溢出的運算(不一定是浮點運算)

SIGILL

(信號非法指令)無效的功能圖像,例如非法指令。這通常是由於代碼中的損壞或嘗試執行數據

SIGINT

(信號中斷)交互式注意信號。通常由應用程序用戶生成

SIGSEGV

(信號分段違規)對存儲的無效訪問:當程序試圖在已分配的內存之外讀取或寫入時。

SIGTERM

(信號終止)發送到程序的終止請求。

 

每個庫實現可以提供可以與此函數一起使用的附加信號值宏常量。

 

注意:並不是所有的運行環境都需要生成自動信號,即使在上述特定情況下也是如此,盡管所有運行環境都必須通過顯示調用生成的信號來生成提高功能

 

FUNC

指向函數的指針。這是程序員定義的函數,也可以是以下預定義函數之一:

SIG_DFL

默認處理:信號由該特定信號的默認操作處理

SIG_IGN

忽略信號:忽略信號

 

如果是一個函數,它應該遵循以下原型(使用C鏈接)

void handler_function(int parameter)

 

返回值

返回類型與參數func類型相同。

如果請求成功,則該函數返回指向特定處理函數的指針,該函數在調用 之前負責處理該信號(如果有的話)。或者SIG_DFL要么SIG_IGN。如果在調用之前信號由默認處理程序處理或被忽略,則相應的,如果該功能尚未能成功注冊新的信號處理程序,則返回SIG_ERR和錯誤號可以設置成正值。

 

/***
signal.c
***/
 #include<stdio.h>
 #include<signal.h>
 
 sig_atomic_t signaled = 0;
 
 void my_handler(int param)
 { 
     signaled = 1;
 }
 
 int main()
 {
     void (*prev_handler)(int); 
 
     prev_handler = signal(SIGINT,my_handler);
   
     raise(SIGINT);
 
     printf("signaled is %d.\n",signaled);
 }

運行結果:

root@ubuntu:/mnt/hgfs/ShareWindows/shiyanlou/C/Flappy_Bird# gcc signal.c -o signal

root@ubuntu:/mnt/hgfs/ShareWindows/shiyanlou/C/Flappy_Bird# ./signal

signaled is 1.

 

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

第一個參數是要捕捉的信號(查看信號: kill –l , 9號SIGKILL信號不能被捕捉)

第二個參數表示我們要對信號進行的處理方式。

 

信號處理方式一般有三種:

1.忽略此信號(SIG_IGN):

/***
sig_ign.c
***/
#include<stdio.h>
#include<unistd.h>
#include<signal.h>

int main()
{
    signal(2,SIG_IGN);
    while(1)
    {
        printf("23333\n");
        sleep(1);
    }
    return 0;
}

執行程序會進入死循環,Ctrl+c進程不會停止,因為我們對Ctrl+c產生的2號SIGINT信號做了忽略處理,Ctrl+z(SIGQUIT)退出。

 

2.執行該信號的默認處理動作(SIG_DEL):

/***
sig_def.c
***/
#include<stdio.h>
#include<signal.h>
#include<unistd.h>

int main()
{
    signal(2,SIG_DFL);
    while(1)
    {
        printf("23333\n");
        sleep(1);
    }
    return 0;
}

執行程序時,對Ctrl+c設置的默認動作處理,此時ctrl+c就可以停止程序。

 

 3.提供一個信號處理函數,要求內核在處理該信號時切換到用戶態執行這個處理函數,這種方式稱為捕捉一個信號:

/***
sig_catch.c
***/
#include<stdio.h>
#include<signal.h>
#include<unistd.h>

void handler(int signo)
{
    printf(" catch a signal:%d\n",signo);
}

int main()
{
    signal(2,handler);
    while(1)
    {
        printf("2333\n");
        sleep(1);
    }
    return 0;
}

運行結果:

 

 

此時按下ctrl+c會被捕捉到,不會中斷程序了。

 

一些常用的信號宏定義:

Signal

Description

SIGABRT

由調用abort函數產生,進程非正常退出

SIGALRM

由alarm函數設置的timer超時或setitimer函數設置的interval timer超時

SIGBUS

某種特定的硬件異常,通常由內存訪問引起

SIGCANCEL

由SOLARIS Thread Library內部使用,通常不會使用

SIGCHLD

進程Terminate或Stop的時候,SIGCHLD會發送給他的父進程。缺省情況下會該Signal會忽略

SIGCONT

當被stop的進程恢復運行的時候,自動發送

SIGEMT

和實現相關的硬件異常

SIGFPE

 數字相關的異常,如被0除,浮點溢出。

SIGFREEZE

Solaris專用,Hiberate或者Suspended時候發送。

SIGHUP

發送給具有Terminal的Controlling Process,當terminal被disconnect時候發送

SUGILL

非法指令異常

SIGINFO

BSD signal。由Status Key產生,通常是CTRL+T。發送給所有Foreground Group的進程

SIGINT

由Interrupt Key產生,通常是CTRL+C或DELETE。發送給所有的ForeGround FROUP的進程

SIGIO

異步IO事件

SIGIOT

實現相關的硬件異常,一般對應SIGABRT

SIGKILL

無法處理和忽略,中止某個程序

SIGLWP

由Solaris Thread Library內部使用

SIGPIPE

在reader終止之后寫Pipe的時候發送

SIGPOLL

當某個事件發送給Pollable Device的時候發送

SIGPROF

Setitimer指定的Profilling Interval Timer所產生

SIGPWR

和系統相關。和UPS相關

SIGQUIT

輸入Quit Key的時候,(CTRL + \)發送給所有的Foreground Group的進程

SIGSEGV

非法內存訪問

SIGSTKFLT

Linux專用,數學協處理器的棧異常

SIGSTOP

中止進程,無法處理和忽略

SIGSYS

非法系統調用

SIGTERM

請求中止進程,kill命令缺省發送

SIGTHAW

Solaris專用,從Suspend恢復時發送

SIGTRAP

實現相關的硬件異常,一般是調試異常

SIGTSTP

Suspend Key,一般是Ctrl+Z,發送給所有的ForeGround Group的進程

SIGTTIN

當BackGround Froup的進程嘗試讀取Terminal的時候發送

SIGTTOU

當Background Group的進程嘗試寫Terminal的時候發送

SIGURG

當out-of-band data接收的時候可能發送

SIGUSR1

用戶自定義signal 1

SIGUSR2

用戶自定義signal 2

SIGVTALRM

setitimer函數設置的Virual Interval Timer超時的時候

SIGTAITING

Solaris Thread Library內部實現專用

SIGWINCH

當Terminal的窗口大小改變的時候,發送給Foreground Group的所有進程

SIGXCPU

當CPU時間限制超時的時候

SIGXFSZ

進程超過文件大小限制

SIGXRES

Solaris專用,進程超過資源限制的時候發

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM