第15课-信号通讯编程
15.1 核心理论
1. 信号
在古老的战场上,信号是最有效,最直接的通讯方式;在linux系统中,信号(signal)同样也是最古老的进程间通讯机制。
2. 信号处理流程
进程A/内核---(1)选择信号-----(2)发送信号-----(3)处理信号----进程B。
3. 信号类型
Linux系统支持的所有信号均定义在/usr/include/asm/signal.h(展示),其中常见的信号有:
SIGKILL:杀死进程
SIGSTOP:暂停进程
SIGCHLD:子进程停止或结束时用来通知父进程
15.2 函数学习
1. 发送信号
(1)函数名
kill
(2)函数原形
int kill(pid_t pid,int sig);
(3)函数功能
向一个进程发送信号(send signal to a process)。
(4)所属头文件
#include<sys/types.h>
#include<signal.h>
(5)返回值
成功:0
失败:-1
(6)参数说明
pid:pid>0,pid参数指向接收信号的进程
sig:指明要发送的信号。
2. 处理信号
(1)函数名
signal
(2)函数原形
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
(3)函数功能
设置信号的处理方式(sets the disposition of the signal signum to handler)。
(4)所属头文件
#include<signal.h>
(5)返回值
成功:返回处理函数指针
失败:SIG_ERR
(6)参数说明
signum:要处理的信号
handler:函数指针,设置对应信号的处理方式。有三种取值:(1)SIG_IGN忽略这个信号不处理,(2)SIG_DFL交给系统去处理,(3)用户自定义的函数:交给用户自定义的函数来处理。
15.3 综合实例编程
A、B进程利用信号通讯。这里我们要一个新的函数pause,下面首先对它进行一个简单的介绍。
(1)函数名
pause
(2)函数原型
int pause(void);
(3)函数头文件
#include<unistd.h>
(4)函数功能
等待信号(wait for signal)
(5)返回值
成功:捕捉了信号返回-1
失败:EINTR
(6)参数
无
范例:
B进程,接收信号
#include<signal.h>
#include<unistd.h>
void myfuc(int a)
{
printf("Process B received SIGINT! ");
}
void main()
{
signal(SIGINT,myfuc);
pause();
}
当我们运行这段程序的时候,看到终端处于等待的状态。
我们先使用命令的方式,测试接收程序的实现。打开另一个终端首先输入:ps aux命令查看我们运行的改程序的进程,将序列号记住。然后输入命令:kill -n SIGINT 3637
我们会看到操作的起一个终端开始打印:Process B received SIGINT!
A进程,发出信号:
#include<signal.h>
#include<sys/types.h>
#include<stdio.h>
void main(int argc,char *argv[]) /*因为要把进程B的进程号传过来,我们要设置参数*/
{ /*argc表示信号个数,argv[]表示信号*/
pid_t pid;
pid = atoi(argv[1]); /*argv[0]是程序的名字,argv[1]是B进程的进程号*/
kill(pid,SIGINT);
}
注:pid的获取由命令行来获取,命令行传进来的是一个字符串,pid是个整数,用atoi函数将字符串转换成整数。
运行结果:先运行B进程,然后ps aux查看B进程的进程号(如3710),运行./ap 3710,在等待状态的B进程打印:Process B received SIGINT!