信號是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)