linux 中signal機制如何應用 二

2021-08-02 20:49:04 字數 3320 閱讀 7027

上一節linux 中signal機制如何應用(一)講的例子是不帶引數的訊號處理機制,這一節講帶引數的。

我們知道用kill只是傳送訊號不能攜帶引數,如果我們想要傳送訊號給程序並且攜帶引數,那就得用sigqueue函式了。可以說,sigqueue函式比kill更加強大,經常是與sigaction()函式配合使用。

sigqueue函式:

int sigqueue(pid_t pid,int signo,const union sigval value);  

//pid: 指定接收訊號的程序pid

//signo: 要傳送的訊號,

//sigval: 聯合資料結構 sigval,指定了訊號傳遞的引數

//返回值: 成功返回0,失敗返回-1

union sigval的定義:

typedef

union sigval

sigval_t;

來思考乙個問題,c++的模板函式是怎麼實現的?

上一節用sigaction實現的signal函式是不攜帶引數的,這是原來的函式signal_test(int signo,void (*func)(int)),第二個引數是函式指標,函式有乙個int引數,返回void型別。而現在,我們想要加上攜帶引數的情形。那麼第二個引數的型別就不是固定的,因為需要void (*func)(int signo, siginfo_t *info,void *context)這種型別的函式指標。我們可能會想到c++的模板函式,但是我們要用c語言實現又該怎麼辦呢?辦法還是有的,這時可以把引數定義為void*型別,引數傳進函式後,在函式體裡面強制轉化為函式指標就可以了。

我們在下面定義了兩個函式指標,用於在訊號處理函式中強制轉化指標型別。具體採用哪乙個需要根據flag型別來確定。

typedef void (*pfunc)(int);

typedef void (*psignalfunparam)(int, siginfo_t *, void *);

通常情況按照下列方式呼叫訊號處理函式:

void handler(int signo);

需要填充sigaction結構體成員act.sa_handler = handler;

但是,如果設定了sa_siginfo標誌,也就是act.sa_flags = sa_siginfo時,要按照下列方式填充sigaction結構體成員和呼叫訊號處理程式:

void handler(int signo, siginfo_t *info,void *context);

需要填充sigaction結構體成員act.sa_sigaction = handler;

這兩種呼叫方式在接下來的程式中都會實踐。這兩種中斷處理函式區別在於,乙個是不攜帶引數,乙個攜帶引數,並且儲存在siginfo_t結構體中,訊號處理函式可以解析這些資料。

接下來用乙個例子來講帶引數的訊號處理機制怎麼實現。

#include 

#include

#include

#include

#include

#include

#include

#include

int logflag = 0;//全域性變數,是否列印log的標誌

//訊號沒有帶引數時使用的中斷處理函式

void signal_handler(int signo)

}//訊號攜帶引數時使用的中斷處理函式

void signal_handler_param(int signo,siginfo_t *info,void *context)

return ;

}typedef

void (*pfunc)(int);

typedef

void (*psignalfunparam)(int, siginfo_t *, void *);

int signal_sigaction(int signo,void *func,int flag)

//將act的屬性sa_mask設定乙個初始值

sigemptyset(&act.sa_mask);

act.sa_flags=flag;

int ret = sigaction(signo,&act,&oact);

if (ret !=0 )

return ret;

}int main(int arg, char *args)

if(pid>0)//父程序

printf("recv signal from child\n");

}if(pid==0)//子程序

//傳送訊號sigusr2

if(sigqueue(getppid(),sigusr2,sigvalue)==-1)

printf("child process send signal successfully\n");

exit(0);

}return

0;}

編譯:

ubuntu:~/test/signal_test$ gcc 2signal.c -o 2signal
後台執行:

ubuntu:~/test/signal_test$ ./2signal &
實驗結果:

[1] 46814

ubuntu:~/test/signal_test$ in father!

in child!

child process send signal successfully

sigusr2 ,signo=12 , recv data :110

sigusr1 , signo=10 ,logflag = 1,recv data :110

kill傳送sigint訊號:

ubuntu:~/test/signal_test$ kill -int

46814

in signal_handler() sigint signal

從上面的程式和實驗結果理解程式的流程,先呼叫fork函式,建立子程序,子程序先睡眠兩秒等待父程序完成訊號的安裝,然後父程序呼叫pause函式,令目前的程序暫停(進入睡眠狀態), 直到被訊號(signal)所中斷,接著子程序向父程序傳送sigusr1,sigusr2的訊號,觸發了中斷,程序根據訊號的型別呼叫了不同的中斷處理函式。當傳送的是sigusr1和sigusr2訊號,會呼叫signal_handler_param函式,當傳送的是sigint訊號,則呼叫的是signal_handler。

Linux訊號機制 signal

linux下能夠通過訊號機制來實現程式的軟中斷。在程式執行的時候按下ctrl c ctrl z或者kill乙個程序的時候事實上都等效於向這個程序傳送了乙個特定訊號,當程序捕獲到訊號後,程序會被中斷並馬上跳轉到訊號處理函式。預設情況下乙個程式對ctrl c發出的訊號 sigint 的處理方式是退出程序...

Linux程序排程之訊號 signal 機制

訊號 signal 機制是unix系統中最為古老的程序間通訊機制,很多條件可以產生乙個訊號 1 當使用者按某些按鍵時,產生訊號 2 硬體異常產生訊號 除數為0 無效的儲存訪問等等。這些情況通常由硬體檢測到,將其通知核心,然後核心產生適當的訊號通知程序,例如,核心對正訪問乙個無效儲存區的程序產生乙個s...

Linux 訊號signal處理機制 四

4 alarm和 setitimer系統呼叫 系統呼叫alarm的功能是設定乙個定時器,當定時器計時到達時,將發出乙個訊號給程序。該呼叫的宣告格式如下 unsigned int alarm unsigned int seconds 在使用該呼叫的程序中加入以下標頭檔案 include 系 統呼叫al...