今天学习了进程间通信的第二种方式,使用信号进行通信。
一 信号类型
linux中共有31种信号类型,常见的几种信号类型如下所示:
SIGHUP:从终端上发出的结束信号
SIGINT:来自健盘的中断信号(ctrl+c)
SIGKILL:该信号结束接收信号的进程
SIGTERM: kill命令发出的信号
SIGCHLO:标识子进程停止或结束的信号
SIGSTOP:来自健盘(ctrl+z)或调试程序的停止执行信号
二 常见信号处理方式
当某信号出现时,通常会采用以下几种常见的处理方式:
1. 忽略此信号
大多数都是采用这种信号处理方式,但是有两种信号不能被忽略,SIGKILL SIGSTOP。
2.执行系统默认的动作
系统对于大多数信号采取的动作是终止该进程。
3.执行用户希望的动作
通知内核,当某种信号出现是,调用一个用户函数,在这个用户函数中,执行用户希望的动作。
三 信号发送函数
在linux中可以使用以下几个函数向某进程发送信号:
1. kill
int kill(pid_t pid, int signo)
pid参数为接受信号进程的pid,signo为需要发送信号的类型。
2. raise
int raise(int signo)
对比raise和kill函数的原型可以看出,kill能向所有进程发送信号,而raise只能向本进程发送信号。
3. kill命令
关于kill命令的使用方法,可以在终端里面执行man kill查看,在此略过。
4. alarm函数
unsigned int alarm(unsigned int seconds)
在seconds秒之后,会向本进程发送SIGARM信号
四 信号处理函数
当某种信号出现时,若希望能执行用户所希望的动作,则需要使用signal函数来制定信号处理函数。signal函数的函数原型为void*(signal(int signo, void*(func(int))))(int),函数原型看起来复杂,使用起来却比较简单,在后面会有例子。
func的可能的值如下:
1. SIG_IGN: 忽略此信号;
2. SIG_DFL: 按系统默认的动作去处理;
3. 信号处理函数名:使用该函数去处理。
此外,pause函数是使进程挂起,直至捕捉到一个信号,并且只有执行了一个信号处理函数之后,挂起才结束。
五 例子
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
void my_function(int signalno)
{
switch(signalno)
{
case SIGINT: printf("Catch a SIGINT signal\n");break;
case SIGQUIT: printf("Catch a SIGQUIT signal\n");break;
default: printf("error!\n");break;
}
}
int main(int args, char* argv[])
{
printf("Waiting for signal SIGINT OR SIGQUIT\n");
signal(SIGINT,my_function);
signal(SIGQUIT,my_function);
pause();
exit(0);
}
使用ps -aux查看本进程pid之后,再用kill命令发送信号:
kill -SIGQUIT 13253
运行结果如下:
Waiting for signal SIGINT OR SIGQUIT
Catch a SIGQUIT signal
欢迎关注新浪微博:ThreadX
共同学习,共同进步!