信号:进程与进程之间通讯机制
信号是软件中断
信号是异步事件
信号来源:内核产生,常用信号kill(),raise(),alarm(),settimer()等
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
查看linux所有 信号共64个 1-31 非实时信号发送信号可能回丢失,不支持信号排队
32-64实时信号
进程处理信号:
忽略信号
SIGKILL和SIGSTOP永远不能被忽略
忽略硬件异常
进程启动时SIGUSER1和SIGUSER2两个信号被忽略
执行默认操作
每个信号都有默认动作,大部分信号动作是终止信号
捕获信号
告诉信号内核出现信号是调用自己处理函数
SIGKILL和SIGSTOP不能被捕获
signal函数 信号注册函数 void (*signal(int signo,void(*func)(int)))(int); 参数 signo 要登记的信号值1-64 func 信号处理函数指针/忽略信号SIG_IGN/默认信号SIG_DEL 若成功返回信号处理函数指针,否则返回SIG_ERR
参数pid
pid > 0 指定进程id发送信号
pid ==0 发送进程同一进程组所有进程
pid <0 指定进程组pid发送信号
pid == -1 发送给进程有权限的所有进程
范列
#include <unistd.h> #include <stdlib.h> #include <signal.h> #include <stdio.h> void set_signal(int signo) { printf("pid: %d,signo: %d\n",getpid(),signo); } int main() { //SIGTSTP就是ctrl + z if(signal(SIGTSTP,set_signal) == SIG_ERR) { printf("set signal error"); } //ctrl+c if(signal(SIGINT,set_signal) == SIG_ERR) { printf("set signal error"); } int i=0; while(i<30) { printf("i : %d\n",i++); sleep(1); } return 0; }
SIGCHLD信号:子进程结束发送此信号给父进程回收资源
#include <unistd.h> #include <stdio.h> #include <sys/wait.h> #include <stdlib.h> void set_signal(int signo) { printf("%d signal %d\n",getpid(),signo); wait(0); } void out(int n) { int i=0; for (i;i<n;i++) { printf("%d is %d\n",getpid(),i); sleep(2); } } int main() { //注册信号函数 if(signal(SIGCHLD,set_signal) == SIG_ERR) { printf("set signal error\n"); return 1; } pid_t pid=fork(); if(pid <0) { printf("fork error\n"); return 1; } else if (pid >0) { //父进程 out(20); } else { //子进程 out(10); } }
进程间发送信号:
内核超级用户可以向其他进程发送信号
一般进程只能向相同uid,gid进程发送信号或者同进程组其他信号
常用发送信号函数kill(),raise(),alarm(),settimer(),abort()
#include <signal.h> int kill(pid_t pid,int signo) 成功返回0,出错返回-1 向进程发送信号 int raise(int signo) 成功返回0,出错发回-1 向自己发送信号,相当于kill(getpid(),signo)
unsigned int alarm(unsigned int seconds)
返回0或者以前设置定时器的余留秒数,定时器会发送一个SIGALRM 信号
alarm函数
#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> void set_signal(int signo) { printf("get signal %d\n",signo); alarm(5); } int main() { if(signal(SIGALRM,set_signal)==SIG_ERR) { printf("signal error\n"); return 1; } alarm(5); int i=0; for(i;i<20;i++) { printf("wait %d\n",i); sleep(2); } }