信号分类 信号分为可靠信号和不可靠信号 不可靠信号的缺点 ①:处理完信号,需要重新再注册信号;②信号可能丢失。 Linux已经对缺点①做了优化,现在的不可靠问题主要指的是信号可能丢失 信号还可以分为实时信号和非实时信号--一般不可靠信号指的是前32种信号,这32种信号已经有了预定义值,每个信号有了确定的用途及含义,并且每种信号都有各自的缺省动作 --可靠信号指的后32种信号 --非实时信号都不支持排队,都是不可靠信号;实时信号都支持排队,都是可靠信号。
信号处理 进程对信号的三种响应 1.忽略信号 --不采取任何操作,有两个信号不能被忽略:SIGKILL(9号信号)和SIGSTOP。 --如果进程可以忽略这两个信号,系统管理无法杀死,暂停进程,无法对系统进行管理。 --SIGKILL(9号信号)和SIGSTOP信号是不能被捕获的 2.捕获并处理信号 --内核终端正在执行的代码,转去执行先前注册过的处理程序 3.执行默认操作 --默认操作通常是终止进程,这取决于被发送的信号
信号发送
发送信号的函数有kill和raise
区别:kill既可以向自身发送信号,也可以向其他进程发送信号
raise函数向进程自身发送信号
int kill(oid_t pid,int sig) 参数组合解释 pid>0 将信号sig发给pid进程 pid=0 将信号sig发给组进程 pid=-1 将信号sig发送给所有进程,调用者进程有权限发送的每一个进程(除了1号进程之外,还有它自身) pid<-1 将信号sig发送给进程组pid(绝对值)的每一个进程
//kill 函数 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <sys/types.h> #include <sys/wait.h> #include <signal.h> void catch_signal(int sign) { switch(sign) { case SIGINT: printf("accept signal!\n"); break; default: break; } } int main(int arg,char *args[]) { //注册信号 if(signal(SIGINT,catch_signal)==SIG_ERR) { perror("signal error"); return-1; } //注意:如果在fork之前安装信号,子进程会继承信号 pid_t pid=0; pid=fork(); if(pid==-1) { printf("fork() failed ! error message:%s\n",strerror(errno)); return -1; } if(pid==0) { printf("child runing!\n"); //kill(getppid(),SIGINT);//向父进程发送信号 kill(0,SIGINT);//向进程组内所有进程发送信号(父子进程在同一个进程组中) //getpgrp()获取进程组的pid,此处进程组ID就是父进程的pid /*killpg向一个进程组所有进程发送信号,第一个参数是进程组组长ID*/ killpg(getpgrp(),SIGINT); exit(0); } printf("parent is runing!\n"); //等待子进程 int status=0,ret=0; while(1) { ret=wait(&status); if(ret==-1) { if(errno==EINTR) { continue; } break; } } printf("game over!\n"); return 0; }