Linux 進程間通信 信號(signal)


1. 概念:

  1)信號是在軟件層次上對中斷機制的一種模擬,是一種異步通信方式

  2)信號可以直接進行用戶空間進程和內核進程之間的交互,內核進程也可以利用它來通知用戶空間進程發生了哪些系統事件。

  3)如果該進程當前並未處於執行態,則該信號就由內核保存起來,直到該進程恢復執行再傳遞給它;如果一個信號被進程設置為阻塞,則該信號的傳遞被延遲,直到其阻塞被 取消時才被傳遞給進程。

2.用戶進程對信號的響應方式:

  1)忽略信號:對信號不做任何處理,但是有兩個信號不能忽略:即SIGKILL及SIGSTOP。

  2)捕捉信號:定義信號處理函數,當信號發生時,執行相應的處理函數。

  3)執行缺省操作:Linux對每種信號都規定了默認操作

 

3.信號:

  SIGINT:ctrl+c 終止信號

  SIGQUIT:ctrl+\ 終止信號

  SIGTSTP:ctrl+z 暫停信號

  SIGALRM:鬧鍾信號 收到此信號后定時結束,結束進程

  SIGCHLD:子進程狀態改變,父進程收到信號

  SIGKILL:殺死信號

4.相關函數:
1)int kill(pid_t pid, int sig);
  功能:信號發送
  參數:pid:指定進程
  sig:要發送的信號
  返回值:成功 0;失敗 -1
2)int raise(int sig);
  功能:進程向自己發送信號
  參數:sig:信號
  返回值:成功 0;失敗 -1
3)unsigned int alarm(unsigned int seconds)
  功能:在進程中設置一個定時器
  參數:seconds:定時時間,單位為秒
  返回值:如果調用此alarm()前,進程中已經設置了鬧鍾時間,則返回上一個鬧鍾時間的剩余時間,否則返回0。

注意:一個進程只能有一個鬧鍾時間。如果在調用alarm時已設置過鬧鍾時間,則之前的鬧鍾時間被新值所代替

4)int pause(void);
  功能:用於將調用進程掛起直到收到信號為止。

5)void (*signal(int signum, void (*handler)(int)))(int);
  或者:
  typedef void (*sighandler_t)(int);
  sighandler_t signal(int signum, sighandler_t handler);
  功能:信號處理函數
  參數:signum:要處理的信號//不能是SIGKILL和SIGSTOP
    handler:SIG_IGN:忽略該信號。
    SIG_DFL:采用系統默認方式處理信號。
    自定義的信號處理函數指針
  返回值:成功:設置之前的信號處理方式;失敗:SIG_ERR

 6)void abort(void);

  給自己發送異常終止信號,(6.SIGABRO)終止並產生core文件。

例子:kill 函數發送殺死pid指向的進程的信號,raise 發送殺死自己的信號  

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
    pid_t pid;
    pid = fork();
    if(pid < 0)
    {
        perror("fork fail ");
        exit(1);
    }
    else if(pid == 0)
    {
        printf("child \n");
    }
    else
    {
        kill(pid,SIGKILL);//(此處pid是子進程的進程號)殺死 pid 發送進程的信號,kill 給其他進程發送信號,指定進程號
        printf("child killed\n");
        sleep(1);
        printf("father \n");
        wait(NULL); //等待子進程結束,並回收子進程資源
        raise(SIGKILL); //殺死自己的信號,函數raise 給自己發送信號
    }
    return 0;
}

測試:子進程還未來得及運行就被殺死了

 

 例子2: 定時器的使用

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, const char *argv[])
{
    printf("%d\n",alarm(7)); //7 秒定時器,此時返回 0 ,前面沒有使用定時器
    sleep(2);  //睡 2 秒
    while(1)
    {
        printf("%d\n",alarm(3)); //重新設置定時器值為 3 ,返回上次定時器剩余的時間,7-2 = 5
        sleep(7); //睡7秒,后會結束進程
    }
    return 0;
}

測試:Alarm clock 是定時器結束時提醒

 

 signal 信號使用例子1 : 

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void handler(int arg)
{
    printf("\nctrl + c\n");
//    exit(1);
//    raise(SIGKILL); 
    kill(getpid(),9); //9表示 SIGKILL 殺死信號
}

int main(int argc, const char *argv[])
{
    signal(SIGINT,handler);//定義自己的處理信號,當SIGINT信號發生時,調用 handler 函數處理
    while(1);
    return 0;
}

測試:

 

  signal 信號使用例子2 : 

 

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main(int argc, const char *argv[])
{
    signal(SIGINT,SIG_IGN);// ctrl +c 信號被忽略,SIG_IGN 表示忽略該信號
    while(1);

    return 0;
}

測試: 通過 ctrl + c 信號不能終止這個進程

 


免責聲明!

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



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