(一)发行版:Ubuntu16.04.7
(二)记录:
(1)信号通信
是进程通信的一张方式。
(2)常用信号通信类型
参考博客:
信号 信号值 程序默认行为 产生原因
SIGHUP 1 终止运行 终端线挂断
SIGINT 2 终止运行 来自键盘Ctrl + C的中断
SIGQUIT 3 终止运行 来自键盘Ctrl + \的退出
SIGILL 4 终止运行 进程尝试执行非法机器指令
SIGTRAP 5 终止运行并dump进程 跟踪陷阱
SIGABRT 6 终止运行并dump进程 来自abort()函数的终止信号
SIGBUS 7 终止运行 总线错误
SIGFPE 8 终止运行并dump进程 算术错误,例如尝试除以0
SIGKILL 9 终止运行 强制杀死进程,程序无法对该信号进行定制处理
SIGUSR1 10 终止运行 用户定义的信号1
SIGSEGV 11 终止运行并dump进程 段错误,程序访问了非法的地址,一般是由于程序本身BUG导致
SIGUSR2 12 终止运行 用户定义的信号2
SIGPIPE 13 终止运行 向一个没有读用户的管道做写入操作
SIGALRM 14 终止运行 来自alarm()函数的定时器信号
SIGTERM 15 终止运行 软件中止信号
SIGSTKFLT 16 终止运行 协处理器上的栈异常
SIGCHLD 17 忽略 一个子进程停止或者终止
SIGCONT 18 忽略 继续进程如果该进程停止
SIGSTOP 19 挂起当前进程直到SIGCONT 不是来自终端的停止信号
SIGTSTP 20 挂起当前进程直到SIGCONT 来自终端的停止信号
SIGTTIN 21 挂起当前进程直到SIGCONT 后台进程向终端读
SIGTTOU 22 挂起当前进程直到SIGCONT 后台进程向终端写
SIGURG 23 忽略 套接字上的紧急情况
SIGXCPU 24 终止运行 CPU时间限制超出
SIGXFSZ 25 终止运行 文件大小限制超出
SIGVTALRM 26 终止运行 虚拟定时器期满
SIGPROF 27 终止运行 剖析定时器期满
SIGWINCH 28 忽略 窗口大小变化
SIGIO 29 终止运行 在某个描述符上有可执行的IO操作
SIGIO 30 终止运行 电源故障
(3) Linux中的信号种类查询kill -l
(4) 信号发送函数kill、raise、alarm
kill:
头文件:#include<sys/types.h>
#include<signal.h>
函数原型:int kill(pid_t pid,int sig);
raise:(自己给自己发信号)
头文件:#include<signal.h>
函数原型:int raise(int sig);
raise函数等价于kill(getpid(),sig);
alarm:(定时产生信号:SIGALRM)
头文件:#include<unistd.h>
函数原型:unsigned int alarm(unsigned int seconds);
(5)raise函数编译运行
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
printf("I will give a signal:\n");
raise(SIGKILL); //终止运行
printf("signal is a.\n");
return 0;
}
(6)kill函数编译运行
新建一个test进程每两秒打印“I am running.”编写一个kill进程来杀死test进程
test.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
while(1)
{
printf("I am runnig\n");
sleep(2);
}
return 0;
}
kill.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
pid_t pid;
int signal;
if(argc != 3)
{
printf("error.\n");
return -1;
}
pid=atoi(argv[1]);
signal=atoi(argv[2]);
kill(pid,signal);
return 0;
}
a.编译生成可执行文件
b.由于我们在运行kill时需要输入pid号和信号,我们不知道test进程的pid号,所以先运行test使用ps aux | grep ./test查询
(7)alarm函数编译运行
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
int i=0;
alarm(10);
while(1)
{
i++;
printf("%d\n",i);
sleep(1);
}
return 0;
}
(8)防止进程结束的几种办法(比如等待接收信号)
while,sleep,pause
(9)信号的处理与signal函数
信号的处理方式:系统默认,忽略,捕获
signal函数:
头文件:<signal.h>
函数原型:
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum,sighandler_t handler);
可简化为signal(参数1,参数2);
参数1:我们要进行处理的信号,系统的信号我们可以再终端键入kill -l查看。
参数2:处理的方式(系统默认,忽略,捕获)
a.系统默认
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
int i=0;
//signal(SIGINT,SIG_IGN); //忽略
signal(SIGINT,SIG_DFL); //系统默认
while(1)
{
i++;
printf("%d\n",i);
sleep(1);
}
return 0;
}
可以被ctrl+c打断(SIGINT 2 终止运行 来自键盘Ctrl + C的中断)
b.忽略
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
int main(int argc,char *argv[])
{
int i=0;
signal(SIGINT,SIG_IGN); //忽略
//signal(SIGINT,SIG_DFL); //系统默认
while(1)
{
i++;
printf("%d\n",i);
sleep(1);
}
return 0;
}
ctrl+c无法打断进程,kill -2 3630也无法打断(2信号已经被忽略)
使用9信号即可kill进程。
c.捕获
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
void WaitCC(int sig)
{
if(sig==SIGINT)
printf("get signal.\n");
}
int main(int argc,char *argv[])
{
int i=0;
//signal(SIGINT,SIG_IGN); //忽略
//signal(SIGINT,SIG_DFL); //系统默认
signal(SIGINT,WaitCC);
while(1)
{
i++;
printf("%d\n",i);
sleep(1);
}
return 0;
}
(三)命令: