Linux進程間通信之信號

信號是Linux系統響應某些條件而產生的一個事件,接收到該信號的進程會執行相應的操作。
信號的名稱是在頭文件signal.h中定義的

信號 描述
SIGABORT 處理失敗
SIGALRM 報警時鐘
SIGFPE 浮點異常
SIGHUP 掛起
SIGILL 非法指令
SIGINT 終端中斷
SIGKILL Kill(不能被捕獲或是忽略)
SIGPIPE 寫入沒有讀端的管道
SIGQUIT 終端退出
SIGSEGV 非法的內存段訪問
SIGTERM 終止
SIGUSR1 用戶定義的信號1
SIGUSR2 用戶定義的信號2
SIGCHLD 子進程已停止或退出
SIGCONT 如果停止,繼續執行
SIGSTOP 停止執行(不能被捕獲或是忽略)
SIGTSTP 終止停止信號
SIGTTIN 後臺進程嘗試讀
SIGTTOU 後臺進程嘗試寫

linux編程中會對信號進行操作,經常進行捕捉和發送;經常用到對信號的捕捉和發送函數有兩對。
1、比較簡單的:如使用kill()(用於發送信號)和signal()(用於捕捉信號)
2、高級一些的:sigaction()(用於發送信號)和sigqueue()(用於捕捉信號)

4.自定義信號處理方式
1)signal函數

#include <signal.h>    
void (*signal(int sig, void (*func)(int)))(int);   

sig:信號值
func:信號處理函數指針,參數爲信號值

代碼示例如下(使用signal實現異步通知):

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>

#define MAX_LEN 100
void input_handler(int signum)
{
    char data[MAX_LEN];
    int len;

    //讀取STDIN_FILENO上的輸入
    len = read(STDIN_FILENO, &data, MAX_LEN);
    printf("signum : %d input availble:%s\n", signum, data);

}


void main(int argc, char const *argv[])
{
    int flags;
    pid_t pid = getpid();
    //安裝信號
    signal(SIGIO, input_handler);

    //設置本進程爲STDIN_FILENO文件的擁有者
    fcntl(STDIN_FILENO, F_SETOWN, pid);

    //啓用異步通知機制
    flags = fcntl(STDIN_FILENO, F_GETFL);
    fcntl(STDIN_FILENO, F_SETFL, flags | FASYNC);

    //死循環
    while (1);
}

輸出如下:
這裏寫圖片描述

2)sigaction函數
原型:
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
–第一個參數是信號的值,可以爲除了SIGKILL及SIGSTOP外的任何一個特定有效的信號(因爲這兩個信號定義了自己的處理函數,將導致信號安裝錯誤)
–第二個參數是指向節後sigaction的一個實例的指針,在sigaction的實例中,指定了對特定信號的處理,可以爲NULL,進程會以缺省方式對信號處理
–第三個參數oldact指向的對象用來保存原來對相應信號的處理,可以爲NULL
返回值:函數成功返回0,失敗返回-1。

sigaction結構體

struct sigaction {
    void     (*sa_handler)(int);//信號處理程序 不接受額外數據
    void     (*sa_sigaction)(int, siginfo_t *, void *);//信號處理程序,能接受額外數據,可以和sigqueue配合使用
    sigset_t   sa_mask;
    int        sa_flags;//影響信號的行爲SA_SIGINFO表示能接受數據
    void     (*sa_restorer)(void);//廢棄
};

–第二個參數最爲重要,其中包含了對指定信號的處理、信號所傳遞的信息、信號處理函數執行過程中贏屏蔽掉哪些函數等等。
–回調函數sa_handler、sa_sigaction只能任選其一

sigqueue

#include <signal.h>    
int sigqueue(pid_t pid, int sig, const union sigval value);   

示例代碼(進程間傳遞信息)
接收me_sigaction.c:


#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>

void handler(int sig, siginfo_t *info, void *ctx)  
{  

        printf("recv a sig=%d data=%d\n",sig, info->si_value.sival_int);  

}  

void main()  
{       

        pid_t pid = getpid();
        printf("current pid is %d\n", pid);
        struct sigaction act;  
        act.sa_sigaction=handler;  
        sigemptyset(&act.sa_mask);  
        act.sa_flags=SA_SIGINFO;  
        if(sigaction(SIGINT,&act,NULL) < 0) {
                printf("sigaction error\n");
                return;
        } 


        while(1);
}  

發送me_sigqueue.c

#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int main(int argc, char *argv[])  
{  

        pid_t pid=atoi(argv[1]);  
        union sigval v;  
        v.sival_int=100;  
        sigqueue(pid,SIGINT,v);  
        return 0;  
}  

輸出結果:
這裏寫圖片描述
(另一終端執行./send_test 8031)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章