上一節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...