Linux和类Linux系统下进程间通信(Inter-Process Communication, IPC)有很多种方式
- 套接字(socket)
- 共享内存(shared memory)
- 管道(pipe)
- 消息队列(message queue)
信号,是Linux中向进程发送的消息,即通过软中断的方式来响应这个信号,触发一些事先指定或特定的事件。
进程之间可以互相通过系统调用kill来发送信号,内核也可以因为内部事件而给进程发送信号,通知进程。
1. linux定义的信号量
在/usr/include/x86_64-linux-gnu//bits/signum.h
下面
cat /usr/include/x86_64-linux-gnu//bits/signum.h
#ifndef _BITS_SIGNUM_H
#define _BITS_SIGNUM_H 1
#ifndef _SIGNAL_H
#error "Never include <bits/signum.h> directly; use <signal.h> instead."
#endif
#include <bits/signum-generic.h>
/* Adjustments and additions to the signal number constants for
most Linux systems. */
#define SIGSTKFLT 16 /* Stack fault (obsolete). */
#define SIGPWR 30 /* Power failure imminent. */
#undef SIGBUS
#define SIGBUS 7
#undef SIGUSR1
#define SIGUSR1 10
#undef SIGUSR2
#define SIGUSR2 12
#undef SIGCHLD
#define SIGCHLD 17
#undef SIGCONT
#define SIGCONT 18
#undef SIGSTOP
#define SIGSTOP 19
#undef SIGTSTP
#define SIGTSTP 20
#undef SIGURG
#define SIGURG 23
#undef SIGPOLL
#define SIGPOLL 29
#undef SIGSYS
#define SIGSYS 31
#undef __SIGRTMAX
#define __SIGRTMAX 64
#endif /* <signal.h> included. */
或者输入 kill -l
能够查看系统所支持的信号,每一个信号的名字都是以SIG开头
wanglei@wanglei-PC:~/ccode$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
2. 信号的简单使用
获取自身的Pid
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void);
2.1 使用sigset接收信号
函数原型
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t sigset(int sig,sighandler_t disp);
测试案例
#include <stdio.h>
#include <signal.h>
void handler();
int main(int argc, char ** argv)
{
sigset( SIGUSR1 , handler );
sigset( SIGUSR2 , handler );
printf( "Process_pid=[%d]\n", getpid() );
while(1);
return 0;
}
void handler(int signo)
{
switch(signo) {
case SIGUSR1: //处理信号 SIGUSR1
printf("SIGUSR1 received...\n");
break;
case SIGUSR2: //处理信号 SIGUSR2
printf("SIGUSR2 received...\n");
break;
default:
printf("Other signal...\n");
break;
}
}
然后使用kill命令
wanglei@wanglei-PC:~$ kill -USR1 7724
wanglei@wanglei-PC:~$ kill -USR2 7724
wanglei@wanglei-PC:~$ kill -10 7724
wanglei@wanglei-PC:~$ kill -12 7724
程序那边就会收到
wanglei@wanglei-PC:~/ccode$ ./a.out
Process_pid=[7724]
SIGUSR1 received...
SIGUSR2 received...
SIGUSR1 received...
SIGUSR2 received...
^C
2.2 使用signal接收信号
函数原型
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int)
关于参数
sig – 在信号处理程序中作为变量使用的信号码
宏 信号 SIGABRT (Signal Abort) 程序异常终止。 SIGFPE (Signal Floating-Point Exception) 算术运算出错,如除数为 0 或溢出(不一定是浮点运算)。 SIGILL (Signal Illegal Instruction) 非法函数映象,如非法指令,通常是由于代码中的某个变体或者尝试执行数据导致的。 SIGINT (Signal Interrupt) 中断信号,如 ctrl-C,通常由用户生成。 SIGSEGV (Signal Segmentation Violation) 非法访问存储器,如访问不存在的内存单元。 SIGTERM (Signal Terminate) 发送给本程序的终止请求信号。 func – 一个指向函数的指针。它可以是一个由程序定义的函数,也可以是预定义函数
函数 说明 SIG_IGN 忽视信号。 SIG_DFL 默认的信号处理程序。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
void sighandler(int);
int main()
{
signal(SIGINT, sighandler);
while(1)
{
printf("开始休眠一秒钟...\n");
sleep(1);
}
return(0);
}
void sighandler(int signum)
{
printf("捕获信号 %d,跳出...\n", signum);
exit(1);
}
另外开一个窗口,发送信号
wanglei@wanglei-PC:~$ kill -10 10603
wanglei@wanglei-PC:~$ kill -12 10654
程序那边
wanglei@wanglei-PC:~/ccode$ ./a.out
pid====>10603
开始休眠一秒钟...
开始休眠一秒钟...
开始休眠一秒钟...
用户定义信号 1
wanglei@wanglei-PC:~/ccode$ ./a.out
pid====>10654
开始休眠一秒钟...
开始休眠一秒钟...
用户定义信号 2
3. sigset 与 signal的区别
sigset 系统调用制定一个持久的信号处理函数,在信号发生时,不会被重置为默认处理动作。
signal 调用使用的是默认的信号处理函数处理了。