linux程式間通訊-----訊號總結

readyao發表於2016-01-07



相關文章:

linux訊號的阻塞和未決

linux中sleep詳解例項


廢話不說,先把所有的訊號列出來(注意裡面沒有32, 33訊號),敲命令 kill -l


還有一個命令 man 7 signal 來檢視訊號的預設行為


後32個訊號表示實時訊號,是可靠訊號,這保證了傳送的多個實時訊號都被接收;

實時訊號都支援排隊,都是可靠訊號;非實時訊號都不支援排隊,都是不可靠訊號;

#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
signal是註冊訊號的函式,當註冊了該訊號的行為後,那麼程式收到該訊號會執行設定好的行為;
引數handler還可以指定兩個特殊的值;SIG_IGN是遮蔽該訊號;SIG_DFL是恢復預設行為,SIGINT的預設行為是程式退出;


#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
傳送訊號的函式,可以向程式ID為pid的程式傳送sig訊號;也可以向自身傳送訊號;

例項1:程式註冊了SIGINT和SIGQUIT訊號的處理函式;

SIGINT的值為2,SIGQUIT的值為3;按下Ctrl+c產生SIGINT訊號,按下Ctrl+\產生SIGQUIT訊號;

/*************************************************************************
	> File Name: int_quit_signal.cpp
	> Author: 
	> Mail: 
	> Created Time: 2015年12月16日 星期三 21時48分22秒
 ************************************************************************/

#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;

void handler(int num)
{
    cout << "\nrecvive the signal is " << num << endl;
    if(num == SIGQUIT){
        cout << "recevie the exit signal..." << endl;
        exit(0);
    }
}
int main(int argc, char *argv[])
{
    //註冊中斷訊號SIGINT
    signal(SIGINT, handler);
    signal(SIGQUIT, handler); 
    cout << "main process is waiting for the signal of SIGINT and SIGQUIT..." << endl;
    while(1){
        pause();
    }
    cout << "main process exit.." << endl;
    exit(0);
}


例項2:程式執行的前10秒是遮蔽了SIGINT訊號,所以當產生SIGINT訊號的時候程式不處理直接忽略;10秒過後就恢復預設行為,當產生SIGINT訊號的時候程式直接退出;

/*************************************************************************
	> File Name: int_quit_signal.cpp
	> Author: 
	> Mail: 
	> Created Time: 2015年12月16日 星期三 21時48分22秒
 ************************************************************************/

#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;

int main(int argc, char *argv[])
{
    //註冊中斷訊號SIGINT
    signal(SIGINT, SIG_IGN);
    cout << "main process is sleeping(10s)...." << endl;
    sleep(10);
    cout << "\nthe signal has the default action and waiting the SIGITN to quit..." << endl;
    signal(SIGINT, SIG_DFL);

    sleep(100);
    cout << "main process exit.." << endl;
    exit(0);
}

例項3:在這個例子中要使用kill來傳送訊號;程式的內容是,在父程式中註冊SIGINT訊號的訊號處理函式,在子程式中每個2秒鐘就向父程式傳送一個SIGINT訊號;
關於子程式中的每2秒傳送一個訊號,可以簡單的使用while迴圈加上slepp(2)來實現;我這裡使用alarm函式來實現,
該函式設定一個鬧鐘延遲傳送訊號告訴linux核心n秒中以後,傳送SIGALRM訊號;所以我在子程式安裝對SIGALRM的訊號處理函式,並在該訊號處理函式中再呼叫alarm函式;

/*************************************************************************
	> File Name: int_quit_signal.cpp
	> Author: 
	> Mail: 
	> Created Time: 2015年12月16日 星期三 21時48分22秒
 ************************************************************************/

#include <iostream>
#include <signal.h>
#include <cstdlib>
#include <unistd.h>
using namespace std;

void handler(int num)
{
    cout << "parent recvive the signal is " << num << endl;
    if(num == SIGQUIT){
        cout << "parent receive the signal of quit.." << endl;
        exit(0);
    }
}

void child_handler(int num)
{
    cout << "child receive the signal is " << num << endl;
    if(num == SIGQUIT){
        cout << "child receive the signal of quit.." << endl;
        exit(0);
    }
    kill(getppid(), SIGINT);//向父程式傳送訊號
    alarm(2);
}
int main(int argc, char *argv[])
{
    //註冊中斷訊號SIGINT
    signal(SIGINT, handler);
    signal(SIGQUIT, handler);
    pid_t pid = fork();
    if(pid < 0){
        cout << "fork error..." << endl;
        exit(-1);
    }
    if(pid == 0){
       signal(SIGALRM, child_handler);
       signal(SIGQUIT, child_handler);
       alarm(2);
       cout << "this is child process..." << endl;
        while(1){
            pause();
        }
        exit(0);
    }
    cout << "main process is waiting for the signal of SIGINT and SIGQUIT..." << endl;
    while(1){
        pause();
    }
    cout << "main process exit.." << endl;
    exit(0);
}


值得注意的是,最後從鍵盤傳送了一個SIGQUIT訊號,但是兩個程式(父子程式)都收到了該訊號;如果沒有在子程式中安裝該訊號,那麼父程式會連續收到兩個SIGQUIT訊號;



相關文章