信號的發送和捕捉函數(alarm、kill、raise、pause、 sleep、abort)

1.   alarm函數

(1) alarm函數原型

             alarm(設置信號傳送鬧鐘)

所需頭文件

#include <unistd.h>

#include <signal.h>

函數說明

alarm()用來設置信號SIGALRM在經過參數seconds指定的秒數後傳送給目前的進程。如果參數seconds 爲0,則之前設置的鬧鐘會被取消,並將剩下的時間返回

函數原型

unsigned int alarm(unsigned int seconds)

函數返回值

返回之前鬧鐘的剩餘秒數,如果之前未設鬧鐘,則返回0

 

(2) alarm函數說明

當所設置的時間值超過後,產生SIGALRM信號。如果不忽略或不捕捉此信號,則其默認動作是終止該進程。

每個進程只能有一個鬧鐘時間。如果在調用alarm時,以前已爲該進程設置過鬧鐘時間,而且它還沒有超時,則該鬧鐘時間的剩餘時間值作爲本次alarm函數調用的值返回,以前登記的鬧鐘時間則被新值代換。

如果有以前登記的尚未超過的鬧鐘時間,而新設的鬧鐘時間值爲0,則取消以前的鬧鐘時間,其剩餘時間值仍作爲函數的返回值。

 

(3) alarm函數舉例

alarm.c 源代碼如下:

#include <unistd.h>

#include <signal.h>

#include <stdio.h>

void handler() {  /*信號處理函數*/

    printf("hello\n");

}

int main()

{

    int i;

    int time ;

    signal(SIGALRM,handler);  /*註冊SIGALRM信號處理方式*/

    alarm(3);

    for(i=1;i<5;i++){

        printf("sleep %d ...\n", i);

        sleep(1);

    }

 

    alarm(3);

    sleep(2);

    time=alarm(0) ; /*取消SIGALRM信號,返回剩餘秒數*/

    printf("time=%d\n",time) ;

    for(i=1;i<3;i++){

        printf("sleep %d ...\n", i);

        sleep(1);

    }

 

    return 0 ;

}

編譯 gcc alarm.c –o alarm。

執行./alarm,執行結果如下:

sleep 1 ...

sleep 2 ...

sleep 3 ...

hello

sleep 4 ...

time=1

sleep 1 ...

sleep 2 ...

對程序結果分析如下:

信號是一種軟中斷,中斷的原理是保留執行現場,跳轉到中斷函數處執行,執行完後恢復以前的現場在斷點處繼續往下執行。所以alarm函數經過3秒時,for循環已經到了sleep的3秒位置;alarm發送鬧鈴信號,引起中斷,程序執行SIGALRM註冊函數handler(中斷處理函數),即輸出hello。信號處理handler函數執行完後,應用程序從中斷點恢復,繼續執行for循環,此時sleep到了4秒的位置。

alarm(0)取消註冊的鬧鈴(SIGALRM)信號,所以,第二次沒有執行SIGALRM信號註冊函數。

2. kill函數

(1) kill函數原型

kill函數是將信號發送給指定的pid進程。普通用戶利用kill函數將信號發送給該用戶下任意一個進程,而特權用戶(root)可以將信號發送系統中的任意一個進程。

kill函數原型及說明如下:

kill(傳送信號給指定的進程)

所需頭文件

#include <sys/types.h>

#include <signal.h>

函數說明

kill()可以用來傳送參數sig指定的信號給參數pid指定的進程

函數原型

int kill(pid_t pid,int sig)

函數傳入值

pid

pid>0 將信號傳給進程識別碼爲pid 的進程

pid=0 將信號傳給和目前進程相同進程組的所有進程

pid=-1 將信號廣播傳送給系統內所有的進程

pid<0將信號傳給進程組識別碼爲pid絕對值的所有進程

sig

信號編號

函數返回值

成功:0

出錯:-1,錯誤原因存於error中

錯誤代碼

EINVAL:參數sig不合法

ESRCH:參數pid 所指定的進程或進程組不存在

EPERM:權限不夠無法傳送信號給指定進程

 

(2) kill函數舉例

下面代碼實現的是父進程發信號給子進程。

kill.c 源代碼如下:

#include <stdio.h>

