进程间通信的方式
1. 进程间通信的几种方式
-  管道 比如 ls | grep 1;也就是将 进程 ls 拿到的结果作为 grep 1 这个进程的输入。实现了进程间的通信。 
-  消息队列 消息队列就是我们的内核给我们创建的一种消息队列。我们可以往其中发送消息,也可以从其中接收消息。 
-  共享内存 每个进程在访问内存的时候,会有虚拟内存地址和物理内存地址的一个映射。一般来说,俩个进程的虚拟内存地址可以是一样的,但是它们映射的物理内存地址是不一样的。共享内存就是将俩个进程的内存地址也是一样的。这个时候,俩个进程就可以访问共同的物理内存,实现通信。 
-  套接字 比如访问数据库的进程和数据库进程本身之间的通信。 
-  信号 信号就是说一个进程在运行的时候可以向另外的一个进程发送信号。 
 可以通过 kill -l 指令可以列举出所有的信号指令。kill 和信号有什么关系呢?linux 的信号大多数都是将一个进程杀死。
2. 进程间通过信号进行通信的几个例子
-  比如说使用命令 tail -f 1.txt, 运行了这个命令以后,这个进程会一直存在。那么怎么终止呢? ctrl + c, 就可以终止这个进程。其实这时候就是shell 终端进程向 运行的这个进程发送了一个 信号,这个信号的值其实是 SIGINT。 
-  比如说使用命令 tail -f 1.txt, 运行了这个命令以后,这个进程会一直存在。那么怎么终止呢?还可以通过 kill + 进程号。其实这时候就是shell 终端进程向 运行的这个进程发送了一个 信号,这个信号的值其实是 Terminated。 
-  比如说使用命令 tail -f 1.txt, 运行了这个命令以后,这个进程会一直存在。那么怎么终止呢?还可以通过 kill -9 + 进程号。其实这时候就是shell 终端进程向 运行的这个进程发送了 9号 信号,这个信号的值其实是 Killed。 
3. 通过程序捕获信号
通过在程序中捕获信号,比如说,我们运行了一个java程序,但是我们想做到 ctrl + c , 和 kill + 进程号
 ,都不能终止这个进程,那么我们就可以捕获相应的信号。
- 程序如下:
package org.example;
import sun.misc.Signal;
import sun.misc.SignalHandler;
public class Main {
    public static void main(String[] args) throws InterruptedException {
        // 注册信号的处理。捕获 SIGINT 信号的处理。
        Signal.handle(new Signal("INT"), new SignalHandler() {
            @Override
            public void handle(Signal signal) {
                System.out.println(signal.toString() + "catched");
            }
        });
        // 循环打印123
        while (true) {
            Thread.sleep(1000);
            System.out.println(123);
        }
    }
}
-  通过 javac 命令编译这个程序 
  
-  通过 java 命令运行这个程序 可以看到控制台打印了如下内容,并且通过ctrl + c不能终止这个进程 
  
-  通过 kill + 进程号 终止这个进程。注意: Killed 这个信号是无法被捕获的,执行了 kill -9 ,那么这个进程必须被强制杀死。 
  


















![2022年 大学生工程训练比赛[物料搬运]](https://img-blog.csdnimg.cn/6bf79a143bca48338c8da0d5f58c3cb7.jpeg)
