信号(对于Linux来说,实际信号就是软中断)
-
信号的名字和编号:每个信号都有一个名字和编号,这些名字都以“SIG开头”,例如"SIGIO"、“SIGCHLD”等等
-
信号定义在signal.h头文件中,信号名都定义为整数
-
具体的信号名称都已使用kill -l来查看信号的名字以及序号,信号是从1开始编号的,不存在0号信号。kill对于信号0有特殊的应用
-
kill命令:发送信号
- kill 信号编码或是信号名字 进程ID
-
信号的意义不是为了杀死进程,而是实现一些异步通信的手段
-
信号的处理:有三种方法,分别是:忽略、捕捉和默认
-
忽略:不用响应。(注意:SIGKILL和SIGSTOP这两个信号是不能被忽略的)
-
捕捉:当该信号产生时,由内核来调用用户自定义的函数,以实现某种信号的处理(修改了默认动作:如Ctrl+c为终止进程信号,但是捕捉到的信号来去处理别的函数的时候,默认动作(终止进程就不会执行了))
-
默认:对于每个信号来说,系统都对应默认的处理动作,当发生了该信号,系统会自动执行
-
-
信号处理函数的注册(接收信号)
-
入门:函数signal
-
#include<signal.h> #include<stdio.h> //typedef void (*sighandler_t)(int); //sighandler_t signal(int signum,sighanler_t handler); void handler(int signum) { printf("get signum=%d\n",signum); switch(signum){//捕抓相应信号去修改其功能(执行别的任务) case 2: printf("SIGINT\n"); break; case 9: printf("SIGKILL\n");//SIGKILL是不能被修改的,进程收到这个信号直接被杀死 break; case 10: printf("SIGUSR1\n"); break; } } int main() { signal(SIGINT,handler); signal(SIGKILL,handler); signal(SIGUSR1,handler); signal(SIGPIPE,SIG_IGN);//SIG_IGN是一个宏,可以忽略信号 while(1); return 0; }
-
-
高级:函数sigaction(可以从信号读出信息)
-
#include<signal.h> #include<stdio.h> #include<sys/types.h> #include<unistd.h> /*struct sigaction { void (*sa_handler)(int); void (*sa_sigaction)(int, siginfo_t *, void *); sigset_t sa_mask; int sa_flags; void (*sa_restorer)(void); };*/ //int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact); void handler(int signum, siginfo_t *info, void *context) { printf("get signum %d\n",signum); if(context != NULL){ printf("get data=%d\n",info->si_int);//信息都在sigset_t结构体里 printf("From=%d\n",info->si_pid); } } int main() { struct sigaction act; printf("Receve:%d\n",getpid()); act.sa_sigaction = handler; act.sa_flags = SA_SIGINFO;//配置为SA_SIGINFO能够获取信息 sigaction(SIGUSR1,&act,NULL); while(1); return 0; }
-
-
-
信号处理发送函数
-
入门:kill
-
#include <stdio.h> #include <stdlib.h> int main(int argc,char **argv) { int pid; int signal; char cmd [128]={0}; if(argc != 4){ printf("argc error\n"); return -1; } signal=atol(argv[2]); pid=atol(argv[3]); sprintf(cmd,"kill %d %d",signal,pid); printf("cmd=%s\n",cmd); system(cmd); return 0; }
-
假如如上代码生成signal_kill.out程序 命令行输入:./signal_kill.out -信号编号 进程ID号 如:./signal_kill.out -9 4739 (即可对ID为4739的进程发送编号为9的信号)
-
-
高级版:sigqueue(可以让信号携带信息)(配合上面那个sigaction使用)
-
#include <stdio.h> #include <signal.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> int main(int argc,char **argv) { int signum; int pid; signum = atoi(argv[1]); pid = atoi(argv[2]); union sigval value; value.sival_int=100;//携带的信息 printf("Send=%d\n",getpid()); sigqueue(pid,signum,value); printf("done\n"); return 0; }
-
-
补充
-
查找进程ID
- ps -aux|grep 进程名
-
查看进程类型
- kill -l