#include <unistd.h>

#include <signal.h>

#include <sys/types.h>

#include <sys/wait.h>

int main()

{

    pid_t pid;

    int status;

 

    pid= fork() ;

    if( 0==pid ){

        printf("Hi I am child process!\n");

        sleep(10);

    }

    else if ( pid > 0 ){

        printf("send signal to child process (%d) \n",pid);

        sleep(1);

   /*發送SIGABRT信號給子進程,此信號引起接收進程異常終止*/

        kill(pid ,SIGABRT);

   /*等待子進程返回終止信息*/

        wait(&status);

        if(WIFSIGNALED(status))

            printf("chile process receive signal %d\n",WTERMSIG(status));

    }else{

        perror("fork error") ;

        return -1 ;

    }

   

    return 0 ;

}

編譯 gcc kill.c –o kill。

執行./kill,執行結果如下:

Hi I am child process!

send signal to child process (10498)

chile process receive signal 6

3. raise函數

與kill函數不同的是,raise函數運行是向進程自身發送信號。

              raise(向自己發送信號)

所需頭文件

#include <sys/types.h>

#include <signal.h>

函數說明

向自己發送信號

函數原型

int raise(int sig)

函數傳入值

sig:信號

函數返回值

成功:0

出錯:-1,錯誤原因存於error中

4. pause函數

(1) pause函數原型

              pause(讓進程暫停直到信號出現)

所需頭文件

#include <unistd.h>

函數說明

令目前的進程暫停(進入睡眠狀態),直到被信號(signal)所中斷

函數原型

int pause(void)

函數返回值

只返回-1,錯誤原因存於error中

錯誤代碼

EINTR:有信號到達中斷了此函數

 

(2) pause函數舉例

下面pause.c源代碼簡單的實現了sleep函數的功能。由於SIGALRM信號默認的系統動作爲終止進程,所以在程序調用pause之後就暫停,當3秒後接收到alarm信號時進程就終止。

pause.c源代碼如下:

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

int main()

{

    int ret ;

    ret=alarm(3) ; /*調用alarm定時器函數*/

    pause() ;

    printf("I have been waken up.\n") ;

    return 0 ;

}

編譯 gcc pause.c –o pause。

執行./pause,執行結果如下:

Alarm clock

5. sleep和abort

(1) sleep函數原型

             sleep(讓進程暫停執行一段時間)

所需頭文件

#include <unistd.h>

函數說明

sleep()會令目前的進程暫停,直到達到參數seconds所指定的時間,或是被信號所中斷

函數原型

unsigned int sleep(unsigned int seconds)

函數傳入值

seconds:睡眠的秒數

函數返回值

若進程暫停到參數seconds所指定的時間,則返回0;若有信號中斷則返回剩餘秒數

 

(2) abort函數原型

             abort(以異常方式結束進程)

所需頭文件

#include <stdlib.h>

函數說明

此函數將SIGABRT信號給調用進程,此信號將引起調用進程的異常終止。此時所有已打開的文件流會自動關閉,所有的緩衝區數據會自動寫回。

函數原型

void abort(void)

 

(3) sleep、abort函數舉例

sys_sleep.c源代碼如下:

#include <stdio.h>

#include <stdlib.h>

int main(void)

{

    system("pwd") ;

    sleep(9) ; /*wait 9 second*/

    printf("Calling abort()\n");

        abort();

    printf("abort() after\n") ;

        return 0; /* This is never reached */

}

編譯 gcc sys_sleep.c -o sys_sleep。

執行./sys_sleep,執行結果如下:

/home/zjkf/public/signal

Calling abort

 

6.  信號的發送與捕捉簡要總結

對上述信號的發生與捕捉函數簡要總結說明如下:

kill函數可以向有用戶權限的任何進程發送信號,通常用kill函數來結束進程。

與kill函數不同的是,raise函數只向進程自身發送信號。

使用alarm函數可以設置一個時間值(鬧鈴時間),在將來的某個時刻該時間值超過時發送信號。

pause函數使調用進程掛起直至捕捉到一個信號。

 

摘錄自《深入淺出Linux工具與編程》

 

  

發佈了47 篇原創文章 · 獲贊 61 · 訪問量 44萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章