linux中进程间通信,简称IPC。主要存在以下几种方式:
- 管道、FIFO(有名管道);
- 消息队列;
- 共享内存;
- 信号量;
- 信号;
- 套接字(主要是用于不同机器之间的通信);
这次,先看看比较常见的信号方式。linux支持的信号可以通过kill命令来查看。
查看一下linux支持的信号种类如下:
一共支持64种信号。
信号的产生,一般来说分为两大类,分别是软件中断和硬件中断。比较常见的一个例子就是C-c组合键用来停止当前正在运行的进程。前面,做练习用到的除零操作也是其中的一个例子。除此之外,还有一些跟我现在熟悉的嵌入式的系统有一定雷同性的就是非法存储区的 ,比如访问了不存在的存储空间等。
对于信号的处理,主要有3种方式。在说明之前,可以先看看signal函数。
#include <signal.h>
typedef void (*sighandler_t)(int);
sighandler_t signal(int signum, sighandler_t handler);
使用signal函数,需要包含signal.h的库函数声明文件。这个函数的作用是为当前的进程注册信号以及信号处理函数。第一个参数中的信号编号,就是前面截图中1~64的编号,而处理函数则有三种可能:
- 用户自定义的函数,这种方式意味着要去捕捉这个信号;
- 忽略,不处理,周三是信号处理的一个常见方式,参数填SIG_IGN;
- 采用系统默认的行为;,参数填SIG_DFL;
关于系统的默认行为,主要有以下几种情况:
- 结束进程(Term)
- 忽略信号(Ignore)
- 结束进程并生成核心转储文件(Core),该文件用于gdb后期调试
- 暂停进程(Stop)
- 继续进程(Continue),如果进程被挂起,则恢复进程的运行。否则,忽略该信号
接下来,通过一个例子做一个简单的探索。
首先设计了一个信号的处理函数。
接下来,是测试程序。
软件编译运行:
查看该进程的PID。
pid应该是7733。
接下来,给这个进程发送两个处理函数中可以识别的信号。两个信号的编号分别如下:
测试效果:
接下来,测试一下Ctrl-C是否可以终止。
看的出,这个是终止不掉的,因为这个处理函数被注册成了我们自己的用户函数。而9号信号,也就是杀进程用的信号是无法屏蔽掉的,接下来做一个测试。
测试效果:
成功杀死了这个进程。